From 90d8ddc6167c83bb55490cdeec9020227c2adf0b Mon Sep 17 00:00:00 2001 From: Luan Yuan Date: Tue, 30 Apr 2019 19:05:19 +0800 Subject: [PATCH] common: support tp CST226 for yeke [1/1] PD#SWPL-8013 Problem: support touchpanel CST226 for yeke. Solution: support touchpanel CST226 for yeke. Verify: verify by u202. Change-Id: Id74df3e25761118db4c10706128df29eb6eb2894 Signed-off-by: Luan Yuan dts: add touch screen dts config for CST226 [1/1] PD#SWPL-8013 Problem: separate dts config from driver Solution: separate dts config from driver Verify: verify by u202 Change-Id: I4de45ec213b86d12cdd9296f80de62f4f2dc6713 Signed-off-by: GongWei Chen Signed-off-by: Luan Yuan --- .../bindings/input/touchscreen/hyn,cst226.txt | 29 + .../devicetree/bindings/vendor-prefixes.txt | 1 + MAINTAINERS | 4 + arch/arm/boot/dts/amlogic/g12a_s905d2_u202.dts | 8 + arch/arm/boot/dts/amlogic/g12a_s905d2_u202_1g.dts | 8 + arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts | 8 + arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts | 8 + arch/arm/configs/meson64_a32_defconfig | 1 + arch/arm64/boot/dts/amlogic/g12a_s905d2_u202.dts | 8 + .../arm64/boot/dts/amlogic/g12a_s905d2_u202_1g.dts | 8 + arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts | 8 + .../arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts | 8 + arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/input/touchscreen/Kconfig | 6 + drivers/amlogic/input/touchscreen/Makefile | 1 + .../amlogic/input/touchscreen/hyn_cst2xx/Kconfig | 10 + .../amlogic/input/touchscreen/hyn_cst2xx/Makefile | 7 + .../input/touchscreen/hyn_cst2xx/cst226firmware.h | 526 ++++++++ .../input/touchscreen/hyn_cst2xx/hyncst226.c | 1318 ++++++++++++++++++++ 19 files changed, 1968 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hyn,cst226.txt create mode 100644 drivers/amlogic/input/touchscreen/hyn_cst2xx/Kconfig create mode 100644 drivers/amlogic/input/touchscreen/hyn_cst2xx/Makefile create mode 100644 drivers/amlogic/input/touchscreen/hyn_cst2xx/cst226firmware.h create mode 100644 drivers/amlogic/input/touchscreen/hyn_cst2xx/hyncst226.c diff --git a/Documentation/devicetree/bindings/input/touchscreen/hyn,cst226.txt b/Documentation/devicetree/bindings/input/touchscreen/hyn,cst226.txt new file mode 100644 index 0000000..76425a6 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/hyn,cst226.txt @@ -0,0 +1,29 @@ +* Neonode infrared touchscreen controller + +Required properties: +- compatible: must be "hyn,cst226" +- reg: I2C address of the chip +- interrupts: interrupt to which the chip is connected +- reset-gpios: reset gpio the chip is connected to +- x-size: horizontal resolution of touchscreen +- y-size: vertical resolution of touchscreen + +Optional properties: +- irq-gpios : interrupt gpio the chip is connected to +- vdd-supply: Regulator controlling the controller supply + +Example: + + i2c@00000000 { + /* ... */ + + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + + /* ... */ + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 3e09d25..8a410b8 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -322,3 +322,4 @@ zii Zodiac Inflight Innovations zte ZTE Corp. zyxel ZyXEL Communications Corp. rohm +hyn hyn diff --git a/MAINTAINERS b/MAINTAINERS index 45487be..5c9389e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14844,3 +14844,7 @@ F: include/linux/amlogic/media/mipi/* AMLOGIC SM1 S905D3 AC202 M: LUAN YUAN F: arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202* + +AMLOGIC HYN_CST2XX TOUCHSCREEN +M: XINLIANG ZHANG +F: drivers/amlogic/input/touchscreen/hyn_cst2xx/* diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u202.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u202.dts index ec91db29..89cddc8 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u202.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u202.dts @@ -1029,6 +1029,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm/boot/dts/amlogic/g12a_s905d2_u202_1g.dts b/arch/arm/boot/dts/amlogic/g12a_s905d2_u202_1g.dts index 91895f5..89f10e6 100644 --- a/arch/arm/boot/dts/amlogic/g12a_s905d2_u202_1g.dts +++ b/arch/arm/boot/dts/amlogic/g12a_s905d2_u202_1g.dts @@ -873,6 +873,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts index acd77ac..b4c97f4 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202.dts @@ -1092,6 +1092,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts index e8ffe1d..1fbfb81 100644 --- a/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts +++ b/arch/arm/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts @@ -1092,6 +1092,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm/configs/meson64_a32_defconfig b/arch/arm/configs/meson64_a32_defconfig index 8753a0f..27857d8 100644 --- a/arch/arm/configs/meson64_a32_defconfig +++ b/arch/arm/configs/meson64_a32_defconfig @@ -261,6 +261,7 @@ CONFIG_AMLOGIC_TOUCHSCREEN=y CONFIG_AMLOGIC_TOUCHSCREEN_FTS=y CONFIG_AMLOGIC_TOUCHSCREEN_GT1X=y CONFIG_AMLOGIC_TOUCHSCREEN_GT9XX=y +CONFIG_AMLOGIC_TOUCHSCREEN_HYN_CST2XX=y CONFIG_AMLOGIC_EFUSE=y CONFIG_AMLOGIC_REBOOT=y CONFIG_AMLOGIC_GX_REBOOT=y diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202.dts index e6aa019..0cf0177 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202.dts @@ -1028,6 +1028,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202_1g.dts b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202_1g.dts index 781463b..84d3d5b 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202_1g.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_s905d2_u202_1g.dts @@ -867,6 +867,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts index 04d6cad..e6c7d24 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202.dts @@ -1091,6 +1091,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts index 7314024..ea75088 100644 --- a/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts +++ b/arch/arm64/boot/dts/amlogic/sm1_s905d3_ac202_1g.dts @@ -1091,6 +1091,14 @@ pinctrl-0=<&i2c3_master_pins2>; clock-frequency = <100000>; /* default 100k */ + hyn@1A { + compatible = "hyn,cst226"; + status = "okay"; + reg = <0x1a>; + reset-gpio = <&gpio GPIOA_5 0x00>; + irq-gpio = <&gpio GPIOA_6 0x00>; + }; + /* for ref board */ ad82584f_62: ad82584f_62@62 { compatible = "ESMT, ad82584f"; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 03d9fcf..c9753e4 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -255,6 +255,7 @@ CONFIG_AMLOGIC_TOUCHSCREEN=y CONFIG_AMLOGIC_TOUCHSCREEN_FTS=y CONFIG_AMLOGIC_TOUCHSCREEN_GT1X=y CONFIG_AMLOGIC_TOUCHSCREEN_GT9XX=y +CONFIG_AMLOGIC_TOUCHSCREEN_HYN_CST2XX=y CONFIG_AMLOGIC_EFUSE=y CONFIG_AMLOGIC_REBOOT=y CONFIG_AMLOGIC_GX_REBOOT=y diff --git a/drivers/amlogic/input/touchscreen/Kconfig b/drivers/amlogic/input/touchscreen/Kconfig index 912a54f..e0bcabf 100644 --- a/drivers/amlogic/input/touchscreen/Kconfig +++ b/drivers/amlogic/input/touchscreen/Kconfig @@ -32,4 +32,10 @@ config AMLOGIC_TOUCHSCREEN_GT9XX help Say Y here if you want to use the Goodix gt9xx. +config AMLOGIC_TOUCHSCREEN_HYN_CST2XX + tristate "hyn cst2xx touch driver support" + depends on I2C + default n + help + Say Y here if you want to use the hyn cst2xx. endif diff --git a/drivers/amlogic/input/touchscreen/Makefile b/drivers/amlogic/input/touchscreen/Makefile index 44c27f8..7352670 100644 --- a/drivers/amlogic/input/touchscreen/Makefile +++ b/drivers/amlogic/input/touchscreen/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_FTS) += focaltech_touch/ obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_GT1X) += goodix_gt1x/ obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_GT9XX) += goodix_gt9xx/ +obj-$(CONFIG_AMLOGIC_TOUCHSCREEN_HYN_CST2XX) += hyn_cst2xx/ diff --git a/drivers/amlogic/input/touchscreen/hyn_cst2xx/Kconfig b/drivers/amlogic/input/touchscreen/hyn_cst2xx/Kconfig new file mode 100644 index 0000000..bd23841 --- /dev/null +++ b/drivers/amlogic/input/touchscreen/hyn_cst2xx/Kconfig @@ -0,0 +1,10 @@ +# +# Touchscreen driver configuration +# + +config TOUCHSCREEN_HYN_CST2XX + tristate "hyn_CST2XX touchscreen driver" + depends on INPUT && I2C + default m + help + hyn_CST2XX touchscreen driver diff --git a/drivers/amlogic/input/touchscreen/hyn_cst2xx/Makefile b/drivers/amlogic/input/touchscreen/hyn_cst2xx/Makefile new file mode 100644 index 0000000..c2f3764 --- /dev/null +++ b/drivers/amlogic/input/touchscreen/hyn_cst2xx/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the touchscreen drivers. +# + +# Each configuration option enables a list of files. + +obj-y += hyncst226.o \ No newline at end of file diff --git a/drivers/amlogic/input/touchscreen/hyn_cst2xx/cst226firmware.h b/drivers/amlogic/input/touchscreen/hyn_cst2xx/cst226firmware.h new file mode 100644 index 0000000..8c57ab2 --- /dev/null +++ b/drivers/amlogic/input/touchscreen/hyn_cst2xx/cst226firmware.h @@ -0,0 +1,526 @@ + +#ifndef __CST2xx_FW_H__ +#define __CST2xx_FW_H__ + +unsigned char fwbin[] = { + 0xA8, 0xC5, 0x77, 0xA2, 0x25, 0x01, 0x00, 0xA3, 0x46, 0x9A, 0x18, 0x23, + 0xBE, 0xFF, 0xFF, 0xE7, 0x40, 0x01, 0x88, 0x06, 0x38, 0xF7, 0x47, 0x8A, + 0x18, 0x23, 0x80, 0x07, 0xC8, 0xA7, 0x61, 0x7A, 0x42, 0x7A, 0xA0, 0x01, + 0x01, 0x03, 0x37, 0x2A, 0xE8, 0x01, 0x39, 0x09, 0xE8, 0x43, 0x45, 0x01, + 0x80, 0x66, 0x40, 0x31, 0x89, 0xD6, 0x47, 0x8B, 0x59, 0x03, 0x83, 0x01, + 0xC9, 0x13, 0x34, 0xC2, 0x04, 0x82, 0x1C, 0x0A, 0x07, 0x8B, 0xB9, 0xFF, + 0xFF, 0x3F, 0x3E, 0x7F, 0x83, 0x07, 0xC8, 0x5F, 0x38, 0x67, 0x07, 0x00, + 0xF8, 0x00, 0x06, 0x42, 0x78, 0x00, 0x06, 0x01, 0x78, 0x00, 0x03, 0x01, + 0x60, 0x9B, 0x04, 0x00, 0xAE, 0xC5, 0x47, 0xC2, 0xE8, 0x03, 0x44, 0x01, + 0x87, 0x1E, 0xB8, 0xFF, 0xF8, 0xFF, 0x44, 0x01, 0x89, 0x16, 0x02, 0x89, + 0x4C, 0xAA, 0x0E, 0x00, 0x58, 0x92, 0xC6, 0x60, 0x07, 0x79, 0xD9, 0x01, + 0x0A, 0x00, 0x34, 0xE9, 0xC8, 0xD3, 0xC6, 0x40, 0x0E, 0xB0, 0x6B, 0x7A, + 0xC8, 0x48, 0x54, 0x01, 0x8B, 0x56, 0x58, 0x3B, 0x31, 0xD2, 0x90, 0x01, + 0xBC, 0x01, 0xF9, 0xB3, 0xD5, 0xFB, 0x11, 0xF2, 0x98, 0x3E, 0xF0, 0x93, + 0x30, 0x90, 0xA8, 0x26, 0x55, 0x32, 0xD6, 0x01, 0xD0, 0x93, 0x50, 0x01, + 0x80, 0x1E, 0xF9, 0x53, 0x50, 0xA9, 0x82, 0x2E, 0xFA, 0x53, 0x54, 0xA9, + 0x8A, 0xE6, 0xC0, 0xD3, 0x50, 0x31, 0x88, 0xCE, 0x14, 0x01, 0xB8, 0x53, + 0xB8, 0x53, 0xA0, 0x13, 0x0C, 0x59, 0xAD, 0x0B, 0xA9, 0x13, 0x42, 0x43, + 0x58, 0x0B, 0x33, 0x09, 0x8C, 0x01, 0xC9, 0x53, 0x34, 0x8A, 0x01, 0x8A, + 0x19, 0x42, 0x04, 0x43, 0x07, 0x41, 0xB9, 0xF7, 0xE1, 0x9F, 0x40, 0x4B, + 0x59, 0x03, 0x83, 0x01, 0xCC, 0x03, 0x04, 0x32, 0x19, 0x8A, 0x01, 0x4B, + 0xEA, 0xC5, 0x17, 0xA9, 0xB9, 0x53, 0x44, 0x53, 0x58, 0x0B, 0x33, 0x09, + 0x8C, 0x01, 0xC9, 0x5B, 0x34, 0x8A, 0x01, 0xCA, 0x19, 0x52, 0x00, 0x53, + 0x0D, 0x01, 0x50, 0x7A, 0xE5, 0x1B, 0x58, 0x59, 0x88, 0x0E, 0xE0, 0x03, + 0x02, 0x1F, 0xE0, 0x48, 0x94, 0x4D, 0x14, 0x8A, 0x9F, 0xB6, 0xBF, 0xFF, + 0xF9, 0x2F, 0x42, 0x4B, 0x59, 0x03, 0x83, 0x01, 0xC9, 0x13, 0x34, 0x82, + 0x04, 0x82, 0x1C, 0x0A, 0x01, 0x4B, 0x01, 0x41, 0xBF, 0xF7, 0xDF, 0x47, + 0x43, 0x4B, 0x59, 0x03, 0x84, 0x01, 0xC9, 0x03, 0x01, 0x32, 0x1C, 0x8A, + 0x07, 0x4B, 0xE9, 0xC5, 0xAC, 0x85, 0x41, 0xE2, 0xE8, 0x0B, 0x4C, 0x01, + 0x8E, 0x4E, 0xF8, 0x08, 0xCE, 0xC9, 0xFF, 0x4B, 0x48, 0x29, 0xC8, 0x26, + 0x01, 0x07, 0xF8, 0x85, 0xC0, 0x0B, 0x4A, 0x01, 0x80, 0xDE, 0xEF, 0x0B, + 0x38, 0x48, 0xA8, 0xAE, 0x60, 0xBA, 0x1C, 0x09, 0x1C, 0x1B, 0x55, 0xBA, + 0x40, 0x8B, 0x28, 0x41, 0x18, 0x4A, 0x01, 0x8B, 0xEF, 0x0B, 0x10, 0x79, + 0x00, 0x8A, 0xA8, 0x0B, 0x01, 0x07, 0xF8, 0x85, 0xEE, 0x0B, 0x30, 0x48, + 0xA8, 0xDE, 0x0F, 0x01, 0x18, 0x0B, 0xED, 0x0B, 0x18, 0xCA, 0xA8, 0x0B, + 0x4B, 0x42, 0xCC, 0x01, 0x42, 0x43, 0xE4, 0x00, 0x00, 0x43, 0x74, 0x10, + 0x8C, 0x01, 0xB2, 0x53, 0x62, 0x10, 0xB0, 0x53, 0x50, 0x10, 0xB0, 0x53, + 0xA9, 0x43, 0xEE, 0x85, 0x39, 0x82, 0xAB, 0x85, 0x40, 0x0A, 0x44, 0x23, + 0x48, 0xFA, 0x13, 0x09, 0x8A, 0x01, 0x59, 0x4B, 0x31, 0x9A, 0x88, 0x01, + 0xCD, 0x6B, 0x04, 0x5A, 0x18, 0xE2, 0x04, 0x23, 0x44, 0x1B, 0xCE, 0x6B, + 0x35, 0xA2, 0x00, 0x62, 0x1E, 0x1A, 0x01, 0x1B, 0x4C, 0x1B, 0xCA, 0x6B, + 0x35, 0xA2, 0x00, 0x62, 0x1A, 0x1A, 0x0D, 0x1B, 0x4C, 0x1B, 0xC8, 0x4B, + 0x04, 0x52, 0x1C, 0x9A, 0x09, 0x1B, 0xE8, 0x85, 0xAB, 0xC5, 0x47, 0x8A, + 0x82, 0x01, 0x59, 0x03, 0xCE, 0x2B, 0xC0, 0x03, 0x80, 0x04, 0x30, 0x01, + 0x00, 0xAF, 0x01, 0x01, 0x09, 0x01, 0x30, 0x92, 0x1A, 0x52, 0x03, 0x98, + 0x54, 0x62, 0xC3, 0xD8, 0x54, 0x7A, 0xC3, 0xD0, 0x30, 0xA2, 0x18, 0x01, + 0x00, 0x3F, 0x40, 0xBC, 0xC0, 0xC0, 0x91, 0x05, 0xE0, 0x48, 0x92, 0x4D, + 0xE2, 0x90, 0xE4, 0xD8, 0x95, 0xDD, 0x16, 0x5A, 0x9F, 0xAE, 0xBF, 0xFF, + 0xE8, 0x2F, 0x92, 0x05, 0x08, 0x01, 0x00, 0xB7, 0x40, 0x01, 0xE8, 0x5E, + 0x15, 0x01, 0xF0, 0x12, 0x10, 0x12, 0xDC, 0x16, 0xD1, 0x90, 0x00, 0x14, + 0x00, 0x57, 0x50, 0x01, 0xE8, 0x46, 0x10, 0x09, 0x00, 0x14, 0x01, 0x2F, + 0x15, 0x01, 0xF0, 0x12, 0x10, 0x12, 0xE4, 0x0E, 0xD1, 0x90, 0x00, 0x14, + 0xE2, 0x20, 0xE5, 0x48, 0x95, 0x4D, 0x16, 0x4A, 0x9B, 0x36, 0xE7, 0xB0, + 0x90, 0xB5, 0xC7, 0x04, 0x16, 0x32, 0x9C, 0x36, 0xEB, 0xC5, 0xAF, 0x85, + 0x02, 0x01, 0x28, 0xE9, 0x08, 0x68, 0x0B, 0x01, 0x51, 0x7A, 0x1A, 0x79, + 0x08, 0xD8, 0xC4, 0xA0, 0xC9, 0x20, 0xB3, 0x0B, 0x40, 0x21, 0x90, 0x1E, + 0x05, 0x20, 0xC2, 0x20, 0xC1, 0x20, 0x07, 0x0C, 0x40, 0x11, 0x90, 0x1E, + 0x05, 0x20, 0xC4, 0x20, 0xC5, 0x20, 0x07, 0x0B, 0xE6, 0x00, 0x92, 0x05, + 0x47, 0x41, 0x98, 0x66, 0x41, 0x12, 0xC2, 0x01, 0xF8, 0x13, 0x30, 0x1A, + 0xDA, 0x01, 0xB3, 0xD3, 0x55, 0x32, 0x9A, 0x01, 0x18, 0xD3, 0x32, 0x12, + 0x64, 0x2A, 0xD2, 0x01, 0x12, 0xA3, 0x62, 0x2A, 0x12, 0xA3, 0x64, 0x2A, + 0x12, 0xA3, 0x66, 0x2A, 0x1A, 0xA3, 0x60, 0x2A, 0x18, 0xA3, 0x12, 0x09, + 0xBC, 0x13, 0xBA, 0x0B, 0xBF, 0x13, 0x26, 0x11, 0xBE, 0x23, 0xB0, 0x0B, + 0xB2, 0x13, 0xB4, 0x13, 0x44, 0x02, 0x02, 0xC3, 0x86, 0x07, 0xD8, 0x5F, + 0x86, 0x07, 0xD8, 0xBF, 0xB8, 0xFF, 0xF7, 0x87, 0xB8, 0xFF, 0xF7, 0x97, + 0x07, 0xE1, 0xB9, 0xFF, 0xF7, 0xFF, 0xBA, 0xFF, 0xF0, 0x8F, 0x00, 0x19, + 0x84, 0x07, 0xD8, 0x67, 0xBA, 0xFF, 0xFF, 0x8F, 0x85, 0x07, 0xD8, 0x2F, + 0xEB, 0x85, 0xAB, 0x85, 0x61, 0x3A, 0xE9, 0x03, 0x08, 0x09, 0x18, 0x42, + 0xA9, 0x03, 0x31, 0x2A, 0xAA, 0x01, 0x01, 0x1F, 0xBE, 0xFF, 0xEF, 0x57, + 0xBE, 0xFF, 0xEF, 0x67, 0xEE, 0x03, 0x39, 0x00, 0x81, 0x36, 0x00, 0xE1, + 0xBA, 0xFF, 0xF7, 0x17, 0x4A, 0xF2, 0x00, 0xA9, 0xC8, 0x01, 0xBC, 0x43, + 0xBE, 0xFF, 0xEF, 0x27, 0x59, 0x43, 0x83, 0x01, 0xC0, 0x03, 0x42, 0x01, + 0x87, 0x0E, 0xB8, 0xFF, 0xEB, 0x0F, 0x5E, 0x43, 0x08, 0x09, 0xE1, 0x4A, + 0x48, 0x48, 0x80, 0x36, 0x4B, 0xAA, 0x80, 0x01, 0xCC, 0x01, 0xC7, 0x4B, + 0xEC, 0x03, 0x16, 0x0A, 0x88, 0xE6, 0x80, 0x07, 0xD0, 0x57, 0x81, 0x07, + 0xF0, 0x97, 0x87, 0x07, 0xF8, 0xC7, 0x40, 0x7A, 0xC6, 0x01, 0xF1, 0x03, + 0x30, 0x00, 0xA0, 0x0E, 0xBD, 0xFF, 0xEF, 0x87, 0xB9, 0xFF, 0xFF, 0x97, + 0x86, 0x07, 0xD8, 0x87, 0xBD, 0xFF, 0xEF, 0x77, 0xBD, 0xFF, 0xEF, 0x87, + 0x87, 0x07, 0xE8, 0x5F, 0xBD, 0xFF, 0xEF, 0xA7, 0xBD, 0xFF, 0xEF, 0xB7, + 0xB8, 0xFF, 0xFF, 0x27, 0xBA, 0xFF, 0xF7, 0xA7, 0xBE, 0xFF, 0xF7, 0x57, + 0xE8, 0x03, 0x45, 0x31, 0x8B, 0xC6, 0xED, 0x85, 0x78, 0x00, 0x04, 0x01, + 0xF8, 0x00, 0x06, 0x42, 0x18, 0x00, 0x03, 0x01, 0x58, 0x63, 0x03, 0x00, + 0x18, 0x00, 0x02, 0x42, 0x00, 0x00, 0x00, 0x42, 0x20, 0xE0, 0x03, 0x00, + 0x98, 0xA3, 0x06, 0x00, 0xB0, 0xB3, 0x03, 0x00, 0xB0, 0x43, 0x04, 0x00, + 0xB8, 0x43, 0x01, 0x00, 0xB0, 0x23, 0x02, 0x00, 0xB0, 0x23, 0x03, 0x00, + 0x20, 0xEB, 0x01, 0x00, 0x3F, 0x18, 0x14, 0xF9, 0x74, 0xD8, 0x06, 0xD2, + 0x38, 0x48, 0x74, 0x48, 0x00, 0xCA, 0x44, 0x01, 0xD0, 0x5E, 0x38, 0x00, + 0x78, 0x00, 0xC0, 0x41, 0x47, 0x18, 0x44, 0xE2, 0x00, 0xD8, 0xC4, 0xC0, + 0x4C, 0x1B, 0x1E, 0x9A, 0x1E, 0x5A, 0x08, 0x1B, 0x3C, 0x82, 0x43, 0x18, + 0x44, 0xC2, 0x07, 0xD8, 0xC0, 0xC0, 0x40, 0x1B, 0x18, 0x9A, 0x1C, 0x5A, + 0x03, 0x1B, 0x38, 0x82, 0xAC, 0x85, 0x87, 0xBD, 0x63, 0xA2, 0x5F, 0x03, + 0xC0, 0x0B, 0x88, 0x9C, 0xE4, 0x13, 0xE2, 0x0B, 0x88, 0x0C, 0xC8, 0x2B, + 0x44, 0x8A, 0x37, 0x22, 0x40, 0x8A, 0x87, 0xB4, 0xF8, 0x03, 0x1E, 0x01, + 0x40, 0x09, 0x88, 0x66, 0x0F, 0x01, 0x70, 0x6A, 0xF0, 0x71, 0x00, 0x27, + 0xC5, 0xB8, 0x9B, 0xDB, 0xA2, 0x9A, 0xE3, 0x48, 0x93, 0x4D, 0x5A, 0x03, + 0xCC, 0x03, 0x10, 0x42, 0xE7, 0xB6, 0x0F, 0x1B, 0x13, 0x1B, 0x11, 0x1B, + 0x06, 0x01, 0x18, 0x02, 0x0B, 0x03, 0x5D, 0x03, 0xCF, 0x0B, 0x40, 0x12, + 0x80, 0x01, 0x81, 0xAC, 0xA0, 0x0B, 0x08, 0x01, 0x40, 0x02, 0xC7, 0x71, + 0x01, 0x70, 0x3C, 0x89, 0x19, 0x01, 0xC0, 0xB0, 0x0F, 0xF8, 0xCD, 0xB0, + 0x13, 0x9B, 0x3D, 0x19, 0xC3, 0x30, 0x0A, 0xF8, 0xCB, 0xB0, 0xA7, 0x9B, + 0xE2, 0x48, 0x92, 0x4D, 0x4F, 0x11, 0xD8, 0x7E, 0xCE, 0xB4, 0xF8, 0x4B, + 0x4B, 0x29, 0xC8, 0xCE, 0x45, 0xAA, 0x06, 0x48, 0xC0, 0x71, 0xC0, 0x40, + 0x02, 0x48, 0xC3, 0x18, 0x4A, 0xA2, 0xC6, 0xD8, 0x9A, 0x24, 0xC0, 0x00, + 0x83, 0x1C, 0x30, 0x02, 0x58, 0x7A, 0x9E, 0x71, 0x08, 0x01, 0x88, 0x44, + 0x48, 0x82, 0x8E, 0x84, 0x88, 0x7C, 0x30, 0xCA, 0xC8, 0xE1, 0x88, 0x14, + 0x0C, 0x01, 0x30, 0x62, 0x00, 0x37, 0xF2, 0x24, 0x0B, 0x01, 0xF0, 0x8A, + 0xF8, 0x1C, 0x88, 0xA4, 0x35, 0x01, 0xF8, 0xF2, 0xD8, 0x48, 0x94, 0x4D, + 0x48, 0xF9, 0xEF, 0x06, 0x08, 0xF9, 0xFF, 0xA4, 0xCB, 0xF0, 0x85, 0xB0, + 0x70, 0xF9, 0xEF, 0x06, 0x30, 0xF9, 0xFF, 0x14, 0x80, 0xF3, 0xF1, 0x14, + 0xE0, 0xB0, 0xB3, 0x14, 0xC4, 0x3B, 0x10, 0xBA, 0x9C, 0x46, 0x10, 0x8A, + 0xD8, 0x36, 0x40, 0xF4, 0xDB, 0x48, 0xC6, 0x88, 0x90, 0x4D, 0x00, 0xCC, + 0x80, 0x48, 0x04, 0x37, 0x10, 0x8A, 0xDC, 0x16, 0x00, 0x70, 0x04, 0xF4, + 0x00, 0x0F, 0x30, 0x01, 0x04, 0xF4, 0x10, 0x8A, 0xD8, 0x0E, 0x30, 0x09, + 0xB3, 0x44, 0x40, 0x70, 0x28, 0x32, 0xEB, 0x26, 0xF4, 0x84, 0x10, 0x72, + 0xE8, 0x2E, 0x88, 0x84, 0x00, 0x1F, 0xF0, 0x7C, 0x10, 0x72, 0xEC, 0x06, + 0x88, 0x7C, 0x80, 0x0B, 0xE4, 0x00, 0xE2, 0xD8, 0xCC, 0x24, 0xE0, 0x48, + 0x88, 0x24, 0xC8, 0x1C, 0xE0, 0x48, 0x8C, 0x1C, 0x32, 0x0A, 0xE3, 0x48, + 0x94, 0x4D, 0x32, 0x62, 0x2D, 0x62, 0xDD, 0xB6, 0xC8, 0x44, 0x48, 0x01, + 0x80, 0xA6, 0x08, 0x01, 0x18, 0x01, 0x98, 0x74, 0xDC, 0x0C, 0xC0, 0xD8, + 0x40, 0xD8, 0x9A, 0x94, 0xDA, 0x0C, 0x30, 0xD8, 0x70, 0xD8, 0x98, 0x8C, + 0x1C, 0x01, 0x30, 0xE2, 0x98, 0x3C, 0x98, 0x34, 0x9A, 0x2C, 0xF0, 0x00, + 0xF2, 0x58, 0x93, 0xDD, 0x9A, 0x4C, 0x00, 0x0F, 0x03, 0xAF, 0x35, 0x1A, + 0x04, 0xD8, 0x32, 0xE2, 0xDA, 0x3C, 0x00, 0xD8, 0x98, 0x3C, 0xD8, 0x34, + 0x00, 0xD8, 0x9A, 0x34, 0xDA, 0x2C, 0x00, 0xD8, 0x98, 0x2C, 0xF0, 0x4C, + 0x45, 0x58, 0x13, 0x9A, 0xE8, 0x26, 0xC0, 0x1B, 0xF4, 0x84, 0xD8, 0xD8, + 0x80, 0x1B, 0x00, 0x1F, 0xC0, 0x1B, 0xF0, 0x7C, 0xD8, 0xD8, 0x84, 0x1B, + 0xF8, 0x4C, 0xC0, 0x1B, 0x77, 0x55, 0xA8, 0x9A, 0xC4, 0x1B, 0x10, 0x9A, + 0xDA, 0xDE, 0xE0, 0x48, 0x90, 0x4D, 0xF2, 0x74, 0xC1, 0xB0, 0x97, 0xB5, + 0xB3, 0x74, 0x30, 0x32, 0x39, 0x09, 0x18, 0xF2, 0x30, 0xA2, 0xF5, 0x94, + 0x10, 0x9A, 0xDD, 0x76, 0xF1, 0x3C, 0x18, 0xF2, 0xB0, 0x3C, 0xF0, 0x0C, + 0x10, 0x9A, 0xDD, 0x46, 0xF1, 0x34, 0x18, 0xF2, 0xB0, 0x34, 0xF0, 0x8C, + 0x10, 0x9A, 0xDD, 0x16, 0xD9, 0x2C, 0x18, 0xDA, 0x9A, 0x2C, 0xF0, 0x00, + 0xDA, 0x4C, 0xF0, 0xD8, 0x90, 0xDD, 0x9A, 0x4C, 0xD8, 0x4C, 0x58, 0x01, + 0xD0, 0xDE, 0xC5, 0xAC, 0xA0, 0x0B, 0xD2, 0xAC, 0xD0, 0x40, 0xA3, 0x83, + 0x36, 0x02, 0x1B, 0x02, 0x0B, 0x03, 0x35, 0x02, 0x10, 0x03, 0xC5, 0x3C, + 0x08, 0x03, 0xC7, 0x34, 0x10, 0x03, 0xC1, 0x2C, 0x10, 0x03, 0x33, 0x01, + 0x00, 0x07, 0xC2, 0x74, 0xB9, 0xFF, 0xE7, 0x87, 0x90, 0x05, 0x80, 0x74, + 0x4D, 0x52, 0x03, 0x80, 0xCA, 0x71, 0xC0, 0x00, 0x0C, 0x89, 0x09, 0x48, + 0xC4, 0x00, 0x52, 0x13, 0x40, 0x55, 0x08, 0x01, 0x18, 0x01, 0x98, 0x04, + 0x30, 0xE2, 0x04, 0xD7, 0x38, 0x98, 0x86, 0x86, 0xC0, 0x1B, 0xF8, 0x74, + 0xD8, 0xD8, 0x96, 0xDD, 0x58, 0x01, 0xE8, 0x3E, 0x80, 0x1B, 0xF8, 0x04, + 0xC6, 0xD8, 0x97, 0xDD, 0x9A, 0x04, 0xE0, 0x48, 0x90, 0x4D, 0x02, 0x27, + 0x18, 0x01, 0x80, 0x1B, 0x00, 0x0F, 0x18, 0x01, 0x82, 0x1B, 0x40, 0x90, + 0xE3, 0x00, 0x32, 0x1A, 0xE2, 0xD8, 0x92, 0xDD, 0x35, 0xE2, 0x2C, 0x62, + 0xDB, 0x16, 0xE7, 0xB0, 0x90, 0xB5, 0xC3, 0x04, 0x82, 0x74, 0x40, 0x9A, + 0x00, 0x98, 0xC5, 0x71, 0x38, 0x89, 0xC1, 0xD8, 0x0E, 0xF8, 0xCD, 0xD8, + 0x13, 0xD3, 0x14, 0x19, 0xCA, 0x00, 0x0C, 0x90, 0xC2, 0x00, 0xA4, 0x0B, + 0x48, 0x21, 0xD8, 0x0E, 0x75, 0x09, 0xD8, 0xD6, 0x02, 0x01, 0x48, 0x52, + 0x38, 0x89, 0xC9, 0x71, 0x0C, 0xF8, 0x05, 0x10, 0xC6, 0x90, 0xCA, 0x98, + 0xE4, 0x10, 0x02, 0xB0, 0xC7, 0xB0, 0xCB, 0xB0, 0x55, 0xEB, 0x54, 0xB3, + 0x1C, 0xAA, 0x15, 0xEB, 0x18, 0x19, 0xC3, 0x40, 0x0E, 0xD8, 0xC2, 0x00, + 0xE4, 0x1B, 0xE2, 0x2B, 0xDA, 0xD8, 0xA2, 0x1B, 0x90, 0x85, 0x42, 0x09, + 0xD9, 0x4E, 0x4F, 0xF2, 0x02, 0x09, 0x88, 0x01, 0x83, 0x43, 0x50, 0x03, + 0x10, 0x21, 0x40, 0x01, 0x80, 0x16, 0x00, 0x29, 0x80, 0x53, 0x00, 0xFF, + 0x50, 0x03, 0x41, 0x01, 0x80, 0x16, 0x00, 0x21, 0x80, 0x53, 0x00, 0xCF, + 0x48, 0x03, 0x47, 0x01, 0x80, 0x1E, 0x00, 0x19, 0x10, 0x19, 0x80, 0x53, + 0x05, 0x97, 0x50, 0x03, 0x40, 0x01, 0x88, 0x2E, 0x5A, 0x03, 0xEB, 0x53, + 0x80, 0x01, 0xD9, 0x03, 0x10, 0x12, 0x9C, 0x0E, 0x00, 0x11, 0x00, 0x3F, + 0x41, 0x62, 0x81, 0x01, 0xE8, 0x03, 0x40, 0x01, 0x80, 0x0E, 0x00, 0x11, + 0x00, 0x07, 0x00, 0x09, 0xC4, 0x53, 0xE0, 0x98, 0x83, 0x5B, 0x5A, 0x1B, + 0xE3, 0xEB, 0x3E, 0x68, 0xA2, 0x0E, 0xF0, 0x90, 0x81, 0x53, 0xE8, 0x13, + 0x2C, 0x29, 0x10, 0x12, 0x94, 0x0E, 0x80, 0x6B, 0x04, 0xE7, 0x10, 0x12, + 0xC8, 0x46, 0x40, 0x09, 0x8F, 0x16, 0x10, 0x81, 0x80, 0x53, 0x04, 0xAF, + 0xD4, 0x90, 0x00, 0xAA, 0x80, 0x6B, 0x04, 0x8F, 0x40, 0x19, 0xC8, 0x0E, + 0x10, 0x19, 0x00, 0x07, 0x94, 0x15, 0xC2, 0x6B, 0x68, 0x01, 0x80, 0x16, + 0xF4, 0x68, 0x83, 0x6B, 0x02, 0x37, 0xC0, 0xCB, 0xF2, 0x90, 0x1A, 0x8A, + 0xD4, 0x9C, 0xC0, 0x48, 0xD4, 0xB4, 0xB8, 0x8B, 0xA8, 0x03, 0x81, 0xBD, + 0xEF, 0x85, 0xAF, 0x85, 0x80, 0x5D, 0x44, 0x72, 0x82, 0x54, 0x58, 0x03, + 0xC8, 0x23, 0xE0, 0x0B, 0x8E, 0x44, 0xE0, 0x0B, 0x30, 0x48, 0xA8, 0x1E, + 0x84, 0x01, 0xC5, 0x03, 0x41, 0x01, 0x80, 0x1E, 0x4D, 0x42, 0x00, 0x00, + 0xCA, 0x71, 0xC0, 0x00, 0x00, 0x08, 0x53, 0x42, 0xC4, 0x08, 0xC2, 0x48, + 0xC0, 0x10, 0x04, 0x01, 0x18, 0x01, 0x00, 0x9F, 0x68, 0x07, 0x00, 0x07, + 0x20, 0x07, 0x00, 0x07, 0x78, 0x00, 0x05, 0x01, 0x18, 0x70, 0x03, 0x01, + 0x70, 0x00, 0x04, 0x01, 0x20, 0xE0, 0x03, 0x00, 0x78, 0xF8, 0x07, 0x00, + 0x00, 0x5C, 0x00, 0x9C, 0xE4, 0x48, 0xE4, 0x90, 0xE2, 0x00, 0x92, 0x05, + 0x17, 0x02, 0xDD, 0xBE, 0x87, 0x5D, 0xE8, 0x85, 0x40, 0xFA, 0xC7, 0x03, + 0x6F, 0xFA, 0x0F, 0x43, 0x08, 0x01, 0x00, 0x11, 0xBE, 0xFF, 0xDF, 0x57, + 0x42, 0xE2, 0x87, 0x01, 0x43, 0x0B, 0x30, 0x5A, 0x11, 0xCC, 0x58, 0x4B, + 0x13, 0xCC, 0x5A, 0x4B, 0x15, 0xCC, 0x5C, 0x4B, 0x17, 0xCC, 0x46, 0x4B, + 0x1F, 0xCC, 0x48, 0xBA, 0x42, 0x53, 0x18, 0xD4, 0x4C, 0x53, 0x1F, 0xD4, + 0x17, 0x89, 0x00, 0x53, 0x13, 0x19, 0x18, 0x53, 0x40, 0x53, 0x18, 0x11, + 0x18, 0xD2, 0x04, 0x53, 0x40, 0x0B, 0x18, 0xCA, 0x07, 0x0B, 0x40, 0x82, + 0x0E, 0x69, 0xF9, 0x13, 0x44, 0x7A, 0x0F, 0x48, 0xC0, 0x08, 0x8A, 0x4C, + 0x0A, 0x09, 0x0B, 0x48, 0xC0, 0x28, 0x52, 0x09, 0x88, 0xBE, 0xC2, 0x54, + 0x5D, 0x03, 0x82, 0x01, 0x50, 0x04, 0x86, 0x1C, 0x44, 0x2A, 0x5F, 0x0B, + 0x90, 0x75, 0xB6, 0x14, 0x08, 0x01, 0x88, 0x0C, 0x42, 0x12, 0x1F, 0x33, + 0xEA, 0x4B, 0x43, 0x48, 0x03, 0x48, 0xAA, 0x4B, 0x0C, 0x41, 0x00, 0x0B, + 0x47, 0x0B, 0x10, 0xF9, 0x90, 0x21, 0x18, 0x8A, 0x00, 0x0B, 0x00, 0x07, + 0xFB, 0x85, 0xE9, 0x43, 0x3F, 0x00, 0x86, 0xDE, 0x4F, 0xE2, 0x06, 0x00, + 0xC6, 0x00, 0x4A, 0xE2, 0xC0, 0x38, 0xC2, 0x54, 0x5E, 0x03, 0xDA, 0x0B, + 0x37, 0xC2, 0xB9, 0xFF, 0xDE, 0xEF, 0x4B, 0xCA, 0x10, 0x01, 0x00, 0x01, + 0x02, 0x67, 0x00, 0x18, 0x37, 0xE2, 0xF4, 0xDA, 0x10, 0x5A, 0xD4, 0x0E, + 0x33, 0x0A, 0xD3, 0xCA, 0x10, 0x9A, 0xEC, 0x0E, 0x35, 0x12, 0xD3, 0xD2, + 0xE2, 0x00, 0x92, 0x05, 0x17, 0x02, 0xDD, 0x86, 0xC4, 0x1C, 0xE0, 0x00, + 0x10, 0x0A, 0x9C, 0x36, 0xC0, 0x0C, 0x40, 0x01, 0x8B, 0x9E, 0x40, 0x80, + 0x40, 0x08, 0xC2, 0x70, 0x00, 0x3F, 0xC0, 0x1C, 0xF4, 0x00, 0x14, 0x12, + 0xE0, 0x5E, 0x00, 0x09, 0x83, 0x0C, 0xE0, 0xB0, 0x90, 0xB5, 0x77, 0x01, + 0x80, 0x16, 0xC0, 0x14, 0x15, 0x32, 0x9C, 0xBE, 0x70, 0x01, 0x88, 0x06, + 0x30, 0x09, 0xC0, 0x4C, 0x90, 0x33, 0xC0, 0x4C, 0xD5, 0x0B, 0x40, 0xDA, + 0x18, 0x0B, 0x32, 0x01, 0x00, 0xAF, 0xC2, 0x44, 0x10, 0x32, 0xD4, 0x5E, + 0xEA, 0x43, 0x43, 0x00, 0x03, 0x00, 0xAA, 0x43, 0x40, 0xAA, 0x0D, 0x41, + 0x00, 0x0B, 0x44, 0x0B, 0x10, 0xF9, 0x97, 0x21, 0x18, 0x8A, 0x00, 0x0B, + 0x4D, 0xA2, 0x05, 0x00, 0xC3, 0x08, 0x02, 0x00, 0x50, 0x9A, 0xC5, 0x40, + 0xC4, 0x00, 0xC4, 0x48, 0x70, 0x01, 0x88, 0x66, 0x15, 0x01, 0x78, 0x8A, + 0x00, 0x37, 0x18, 0x01, 0x00, 0x1C, 0x00, 0x7C, 0xE4, 0x00, 0xE4, 0x48, + 0xE2, 0x90, 0x92, 0x95, 0x17, 0x12, 0xDD, 0xB6, 0x05, 0x07, 0x59, 0x4A, + 0x06, 0x10, 0xC7, 0x90, 0x5E, 0x42, 0xC5, 0x90, 0x30, 0xA2, 0x1C, 0x01, + 0x03, 0x9F, 0x30, 0x3A, 0x15, 0x01, 0xF0, 0xD2, 0x3E, 0x01, 0xF8, 0x3A, + 0x10, 0xBA, 0xD4, 0x06, 0x00, 0x14, 0x38, 0x01, 0xFC, 0x7A, 0x16, 0xBA, + 0xE8, 0x06, 0x00, 0x54, 0xE4, 0x00, 0xE4, 0x48, 0x34, 0x12, 0xE3, 0x90, + 0x32, 0xA2, 0xE4, 0xD8, 0x95, 0xDD, 0x12, 0x1A, 0xD8, 0x4E, 0xC7, 0x44, + 0x10, 0x32, 0x84, 0x8E, 0xEE, 0x43, 0x3B, 0x00, 0x84, 0xE6, 0x4F, 0xBA, + 0x02, 0x00, 0xC7, 0x00, 0x4A, 0xB2, 0xC4, 0x00, 0xCA, 0x54, 0x58, 0x4B, + 0xDF, 0x4B, 0xBE, 0xFF, 0xD3, 0x9F, 0xE7, 0xB0, 0x90, 0xB5, 0xC3, 0x44, + 0x15, 0x32, 0xEC, 0x36, 0x43, 0x62, 0x34, 0x5A, 0x52, 0xCC, 0x80, 0x01, + 0x04, 0x0B, 0x40, 0x52, 0x50, 0xCC, 0x1A, 0x0B, 0x52, 0xCC, 0x1C, 0x0B, + 0x54, 0xCC, 0x1E, 0x0B, 0x5E, 0xCC, 0x00, 0x0B, 0x4A, 0x32, 0x5C, 0xD4, + 0x04, 0x53, 0x58, 0xCC, 0x08, 0x0B, 0x3E, 0x0F, 0x4C, 0x12, 0x8C, 0x01, + 0x48, 0x53, 0x18, 0x21, 0x18, 0xD2, 0x08, 0x53, 0x4A, 0x53, 0x18, 0x01, + 0x18, 0xD2, 0x08, 0x53, 0x4C, 0x5B, 0x10, 0x01, 0x18, 0x9A, 0x08, 0x5B, + 0x48, 0x0A, 0x1C, 0x01, 0x02, 0x5B, 0x40, 0x5B, 0x1A, 0x9A, 0x00, 0x5B, + 0x48, 0xFA, 0x43, 0x53, 0x18, 0x01, 0x19, 0xD2, 0x03, 0x53, 0x48, 0xB2, + 0x8E, 0x01, 0x02, 0x43, 0x38, 0x82, 0xAB, 0x85, 0x08, 0x09, 0x00, 0x31, + 0xBE, 0xFF, 0xE7, 0x27, 0x08, 0x11, 0x00, 0x21, 0xBE, 0xFF, 0xE7, 0x07, + 0x00, 0x09, 0x80, 0x07, 0xE0, 0x57, 0x04, 0x31, 0x84, 0x07, 0xE0, 0x3F, + 0x00, 0x21, 0x80, 0x07, 0xE3, 0x27, 0xB4, 0x15, 0xEB, 0x85, 0x48, 0x82, + 0x06, 0x89, 0xC8, 0x01, 0x08, 0x43, 0x02, 0x01, 0xE6, 0x00, 0x92, 0x05, + 0x47, 0x51, 0x98, 0xDE, 0x02, 0x81, 0x08, 0x43, 0x02, 0x61, 0x0B, 0x43, + 0x3F, 0x82, 0xAB, 0xC5, 0x42, 0x12, 0x43, 0x0B, 0x14, 0x01, 0x1E, 0x8A, + 0x02, 0x0B, 0x42, 0x0B, 0x10, 0x01, 0x1A, 0x8A, 0x03, 0x0B, 0x42, 0x22, + 0x44, 0x0B, 0x2A, 0x01, 0x1A, 0x4A, 0x01, 0x0B, 0x4B, 0x02, 0x43, 0x12, + 0xE2, 0x48, 0x0E, 0x0B, 0x24, 0x01, 0x00, 0x23, 0x40, 0x0B, 0x42, 0x0B, + 0x18, 0x4A, 0x01, 0x0B, 0x00, 0x09, 0x80, 0x07, 0xE3, 0xC7, 0xB2, 0x15, + 0x01, 0x01, 0x09, 0x01, 0x72, 0x9A, 0x52, 0xDA, 0x7A, 0xDA, 0xB2, 0x01, + 0x1A, 0x42, 0x58, 0x92, 0xDE, 0x01, 0x1A, 0xC3, 0xFA, 0x85, 0x01, 0xA3, + 0x19, 0x21, 0x00, 0x9B, 0x10, 0xD8, 0x02, 0x9B, 0xF8, 0x85, 0x01, 0xA3, + 0x02, 0xA3, 0x41, 0x9B, 0x95, 0xDD, 0x14, 0xDA, 0x94, 0x06, 0x18, 0x42, + 0x40, 0x48, 0x4A, 0x01, 0x8A, 0x56, 0x47, 0x72, 0x45, 0x0B, 0x18, 0x4A, + 0x02, 0x0B, 0x08, 0x23, 0x40, 0x72, 0x0A, 0x11, 0x03, 0x0B, 0xB0, 0x95, + 0x4A, 0x12, 0x42, 0x43, 0x14, 0x01, 0x1E, 0x82, 0x07, 0x43, 0xEA, 0xC5, + 0xAC, 0x85, 0x87, 0x3D, 0x72, 0x4A, 0x42, 0x52, 0x58, 0x03, 0xCA, 0x0B, + 0x8E, 0x1C, 0xC0, 0x03, 0x80, 0x14, 0x28, 0x01, 0x40, 0xE2, 0x81, 0x34, + 0x03, 0xCF, 0x01, 0x40, 0xF4, 0xA2, 0xC9, 0x00, 0x38, 0xA1, 0x80, 0x2C, + 0xF8, 0x3A, 0xC6, 0x34, 0xFD, 0x03, 0x14, 0x02, 0xD3, 0x86, 0x00, 0xC0, + 0x10, 0x02, 0xD5, 0x6E, 0x88, 0x00, 0x09, 0x81, 0xD1, 0x48, 0x30, 0x02, + 0xBD, 0xFF, 0xC7, 0x37, 0xC8, 0x00, 0x96, 0x05, 0x10, 0x02, 0xDD, 0x0E, + 0xF1, 0x20, 0x93, 0x05, 0xCC, 0x2C, 0x10, 0x44, 0xC7, 0x2C, 0x80, 0xF9, + 0x80, 0x09, 0x20, 0xC1, 0x80, 0x24, 0xF8, 0x22, 0x3E, 0x21, 0xF8, 0x3A, + 0xC4, 0x34, 0xF8, 0x03, 0x10, 0x02, 0xD5, 0x86, 0x05, 0xC0, 0x13, 0x02, + 0xD1, 0x6E, 0x88, 0x00, 0x08, 0x81, 0xD0, 0x48, 0x37, 0x02, 0xB9, 0xFF, + 0xC6, 0x4F, 0xCC, 0x00, 0x95, 0x05, 0x10, 0x02, 0xDB, 0x0E, 0xF0, 0x20, + 0x90, 0x05, 0xC9, 0x24, 0x03, 0x44, 0xE4, 0x68, 0x90, 0x6D, 0xC7, 0x1C, + 0x16, 0x2A, 0x9C, 0x16, 0x3A, 0x01, 0x00, 0xBF, 0x30, 0xC2, 0x09, 0xA1, + 0x19, 0x42, 0xF2, 0xA2, 0xC8, 0x28, 0x04, 0x11, 0xF0, 0x42, 0x81, 0x0C, + 0xC4, 0x34, 0xF8, 0x03, 0x10, 0x02, 0xD5, 0x8E, 0xC2, 0x0C, 0x00, 0x00, + 0x10, 0x02, 0xD5, 0x6E, 0x88, 0x08, 0x01, 0x81, 0xD1, 0x08, 0x32, 0x02, + 0xBB, 0xFF, 0xC7, 0x27, 0xCA, 0x0C, 0xC0, 0x00, 0x95, 0x05, 0x10, 0x02, + 0xDB, 0x0E, 0xF0, 0x20, 0x93, 0x05, 0x01, 0x44, 0x21, 0x91, 0xF8, 0x62, + 0x01, 0x81, 0xF0, 0x42, 0x80, 0x0C, 0xC0, 0x34, 0xFD, 0x03, 0x14, 0x02, + 0xD0, 0x76, 0xC1, 0x0C, 0x05, 0x00, 0x12, 0x02, 0xD1, 0x56, 0x89, 0x00, + 0x08, 0x81, 0xD0, 0x48, 0x37, 0x02, 0xB9, 0xFF, 0xC0, 0x4F, 0x02, 0xDF, + 0x60, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x42, 0x18, 0x00, 0x04, 0x42, + 0x70, 0x00, 0x04, 0x01, 0x18, 0x00, 0x03, 0x01, 0x20, 0xE0, 0x03, 0x00, + 0xF8, 0xFB, 0x07, 0x00, 0x00, 0x00, 0x06, 0x42, 0x10, 0x00, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x58, 0x98, 0x02, 0x00, 0x08, 0x07, 0x04, 0x07, + 0x38, 0xE0, 0x06, 0x01, 0x78, 0x00, 0x05, 0x01, 0xCA, 0x0C, 0xC0, 0x00, + 0x95, 0x05, 0x10, 0x02, 0xDB, 0x0E, 0xF0, 0x20, 0x91, 0x05, 0x11, 0x44, + 0xE7, 0xF8, 0x93, 0xFD, 0xC4, 0x14, 0x10, 0x3A, 0x98, 0x26, 0x85, 0x3D, + 0xEF, 0x85, 0xAF, 0xBD, 0x80, 0xF5, 0x04, 0x01, 0x80, 0x84, 0x80, 0x7C, + 0x7B, 0xFA, 0x5F, 0xC3, 0xC8, 0x23, 0x00, 0x01, 0x80, 0x74, 0x80, 0x6C, + 0x81, 0x64, 0x08, 0x89, 0x50, 0xEA, 0x0F, 0x48, 0x42, 0xDA, 0xC7, 0x88, + 0xFF, 0x03, 0x96, 0xF9, 0x90, 0x29, 0x8D, 0xE4, 0x40, 0x09, 0x88, 0x96, + 0xC3, 0xFC, 0x18, 0x02, 0xC0, 0x18, 0xCC, 0xE4, 0xC0, 0x28, 0xC2, 0xF4, + 0x08, 0x01, 0x00, 0x47, 0x40, 0x34, 0x80, 0xF3, 0x41, 0x34, 0x80, 0x73, + 0xE3, 0xD8, 0xE2, 0x68, 0xE2, 0x00, 0xE4, 0x48, 0x95, 0x4D, 0x12, 0x0A, + 0xD8, 0xA6, 0x2F, 0x01, 0x30, 0x72, 0xA9, 0x9C, 0xC0, 0xF4, 0x80, 0x14, + 0x44, 0x2D, 0x30, 0x32, 0xC3, 0xFC, 0x18, 0x02, 0x84, 0xDC, 0xC0, 0x00, + 0x80, 0xD4, 0x80, 0x24, 0x4D, 0xCB, 0x55, 0xC3, 0x30, 0x22, 0x04, 0x01, + 0x00, 0x2F, 0xD1, 0x14, 0xD8, 0x24, 0x40, 0x94, 0xC6, 0xDB, 0xD0, 0x90, + 0x93, 0x95, 0x30, 0x9A, 0x06, 0xD4, 0x38, 0x58, 0x80, 0x26, 0xD8, 0x9C, + 0xC0, 0x90, 0x96, 0x95, 0x90, 0x9C, 0x00, 0x3F, 0x36, 0x1A, 0x3B, 0xD8, + 0x82, 0x16, 0xC8, 0x90, 0x90, 0xAD, 0x00, 0x0F, 0xC8, 0x90, 0x94, 0xB5, + 0x34, 0x92, 0xE3, 0x90, 0x30, 0xB2, 0xD4, 0x14, 0xE0, 0x90, 0x94, 0x14, + 0xD2, 0x24, 0xE0, 0x90, 0x92, 0x24, 0x40, 0x48, 0x32, 0x12, 0x43, 0x90, + 0x32, 0xA2, 0xE4, 0x00, 0x95, 0x05, 0x12, 0x02, 0xDE, 0xBE, 0x46, 0x82, + 0x80, 0x01, 0x81, 0xCC, 0xE0, 0x0B, 0x48, 0x01, 0xE8, 0x26, 0xC0, 0x9C, + 0xBD, 0xF7, 0xFF, 0x87, 0x90, 0x05, 0x80, 0x9C, 0xC2, 0xCC, 0xE0, 0x0B, + 0x48, 0x01, 0xE8, 0x3E, 0x48, 0x09, 0x88, 0x0E, 0x80, 0x68, 0x03, 0x1F, + 0x37, 0x42, 0xB9, 0xF7, 0xF8, 0x1F, 0x95, 0x2D, 0xC4, 0xCC, 0xE0, 0x0B, + 0x48, 0x01, 0xE8, 0x3E, 0x48, 0x09, 0x88, 0x0E, 0x80, 0xB0, 0x03, 0x1F, + 0x37, 0x82, 0xB9, 0xF7, 0xF8, 0xBF, 0x94, 0x35, 0xC0, 0xF4, 0x48, 0x2D, + 0x30, 0x72, 0xCC, 0xD4, 0x8D, 0x24, 0x48, 0xCB, 0x8D, 0x94, 0x50, 0xCB, + 0x8B, 0x8C, 0x58, 0xD3, 0xE6, 0x8B, 0x3E, 0x48, 0x87, 0x66, 0x48, 0xCB, + 0x31, 0x62, 0x54, 0xCB, 0x8B, 0x84, 0x50, 0xCB, 0x88, 0x7C, 0xE8, 0x8B, + 0x8A, 0x74, 0xE8, 0x8B, 0x8C, 0x6C, 0xE8, 0x8B, 0x88, 0x64, 0x00, 0x0F, + 0x0C, 0x01, 0x30, 0x62, 0xC2, 0x8B, 0x42, 0x48, 0x8D, 0xB4, 0x50, 0x8A, + 0xC9, 0xDC, 0x90, 0xC1, 0xC0, 0x48, 0x8C, 0x1C, 0x08, 0x01, 0x88, 0xBC, + 0x00, 0x17, 0xCC, 0x94, 0x38, 0x48, 0x86, 0x0E, 0xC8, 0x9C, 0x00, 0x2F, + 0xCE, 0x8C, 0x38, 0x48, 0x81, 0x0E, 0x30, 0x4A, 0x01, 0x07, 0x30, 0x8A, + 0x48, 0x01, 0xE8, 0x66, 0x30, 0x9A, 0x13, 0x01, 0xF0, 0xD2, 0x54, 0x01, + 0xEC, 0x3E, 0x10, 0x52, 0xD0, 0x06, 0x30, 0x8A, 0x42, 0x14, 0xD0, 0x88, + 0x90, 0x5D, 0x00, 0x1C, 0x03, 0xB7, 0x31, 0x9A, 0x14, 0x01, 0xF0, 0xD2, + 0x51, 0x01, 0xD0, 0x7E, 0x48, 0x01, 0xD0, 0x2E, 0x10, 0x52, 0xEC, 0x06, + 0x30, 0x8A, 0x40, 0x14, 0xD0, 0x88, 0x02, 0x0C, 0x1E, 0x01, 0xF0, 0x1A, + 0x36, 0x0A, 0x3B, 0x48, 0x80, 0x26, 0xC9, 0x24, 0xC0, 0x4B, 0x88, 0xC4, + 0xD0, 0x48, 0x96, 0x4D, 0xD6, 0x7C, 0x38, 0x90, 0x80, 0x3E, 0xD0, 0x64, + 0x10, 0x8A, 0xEC, 0xCE, 0xD0, 0x64, 0xC8, 0xC4, 0xD0, 0x48, 0x04, 0x0C, + 0x00, 0xA7, 0xD0, 0x84, 0x38, 0x90, 0x86, 0x3E, 0xD4, 0x6C, 0x10, 0x8A, + 0xE8, 0x76, 0xD0, 0x6C, 0xCC, 0xC4, 0xD0, 0x48, 0x00, 0x0C, 0x00, 0x4F, + 0xD4, 0x74, 0x10, 0x8A, 0xE8, 0x36, 0xD0, 0x74, 0xCC, 0xC4, 0xD0, 0x48, + 0x00, 0x0C, 0x00, 0x0F, 0x1E, 0x01, 0xF0, 0x1A, 0xC8, 0x1C, 0xD0, 0xB4, + 0xC6, 0x4B, 0xC0, 0x90, 0x10, 0x8A, 0xEC, 0x66, 0xC8, 0xFC, 0x10, 0x09, + 0x06, 0x52, 0xBC, 0x98, 0xC8, 0x04, 0x99, 0x0C, 0x90, 0x04, 0x40, 0x7B, + 0x41, 0x4B, 0x1A, 0xD2, 0x19, 0x5A, 0xC8, 0x04, 0x08, 0x66, 0xC8, 0x1C, + 0xE0, 0x48, 0x8A, 0x1C, 0xE0, 0x00, 0xCC, 0x24, 0xE0, 0x48, 0x8A, 0x24, + 0x34, 0x8A, 0xE3, 0x48, 0x30, 0x72, 0xCC, 0x94, 0x40, 0x48, 0x8A, 0x94, + 0xCA, 0x8C, 0x40, 0x48, 0x8B, 0x8C, 0x30, 0x0A, 0x48, 0x01, 0x80, 0x3E, + 0x44, 0x48, 0x32, 0x62, 0xCA, 0x84, 0x40, 0x48, 0x88, 0x84, 0xC8, 0x7C, + 0x40, 0x48, 0x8A, 0x7C, 0xCA, 0xBC, 0xE0, 0x48, 0x90, 0x4D, 0x8A, 0xBC, + 0xCD, 0xBC, 0x10, 0x0A, 0xD3, 0x06, 0x38, 0xC7, 0xE8, 0xD4, 0xC8, 0xE4, + 0xC2, 0xDC, 0xC0, 0x30, 0xF8, 0xF4, 0x00, 0x01, 0x80, 0xBC, 0x00, 0xEF, + 0x0B, 0x01, 0xF0, 0xCA, 0x89, 0xAC, 0xC0, 0x43, 0xC0, 0x8B, 0x89, 0xA4, + 0xC8, 0xAC, 0xC0, 0x40, 0xCA, 0xA4, 0xC0, 0x00, 0x0F, 0x19, 0xB8, 0xF7, + 0xF0, 0x9F, 0x96, 0x05, 0x80, 0x83, 0xC9, 0xAC, 0x80, 0x4B, 0xC9, 0xA4, + 0x04, 0x50, 0xC2, 0x48, 0xC4, 0x40, 0x80, 0x00, 0x03, 0xC4, 0xE1, 0x68, + 0xE5, 0xB0, 0xE3, 0xF8, 0xC2, 0xBC, 0xE0, 0x00, 0x90, 0x05, 0x82, 0xBC, + 0xC5, 0xBC, 0x10, 0x02, 0xD9, 0xF6, 0x86, 0x0D, 0xE9, 0x85, 0xAF, 0x85, + 0x42, 0x8A, 0x5A, 0x03, 0xC0, 0x23, 0xCE, 0x1B, 0x40, 0x92, 0x12, 0x01, + 0x00, 0x67, 0x08, 0x01, 0x00, 0x37, 0xC0, 0x2B, 0x35, 0x68, 0x75, 0x68, + 0x82, 0x2B, 0xE0, 0x00, 0xE6, 0x48, 0x92, 0x4D, 0x17, 0xCA, 0x9C, 0xB6, + 0xE6, 0x90, 0x92, 0x95, 0x17, 0x12, 0x9D, 0x86, 0xEB, 0x85, 0xA9, 0x85, + 0x48, 0x32, 0x1A, 0x01, 0x8E, 0x01, 0x81, 0x5B, 0x88, 0x5B, 0x30, 0x42, + 0x80, 0x01, 0xEF, 0x13, 0xEA, 0x23, 0x38, 0x90, 0x7A, 0x90, 0x06, 0x90, + 0x29, 0xE9, 0x07, 0x62, 0x18, 0xA2, 0xA8, 0x23, 0xEF, 0x13, 0x20, 0xD9, + 0x00, 0x12, 0xA9, 0x13, 0x63, 0xDA, 0x59, 0x03, 0x84, 0x01, 0xC1, 0x03, + 0x40, 0x01, 0x80, 0x06, 0x88, 0x5B, 0x04, 0x01, 0xB9, 0xDF, 0xF7, 0xB7, + 0x42, 0xBA, 0x81, 0x01, 0xE8, 0x03, 0x42, 0x51, 0x98, 0x16, 0x00, 0x09, + 0xB9, 0xDF, 0xF7, 0x77, 0x59, 0x03, 0x83, 0x01, 0xC0, 0x03, 0x44, 0x01, + 0x87, 0x0E, 0xB8, 0xDF, 0xC7, 0x67, 0xBA, 0xD7, 0xFF, 0xBF, 0xBE, 0xFF, + 0xFB, 0xB7, 0xED, 0x85, 0xAC, 0x85, 0x87, 0x8D, 0x40, 0x5A, 0x81, 0x7C, + 0x5C, 0x0B, 0xCA, 0x73, 0xC8, 0x43, 0x80, 0x54, 0x00, 0x01, 0x80, 0x2C, + 0x40, 0x42, 0x11, 0x01, 0xC6, 0x01, 0x19, 0x92, 0x84, 0x74, 0x28, 0x13, + 0x29, 0x13, 0x8E, 0x01, 0xD8, 0x43, 0x80, 0x64, 0x29, 0x01, 0x40, 0x12, + 0xC0, 0x01, 0x82, 0x6C, 0x00, 0xF7, 0xC4, 0x64, 0x45, 0x00, 0x12, 0x42, + 0xC0, 0x1E, 0xC0, 0x7C, 0x48, 0x03, 0x46, 0x01, 0x80, 0xF6, 0xC3, 0x6C, + 0x0C, 0x01, 0x10, 0x0B, 0x10, 0x0B, 0x8E, 0x34, 0x88, 0x3C, 0xC0, 0x74, + 0x6C, 0x0B, 0x6E, 0x03, 0x88, 0x4C, 0x80, 0x44, 0x20, 0x01, 0x00, 0x4F, + 0xC0, 0x4C, 0xC8, 0x44, 0x3A, 0x10, 0x46, 0x48, 0x1A, 0x8A, 0x40, 0x00, + 0x88, 0x44, 0x80, 0x4C, 0xE7, 0x20, 0x93, 0x25, 0xC6, 0x44, 0x38, 0x00, + 0x8D, 0x0E, 0x10, 0xA2, 0x9D, 0x86, 0x17, 0xA2, 0x80, 0xE6, 0x43, 0x72, + 0x80, 0x01, 0x81, 0x23, 0x41, 0x6A, 0x08, 0x19, 0xCC, 0x00, 0x08, 0x48, + 0xC0, 0x00, 0x7A, 0x6A, 0xC7, 0x03, 0x08, 0xC3, 0x30, 0x12, 0x09, 0x01, + 0x07, 0x09, 0xB8, 0xE7, 0xC9, 0x5F, 0x35, 0x0A, 0x07, 0x11, 0xB8, 0xE7, + 0xC0, 0x0F, 0x46, 0x42, 0x42, 0x0B, 0x3A, 0x48, 0xA8, 0xE6, 0x47, 0x0B, + 0x10, 0x11, 0x00, 0x5F, 0x78, 0x00, 0x05, 0x01, 0x70, 0x00, 0x04, 0x01, + 0x18, 0x00, 0x03, 0x01, 0x50, 0xA0, 0x05, 0x01, 0x00, 0x01, 0x00, 0x42, + 0x18, 0x00, 0x04, 0x42, 0x18, 0x8A, 0x00, 0x0B, 0x05, 0x41, 0x00, 0xC3, + 0x47, 0xC3, 0x09, 0xF9, 0x88, 0x19, 0x18, 0x42, 0x00, 0xC3, 0x69, 0x01, + 0x88, 0x56, 0xC0, 0x7C, 0x40, 0x03, 0x46, 0x01, 0x80, 0x0E, 0x80, 0x2C, + 0x05, 0x0F, 0x40, 0xB2, 0x80, 0x2C, 0xC0, 0x7C, 0x44, 0x03, 0x3C, 0x02, + 0xC5, 0x54, 0x48, 0xA2, 0x1A, 0x02, 0x03, 0x00, 0xC5, 0x00, 0x4A, 0x9A, + 0xC1, 0x38, 0x02, 0x57, 0xC6, 0x44, 0x38, 0x00, 0x80, 0xD6, 0x00, 0x09, + 0x00, 0x02, 0x85, 0x5C, 0x01, 0x07, 0xF8, 0x85, 0x08, 0x01, 0x88, 0x1C, + 0xC0, 0x5C, 0xD0, 0x6C, 0x84, 0x14, 0x50, 0x9B, 0x50, 0x93, 0x06, 0xC2, + 0x30, 0x52, 0x88, 0x0C, 0x82, 0x04, 0x00, 0x4A, 0x00, 0x82, 0x1A, 0x42, + 0x80, 0x7E, 0x57, 0x35, 0x31, 0x0A, 0x31, 0xC2, 0xD8, 0x2C, 0x00, 0x07, + 0x04, 0xD7, 0x38, 0xC2, 0xC2, 0x54, 0x00, 0x00, 0xC8, 0x38, 0xC6, 0x4C, + 0xCE, 0x44, 0x38, 0x10, 0x40, 0x48, 0x1A, 0x8A, 0x40, 0x00, 0x8A, 0x44, + 0x83, 0x4C, 0xE0, 0x20, 0x95, 0x25, 0x17, 0xA2, 0x98, 0x96, 0xC6, 0x74, + 0xD0, 0x3C, 0xC8, 0x34, 0x2C, 0x13, 0x2E, 0x0B, 0xE7, 0x68, 0x93, 0x6D, + 0xC4, 0x64, 0x10, 0x2A, 0x92, 0x06, 0x38, 0xE7, 0x07, 0x01, 0xB8, 0xE7, + 0xC0, 0xDF, 0x84, 0x8D, 0xEF, 0x85, 0xAF, 0xC5, 0x68, 0x9A, 0x34, 0x01, + 0x8F, 0x73, 0xEB, 0x60, 0x07, 0x11, 0xA0, 0xC9, 0xAF, 0x03, 0xBD, 0xFF, + 0xFD, 0xAF, 0xA9, 0x33, 0x5E, 0x03, 0xCB, 0x0B, 0x48, 0x01, 0x80, 0x66, + 0x84, 0x01, 0x7E, 0x6A, 0x47, 0x04, 0x06, 0xC3, 0x03, 0x09, 0x88, 0x43, + 0xBE, 0xE7, 0xCF, 0x5F, 0x8B, 0x73, 0x5B, 0x03, 0x84, 0x01, 0x46, 0x04, + 0x00, 0xC3, 0x0F, 0x01, 0x37, 0x42, 0xB8, 0xE7, 0xC4, 0x9F, 0x49, 0x22, + 0xCE, 0x01, 0xF9, 0x43, 0x40, 0x41, 0x96, 0x0E, 0xE6, 0x00, 0xBA, 0x43, + 0xEF, 0xC5, 0xAF, 0x85, 0x84, 0x6D, 0x44, 0x0A, 0x82, 0x64, 0x58, 0x03, + 0xC8, 0x0B, 0x88, 0x2C, 0xC0, 0x0B, 0x8E, 0x24, 0x49, 0xCA, 0x8B, 0xC1, + 0x8B, 0x5C, 0x50, 0xEA, 0x91, 0x54, 0x18, 0x79, 0xE0, 0xDA, 0x98, 0x44, + 0x18, 0x29, 0xB3, 0xEA, 0x60, 0xB2, 0x3B, 0x01, 0x18, 0x3B, 0xB9, 0x3C, + 0x10, 0x3B, 0xBF, 0x34, 0x1C, 0x01, 0x30, 0xF2, 0x58, 0xB2, 0x33, 0x01, + 0xAA, 0x3B, 0xC1, 0x3B, 0x40, 0xF8, 0xBB, 0x1C, 0x3E, 0x11, 0xFE, 0x3A, + 0x80, 0xC0, 0x83, 0x14, 0x31, 0x3A, 0xF9, 0x01, 0xF8, 0xC3, 0x47, 0x29, + 0xC0, 0xB6, 0x00, 0x01, 0x1D, 0xC4, 0x1B, 0xC4, 0x30, 0x22, 0x04, 0x77, + 0x00, 0x01, 0x00, 0x2F, 0x40, 0xBC, 0x80, 0x7B, 0xE4, 0x48, 0xE2, 0x90, + 0xE3, 0x38, 0x92, 0xC5, 0xFD, 0x2C, 0x10, 0xC2, 0xDB, 0xB6, 0x37, 0x02, + 0xE2, 0x00, 0x92, 0x05, 0x30, 0x22, 0xFC, 0x24, 0x2F, 0xE2, 0xDD, 0x6E, + 0xC4, 0x5C, 0x30, 0x22, 0xD0, 0x54, 0x00, 0x01, 0x82, 0x4C, 0x00, 0x67, + 0x0A, 0x01, 0x00, 0x1F, 0x30, 0x02, 0xC3, 0x03, 0x46, 0xBC, 0xD8, 0x00, + 0x90, 0x05, 0x00, 0x84, 0xFB, 0x64, 0x58, 0xFB, 0xBD, 0x01, 0xC1, 0xFB, + 0x78, 0x11, 0x98, 0x8E, 0x10, 0x42, 0xD5, 0x7E, 0xEB, 0x3B, 0xE1, 0xF8, + 0xAB, 0x3B, 0x31, 0xBA, 0xC5, 0xF8, 0x31, 0xF2, 0x34, 0x3A, 0x10, 0x1A, + 0xD8, 0x06, 0x30, 0xFA, 0x30, 0xDA, 0x31, 0x3A, 0x10, 0x32, 0xE4, 0x06, + 0x31, 0xBA, 0x31, 0xF2, 0xFD, 0x1C, 0x10, 0xC2, 0xEB, 0x6E, 0xE8, 0x3B, + 0x78, 0x09, 0x88, 0x0E, 0x3B, 0x09, 0xAC, 0x3B, 0xFD, 0x44, 0x10, 0xC2, + 0xE8, 0xA6, 0x00, 0x09, 0xFC, 0x3C, 0x00, 0x42, 0x18, 0xC2, 0x81, 0x3C, + 0x00, 0x77, 0xF8, 0x14, 0x10, 0xC2, 0xD5, 0x5E, 0xE8, 0x3B, 0x7B, 0x09, + 0x8C, 0x0E, 0x38, 0x09, 0xAD, 0x3B, 0x13, 0x42, 0xD0, 0x26, 0x00, 0x09, + 0xFC, 0x34, 0x00, 0x42, 0x18, 0xC2, 0x81, 0x34, 0xE3, 0x90, 0x34, 0x02, + 0xE4, 0x00, 0x32, 0x22, 0xE2, 0x48, 0x92, 0x4D, 0xC4, 0x2C, 0x10, 0x0A, + 0xD8, 0xC6, 0xC5, 0x4C, 0xE2, 0x00, 0x92, 0x05, 0x80, 0x4C, 0xC8, 0x24, + 0xC4, 0x4C, 0x10, 0x42, 0xD8, 0x76, 0xC5, 0x64, 0x59, 0x03, 0x82, 0x01, + 0xC0, 0x03, 0x44, 0x11, 0x99, 0x46, 0xEA, 0x03, 0x42, 0x11, 0xC8, 0x2E, + 0xF6, 0x00, 0x94, 0x05, 0x84, 0x04, 0xC8, 0xC8, 0x32, 0x82, 0xD3, 0x00, + 0xCF, 0x04, 0xB8, 0xF7, 0xE0, 0xFF, 0x96, 0x05, 0x80, 0x0C, 0x00, 0x01, + 0x13, 0x04, 0x0B, 0xE9, 0x08, 0x48, 0x10, 0x01, 0xF4, 0x54, 0x30, 0x22, + 0x00, 0x0F, 0x19, 0x01, 0x00, 0xC7, 0x00, 0x01, 0xF5, 0x82, 0x11, 0x42, + 0xD0, 0x8E, 0xF8, 0x0C, 0xD8, 0x00, 0xAE, 0x06, 0x10, 0x02, 0x92, 0x05, + 0x34, 0x3A, 0x10, 0x0A, 0xE0, 0x06, 0x30, 0x7A, 0x30, 0xCA, 0x31, 0x3A, + 0x10, 0x12, 0xDC, 0x06, 0x31, 0xBA, 0x30, 0xD2, 0x51, 0x3C, 0xC3, 0xC0, + 0x15, 0x04, 0xE3, 0xB0, 0xE2, 0xD8, 0x92, 0xDD, 0xC4, 0x2C, 0x10, 0x1A, + 0xDB, 0x1E, 0x37, 0x02, 0xE2, 0x00, 0x92, 0x05, 0x30, 0x22, 0xDC, 0x24, + 0x2E, 0xE2, 0xDC, 0xD6, 0x54, 0x04, 0xC3, 0x48, 0xD4, 0x00, 0x92, 0x05, + 0xCF, 0x04, 0xB8, 0xF7, 0xE3, 0xFF, 0x14, 0x04, 0xC0, 0x0C, 0x40, 0x01, + 0xD2, 0x06, 0x10, 0x02, 0x10, 0x04, 0x01, 0x17, 0x01, 0x01, 0x10, 0x04, + 0x10, 0x04, 0xC3, 0x3C, 0x18, 0x03, 0xC1, 0x34, 0x10, 0x03, 0x87, 0x6D, + 0xEE, 0x85, 0x37, 0x10, 0x70, 0x90, 0x0E, 0x09, 0x02, 0x8A, 0x4C, 0x00, + 0x54, 0x52, 0x00, 0x00, 0xC0, 0x00, 0x04, 0x0B, 0x38, 0x82, 0x03, 0x00, + 0xB0, 0x69, 0x01, 0x00, 0x18, 0x00, 0x03, 0x01, 0x20, 0xE0, 0x03, 0x00, + 0x70, 0x00, 0x05, 0x01, 0x00, 0x01, 0x00, 0x42, 0x78, 0x00, 0x05, 0x01, + 0x38, 0xE0, 0x06, 0x01, 0xE7, 0xC7, 0xF8, 0xFF, 0x08, 0x07, 0x00, 0x07, + 0x61, 0x28, 0x79, 0x68, 0x50, 0x50, 0x00, 0x78, 0x21, 0x10, 0x50, 0x80, + 0x00, 0x00, 0x08, 0x08, 0x30, 0x40, 0x28, 0x74, 0x58, 0xB0, 0x18, 0x28, + 0xF3, 0x50, 0x80, 0x22, 0x80, 0x02, 0x15, 0x40, 0x08, 0x80, 0x00, 0x00, + 0x50, 0xC0, 0x00, 0x28, 0x20, 0x30, 0xA0, 0xA0, 0x29, 0x50, 0xF0, 0x18, + 0x20, 0xE3, 0x41, 0x20, 0x10, 0x08, 0x40, 0x20, 0x10, 0x08, 0x20, 0x40, + 0x08, 0x10, 0x20, 0x40, 0x08, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x40, 0x20, + 0x10, 0x08, 0x40, 0x20, 0x10, 0x08, 0x40, 0x20, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x17, 0xEF, 0x06, 0xB0, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x08, 0x10, 0x10, 0x10, 0x60, 0x40, 0x00, 0x80, 0x48, 0x60, + 0x10, 0x08, 0x40, 0x08, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xF0, 0x40, + 0xE0, 0xF1, 0xA0, 0x00, 0xF0, 0x40, 0x1E, 0x00, 0x20, 0x10, 0x84, 0x80, + 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x00, 0xA0, 0x05, 0x48, 0x00, 0x40, 0x0E, 0x18, 0x12, 0x00, 0x00, 0x00, + 0x07, 0x00, 0xF8, 0xA7, 0x0C, 0x98, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x66, 0x06, 0x00, 0x40, 0x44, 0x04, 0x00, + 0x80, 0x20, 0x01, 0x42, 0x80, 0x20, 0x01, 0x42, 0x80, 0xA0, 0x01, 0x42, + 0x80, 0xA0, 0x01, 0x42, 0x80, 0xA0, 0x01, 0x42, 0x80, 0xA0, 0x01, 0x42, + 0x80, 0x20, 0x02, 0x42, 0x80, 0x20, 0x02, 0x42, 0x80, 0x20, 0x04, 0x42, + 0x80, 0x20, 0x04, 0x42, 0x80, 0x20, 0x04, 0x42, 0x80, 0x20, 0x04, 0x42, + 0x80, 0xA0, 0x03, 0x42, 0x80, 0xA0, 0x03, 0x42, 0x80, 0xA0, 0x03, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x02, 0x42, + 0x80, 0x20, 0x02, 0x42, 0x80, 0xA0, 0x02, 0x42, 0x80, 0xA0, 0x02, 0x42, + 0x80, 0xA0, 0x02, 0x42, 0x80, 0xA0, 0x02, 0x42, 0x80, 0x20, 0x03, 0x42, + 0x80, 0x20, 0x03, 0x42, 0x80, 0x20, 0x03, 0x42, 0x80, 0x20, 0x03, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x08, 0x01, 0x01, 0x42, 0x08, 0x41, 0x01, 0x42, + 0x08, 0x81, 0x01, 0x42, 0x08, 0xC1, 0x01, 0x42, 0x08, 0x01, 0x02, 0x42, + 0x08, 0x41, 0x02, 0x42, 0x08, 0x81, 0x02, 0x42, 0x08, 0xC1, 0x02, 0x42, + 0x08, 0x01, 0x03, 0x42, 0x08, 0x41, 0x03, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, 0x80, 0x20, 0x00, 0x42, + 0x80, 0x20, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x81, 0x02, 0x42, + 0x08, 0xC1, 0x02, 0x42, 0x08, 0x01, 0x03, 0x42, 0x08, 0x41, 0x03, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x41, 0x00, 0x42, 0x08, 0x81, 0x00, 0x42, + 0x08, 0xC1, 0x00, 0x42, 0x08, 0xC1, 0x01, 0x42, 0x08, 0x81, 0x01, 0x42, + 0x08, 0x41, 0x01, 0x42, 0x08, 0x01, 0x01, 0x42, 0x08, 0xC1, 0x00, 0x42, + 0x08, 0x81, 0x00, 0x42, 0x08, 0x41, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, 0x08, 0x01, 0x00, 0x42, + 0x08, 0x01, 0x00, 0x42, 0xF8, 0xFF, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0xF8, 0x0F, 0xF8, 0x07, 0xFF, 0xFF, 0x07, 0xF8, + 0x08, 0xF8, 0x0F, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0xB0, 0x3B, 0xC0, 0x0A, 0x18, 0x19, 0x28, 0x02, 0x28, 0x53, 0xB0, + 0x09, 0xC0, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x52, 0x08, 0x51, 0x18, + 0x54, 0xB0, 0x3A, 0x08, 0x03, 0x08, 0x51, 0x38, 0x54, 0x18, 0x51, 0x38, + 0x54, 0x90, 0x51, 0x38, 0x54, 0x90, 0x51, 0x38, 0x54, 0x90, 0x51, 0x38, + 0x04, 0x00, 0x50, 0x38, 0x54, 0x18, 0x51, 0x38, 0x50, 0x90, 0x01, 0x00, + 0x51, 0x38, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x50, 0x28, + 0x52, 0x38, 0x34, 0x88, 0x00, 0x38, 0x00, 0x28, 0x0B, 0x40, 0x51, 0xB0, + 0x50, 0x90, 0x00, 0x00, 0x01, 0x00, 0x50, 0xA0, 0x53, 0xB0, 0x0A, 0xC0, + 0x00, 0x08, 0x01, 0x00, 0x51, 0x38, 0x53, 0x18, 0x54, 0x08, 0x55, 0x38, + 0x53, 0x90, 0x51, 0x38, 0x54, 0x18, 0x51, 0x38, 0x55, 0x90, 0x51, 0x08, + 0x00, 0x08, 0xF8, 0x07, 0x00, 0xF8, 0x0F, 0x00, 0x10, 0x10, 0x08, 0x10, + 0x10, 0x10, 0x08, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x10, + 0x08, 0x08, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, + 0x7F, 0x00, 0x7F, 0x00, 0x06, 0x80, 0x51, 0x56, 0x6A, 0xDA, 0xAD, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, + 0x30, 0x00, 0xCA, 0xCA, 0xBB, 0x4D, 0x5E, 0x75, 0x51, 0x89, 0x52, 0x80, +}; + +#define FW_INFO_SIZE (0x18) +#define FW_REAL_SIZE (sizeof(fwbin)) +#define FW_BIN_SIZE (6 * 1024) + +#endif diff --git a/drivers/amlogic/input/touchscreen/hyn_cst2xx/hyncst226.c b/drivers/amlogic/input/touchscreen/hyn_cst2xx/hyncst226.c new file mode 100644 index 0000000..299c969 --- /dev/null +++ b/drivers/amlogic/input/touchscreen/hyn_cst2xx/hyncst226.c @@ -0,0 +1,1318 @@ +/* + * drivers/input/touchscreen/hyncst226.c + * + * Copyright (c) 2017 ShenZheng Hynitron + * Ying Zhang + * + * 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 + +#if defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include"cst226firmware.h" + +#define TP_RESET_PIN 3 +#define TP_I2C_ADAPTER (1) +#define TP_I2C_ADDR 0x1A +#define TP_NAME "CST226" +#define TP_IRQ_PORT 100 +#define TP_MAX_X 1024 +#define TP_MAX_Y 600 +static unsigned int gpio_reset; +static unsigned int gpio_irq; + +static unsigned int gpio_irq_exist; +static unsigned int gpio_reset_exist; + +#define CST226_I2C_NAME "cst226" +#define CST226_I2C_ADDR 0x1A + +#define CFG_TP_USE_CONFIG 1 +#if CFG_TP_USE_CONFIG +struct tp_cfg_xml { + unsigned int sirq; + unsigned int i2cNum; + unsigned int i2cAddr; + unsigned int xMax; + unsigned int yMax; + unsigned int rotate; + unsigned int xRevert; + unsigned int yRevert; +}; +static struct tp_cfg_xml cfg_xml; +#endif + +#define RESUME_INIT_CHIP_WORK + +#define REPORT_DATA_PROTOCOL_B +#define SLEEP_RESUME_CLEAR_POINT +#define ICS_SLOT_REPORT + +#define HIGH_SPEED_IIC_TRANSFER + +#define RECORD_POINT +#ifdef FILTER_POINT +#define FILTER_MAX 9 +#endif + +#define HYN_DATA_REG 0x80 +#define HYN_STATUS_REG 0xe0 +#define HYN_PAGE_REG 0xf0 + +#define PRESS_MAX 255 +#define MAX_FINGERS 10 +#define MAX_CONTACTS 10 +#define DMA_TRANS_LEN 0x10 + +#define SCREEN_MAX_X 600 +#define SCREEN_MAX_Y 1024 + +struct mutex mutex; + +static int power_is_on; + +#ifdef HYN_MONITOR +static struct delayed_work hyn_monitor_work; +static struct workqueue_struct *hyn_monitor_workqueue; +static char int_1st[4] = { 0 }; +static char int_2nd[4] = { 0 }; + +static char bc_counter; +static char b0_counter; +static char i2c_lock_flag; +static int clk_tick_cnt = 300; +#endif +static struct i2c_client *hyn_client; + +static struct hyn_ts *this_ts; + +#ifdef HAVE_TOUCH_KEY +static u16 key; + +static int key_state_flag; +struct key_data { + u16 key; + u16 x_min; + u16 x_max; + u16 y_min; + u16 y_max; +}; + +const u16 key_array[] = { + KEY_BACK, + KEY_HOME, + KEY_MENU, + KEY_SEARCH, +}; + +struct key_data hyn_key_data[ARRAY_SIZE(key_array)] = { + {KEY_BACK, 2048, 2048, 2048, 2048}, + {KEY_HOME, 2048, 2048, 2048, 2048}, + {KEY_MENU, 2048, 2048, 2048, 2048}, + {KEY_SEARCH, 2048, 2048, 2048, 2048}, +}; +#endif + +struct hyn_ts_data { + u8 x_index; + u8 y_index; + u8 z_index; + u8 id_index; + u8 touch_index; + u8 data_reg; + u8 status_reg; + u8 data_size; + u8 touch_bytes; + u8 update_data; + u8 touch_meta_data; + u8 finger_size; +}; + +static struct hyn_ts_data devices[] = { + { + .x_index = 6, + .y_index = 4, + .z_index = 5, + .id_index = 7, + .data_reg = HYN_DATA_REG, + .status_reg = HYN_STATUS_REG, + .update_data = 0x4, + .touch_bytes = 4, + .touch_meta_data = 4, + .finger_size = 70, + }, +}; + +struct hyn_ts { + struct i2c_client *client; + struct input_dev *input; + struct work_struct work; + struct workqueue_struct *wq; +#ifdef RESUME_INIT_CHIP_WORK + struct work_struct init_work; + struct workqueue_struct *init_wq; +#endif + struct hyn_ts_data *dd; + u8 *touch_data; + u8 device_id; + int irq; +#if defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif +}; + +#define CTP_POWER_ID ("sensor28") +#define CTP_POWER_MIN_VOL (3300000) +#define CTP_POWER_MAX_VOL (3300000) + +int current_val; + +static int cst226_shutdown_low(void) +{ + gpio_direction_output(gpio_reset, 0); + return 0; +} + +static int cst226_shutdown_high(void) +{ + gpio_direction_output(gpio_reset, 1); + return 0; +} + +#ifdef HIGH_SPEED_IIC_TRANSFER + +static int cst2xx_i2c_read_register(struct i2c_client *client, + unsigned char *buf, int len) +{ + struct i2c_msg msgs[2]; + int ret = -1; + int retries = 0; + + msgs[0].flags = 0; + msgs[0].addr = client->addr; + msgs[0].len = 2; + msgs[0].buf = buf; + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = client->addr; + msgs[1].len = len; + msgs[1].buf = buf; + + while (retries < 5) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) + break; + retries++; + } + + return ret; +} + +static int cst2xx_i2c_write(struct i2c_client *client, unsigned char *buf, + int len) +{ + struct i2c_msg msg; + int ret = -1; + int retries = 0; + + msg.flags = 0; + 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++; + } + + return ret; +} +#else +static int cst2xx_i2c_read(struct i2c_client *client, unsigned char *buf, + int len) +{ + int ret = -1; + int retries = 0; + + while (retries < 5) { + ret = i2c_master_recv(client, buf, len); + if (ret <= 0) + retries++; + else + break; + } + + return ret; +} + +static int cst2xx_i2c_write(struct i2c_client *client, unsigned char *buf, + int len) +{ + int ret = -1; + int retries = 0; + + while (retries < 5) { + ret = i2c_master_send(client, buf, len); + if (ret <= 0) + retries++; + else + break; + } + + return ret; +} + +static int cst2xx_i2c_read_register(struct i2c_client *client, + unsigned char *buf, int len) +{ + int ret = -1; + + ret = cst2xx_i2c_write(client, buf, 2); + + ret = cst2xx_i2c_read(client, buf, len); + + return ret; +} +#endif +static int test_i2c(struct i2c_client *client) +{ + int retry = 0; + int ret; + u8 buf[4]; + + buf[0] = 0xD1; + buf[1] = 0x06; + while (retry++ < 2) { + ret = cst2xx_i2c_write(client, buf, 2); + if (ret > 0) + return ret; + + usleep_range(2000, 2010); + } + + return ret; +} + +void hard_reset_chip(int delay) +{ + cst226_shutdown_high(); + msleep(delay); + cst226_shutdown_low(); + msleep(delay); + cst226_shutdown_high(); +} + +#if CFG_TP_USE_CONFIG +static int tp_get_config(struct i2c_client *client) +{ + struct device_node *np; + + np = client->dev.of_node; + gpio_irq = of_get_named_gpio(np, "irq-gpio", 0); + gpio_reset = of_get_named_gpio(np, "reset-gpio", 0); + + if (!gpio_is_valid(gpio_irq) || !gpio_is_valid(gpio_reset)) + return -EINVAL; + + gpio_reset_exist = 1; + gpio_irq_exist = 1; + + cfg_xml.xMax = TP_MAX_X; + cfg_xml.yMax = TP_MAX_Y; + cfg_xml.xRevert = 0; + cfg_xml.yRevert = 0; + cfg_xml.rotate = 1; + + if (gpio_irq_exist == 1) { + if (gpio_request(gpio_irq, "ts_irq_gpio") != 0) { + gpio_free(gpio_irq); + return -EIO; + } + gpio_direction_input(gpio_irq); + } + if (gpio_reset_exist == 1) { + if (gpio_request(gpio_reset, CST226_I2C_NAME) != 0) { + gpio_free(gpio_reset); + return -EIO; + } + } + + return 0; +} +#endif + +#define CST2XX_BASE_ADDR (24 * 1024) +static int cst2xx_enter_download_mode(struct i2c_client *client) +{ + int ret; + int i; + u8 buf[2]; + + hard_reset_chip(5); + + for (i = 0; i < 20; i++) { + buf[0] = 0xD1; + buf[1] = 0x11; + ret = cst2xx_i2c_write(client, buf, 2); + if (ret < 0) { + usleep_range(1000, 1010); + continue; + } + + usleep_range(4000, 4010); + + buf[0] = 0xD0; + buf[1] = 0x01; + ret = cst2xx_i2c_read_register(client, buf, 1); + if (ret < 0) { + usleep_range(1000, 1010); + continue; + } + + if (buf[0] == 0x55) + break; + } + + if (buf[0] != 0x55) + return -1; + + buf[0] = 0xD1; + buf[1] = 0x10; + ret = cst2xx_i2c_write(client, buf, 2); + if (ret < 0) + return -1; + + return 0; +} + +static int cst2xx_download_program(struct i2c_client *client, + unsigned char *data, int len) +{ + int ret; + int i, j; + unsigned int wr_addr; + unsigned char *pData; + unsigned char *pSrc; + unsigned char *pDst; + unsigned char i2c_buf[8]; + + pData = kmalloc(sizeof(unsigned char) * (1024 + 4), GFP_KERNEL); + if (pData == NULL) + return -1; + + pSrc = data; + + for (i = 0; i < (len / 1024); i++) { + wr_addr = (i << 10) + CST2XX_BASE_ADDR; + + pData[0] = (wr_addr >> 24) & 0xFF; + pData[1] = (wr_addr >> 16) & 0xFF; + pData[2] = (wr_addr >> 8) & 0xFF; + pData[3] = wr_addr & 0xFF; + + pDst = pData + 4; + + for (j = 0; j < 256; j++) { + *pDst = *(pSrc + 3); + *(pDst + 1) = *(pSrc + 2); + *(pDst + 2) = *(pSrc + 1); + *(pDst + 3) = *pSrc; + + pDst += 4; + pSrc += 4; + } + +#ifdef HIGH_SPEED_IIC_TRANSFER + for (j = 0; j < 256; j++) { + i2c_buf[0] = (wr_addr >> 24) & 0xFF; + i2c_buf[1] = (wr_addr >> 16) & 0xFF; + i2c_buf[2] = (wr_addr >> 8) & 0xFF; + i2c_buf[3] = wr_addr & 0xFF; + + i2c_buf[4] = pData[j * 4 + 4 + 0]; + i2c_buf[5] = pData[j * 4 + 4 + 1]; + i2c_buf[6] = pData[j * 4 + 4 + 2]; + i2c_buf[7] = pData[j * 4 + 4 + 3]; + + ret = cst2xx_i2c_write(client, i2c_buf, 8); + if (ret < 0) + goto ERR_OUT; + + wr_addr += 4; + } +#else + ret = cst2xx_i2c_write(client, pData, 1024 + 4); + if (ret < 0) + goto ERR_OUT; +#endif + } + + pData[3] = 0x20000FFC & 0xFF; + pData[2] = (0x20000FFC >> 8) & 0xFF; + pData[1] = (0x20000FFC >> 16) & 0xFF; + pData[0] = (0x20000FFC >> 24) & 0xFF; + pData[4] = 0x00; + pData[5] = 0x00; + pData[6] = 0x00; + pData[7] = 0x00; + ret = cst2xx_i2c_write(client, pData, 8); + if (ret < 0) + goto ERR_OUT; + + pData[3] = 0xD013D013 & 0xFF; + pData[2] = (0xD013D013 >> 8) & 0xFF; + pData[1] = (0xD013D013 >> 16) & 0xFF; + pData[0] = (0xD013D013 >> 24) & 0xFF; + ret = cst2xx_i2c_write(client, pData, 4); + if (ret < 0) + goto ERR_OUT; + + if (pData != NULL) { + kfree(pData); + pData = NULL; + } + return 0; + +ERR_OUT: + if (pData != NULL) { + kfree(pData); + pData = NULL; + } + return -1; +} + +static int cst2xx_read_checksum(struct i2c_client *client) +{ + int ret; + int i; + unsigned int checksum; + unsigned int bin_checksum; + unsigned char buf[4]; + unsigned char *pData; + + for (i = 0; i < 10; i++) { + buf[0] = 0xD0; + buf[1] = 0x00; + ret = cst2xx_i2c_read_register(client, buf, 1); + if (ret < 0) { + usleep_range(2000, 2010); + continue; + } + + if ((buf[0] == 0x01) || (buf[0] == 0x02)) + break; + + usleep_range(2000, 2010); + } + + if ((buf[0] == 0x01) || (buf[0] == 0x02)) { + buf[0] = 0xD0; + buf[1] = 0x08; + ret = cst2xx_i2c_read_register(client, buf, 4); + + if (ret < 0) + return -1; + + checksum = + buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); + + pData = fwbin + 6160; //6*1024+16 + bin_checksum = + pData[0] + (pData[1] << 8) + (pData[2] << 16) + + (pData[3] << 24); + + buf[0] = 0xD0; + buf[1] = 0x01; + buf[2] = 0xA5; + ret = cst2xx_i2c_write(client, buf, 3); + + if (ret < 0) + return -1; + } else { + return -1; + } + + return 0; +} + +static int cst2xx_update_firmware(struct i2c_client *client, + unsigned char *pdata, int data_len) +{ + int ret; + int retry; + + retry = 0; + +start_flow: + ret = cst2xx_enter_download_mode(client); + if (ret < 0) + goto fail_retry; + + ret = cst2xx_download_program(client, pdata, data_len); + if (ret < 0) + goto fail_retry; + + usleep_range(3000, 3010); + + ret = cst2xx_read_checksum(client); + if (ret < 0) + goto fail_retry; + + return 0; + +fail_retry: + if (retry < 4) { + retry++; + goto start_flow; + } + + return -1; +} + +static int cst2xx_boot_update_fw(struct i2c_client *client) +{ + return cst2xx_update_firmware(client, fwbin, FW_BIN_SIZE); +} + +static int cst2xx_check_code(struct i2c_client *client) +{ + int retry = 0; + int ret; + unsigned char buf[4]; + + buf[0] = 0xD0; + buf[1] = 0x4C; + while (retry++ < 3) { + ret = cst2xx_i2c_read_register(client, buf, 1); + if (ret > 0) + break; + usleep_range(2000, 2010); + } + + if ((buf[0] == 226) || (buf[0] == 237) || (buf[0] == 240)) + return 0; + + ret = cst2xx_boot_update_fw(client); + if (ret < 0) + return -2; + else + return 0; +} + +static void init_chip(struct i2c_client *client) +{ + int rc; + + if (gpio_reset_exist == 1) { + cst226_shutdown_low(); + msleep(20); + cst226_shutdown_high(); + msleep(20); + } + rc = test_i2c(client); + if (rc <= 0) + return; + + cst2xx_boot_update_fw(client); +} + +static void cst2xx_touch_down(struct input_dev *input_dev, s32 id, s32 x, s32 y, + s32 w) +{ + + s32 temp_w = (w >> 1); + s32 temp = 0; + + temp_w += (temp & 0x0007); + x = x * cfg_xml.xMax / 2048; + y = y * cfg_xml.yMax / 2048; +#if CFG_TP_USE_CONFIG + if (cfg_xml.rotate == 1) { + int tmp; + + tmp = x; + x = y; + y = cfg_xml.xMax - tmp; + } else if (cfg_xml.rotate == 2) { + x = cfg_xml.xMax - x; + y = cfg_xml.yMax - y; + } else if (cfg_xml.rotate == 3) { + int tmp; + + tmp = x; + x = cfg_xml.yMax - y; + y = tmp; + } + if (cfg_xml.xRevert == 1) + x = cfg_xml.xMax - x; + + if (cfg_xml.yRevert == 1) + y = cfg_xml.yMax - y; +#endif + +#ifdef ICS_SLOT_REPORT + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1); + input_report_abs(input_dev, ABS_MT_TRACKING_ID, id); + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, temp_w); + input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, temp_w); +#else + input_report_key(input_dev, BTN_TOUCH, 1); + input_report_abs(input_dev, ABS_MT_POSITION_X, x); + input_report_abs(input_dev, ABS_MT_POSITION_Y, y); + input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, temp_w); + input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, temp_w); + input_report_abs(input_dev, ABS_MT_TRACKING_ID, id); + input_mt_sync(input_dev); +#endif + +} + +static void cst2xx_touch_up(struct input_dev *input_dev, int id) +{ +#ifdef ICS_SLOT_REPORT + input_mt_slot(input_dev, id); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0); +#else + input_report_key(input_dev, BTN_TOUCH, 0); + input_mt_sync(input_dev); +#endif +} + +int report_flag; +static void hyn_ts_xy_worker(struct work_struct *work) +{ + u8 buf[30]; + u8 i2c_buf[8]; + u8 key_status, key_id, finger_id, sw; + u16 input_x = 0; + u16 input_y = 0; + u16 input_w = 0; + u8 cnt_up, cnt_down; + int i, ret, idx; + int cnt, i2c_len, len_1, len_2; + + struct hyn_ts *ts = container_of(work, struct hyn_ts, work); + + key_status = 0; +#ifdef HYN_MONITOR + if (i2c_lock_flag == 0) + i2c_lock_flag = 1; + else + return; +#endif + + buf[0] = 0xD0; + buf[1] = 0x00; + ret = cst2xx_i2c_read_register(ts->client, buf, 7); + if (ret < 0) + goto OUT_PROCESS; + + if (buf[0] == 0xAB) + goto OUT_PROCESS; + + if (buf[6] != 0xAB) + goto OUT_PROCESS; + + cnt = buf[5] & 0x7F; + if (cnt > MAX_FINGERS) + goto OUT_PROCESS; + + if (buf[5] == 0x80) { + key_status = buf[0]; + key_id = buf[1]; + goto KEY_PROCESS; + } else if (cnt == 0x01) { + goto FINGER_PROCESS; + } else { +#ifdef HIGH_SPEED_IIC_TRANSFER + if ((buf[5] & 0x80) == 0x80) { + i2c_len = (cnt - 1) * 5 + 3; + len_1 = i2c_len; + for (idx = 0; idx < i2c_len; idx += 6) { + i2c_buf[0] = 0xD0; + i2c_buf[1] = 0x07 + idx; + + if (len_1 >= 6) { + len_2 = 6; + len_1 -= 6; + } else { + len_2 = len_1; + len_1 = 0; + } + + ret = + cst2xx_i2c_read_register(ts->client, + i2c_buf, len_2); + if (ret < 0) + goto OUT_PROCESS; + + for (i = 0; i < len_2; i++) + buf[5 + idx + i] = i2c_buf[i]; + } + + i2c_len += 5; + key_status = buf[i2c_len - 3]; + key_id = buf[i2c_len - 2]; + } else { + i2c_len = (cnt - 1) * 5 + 1; + len_1 = i2c_len; + + for (idx = 0; idx < i2c_len; idx += 6) { + i2c_buf[0] = 0xD0; + i2c_buf[1] = 0x07 + idx; + + if (len_1 >= 6) { + len_2 = 6; + len_1 -= 6; + } else { + len_2 = len_1; + len_1 = 0; + } + + ret = + cst2xx_i2c_read_register(ts->client, + i2c_buf, len_2); + if (ret < 0) + goto OUT_PROCESS; + + for (i = 0; i < len_2; i++) + buf[5 + idx + i] = i2c_buf[i]; + } + i2c_len += 5; + } +#else + if ((buf[5] & 0x80) == 0x80) { + buf[5] = 0xD0; + buf[6] = 0x07; + i2c_len = (cnt - 1) * 5 + 3; + ret = + cst2xx_i2c_read_register(ts->client, &buf[5], + i2c_len); + if (ret < 0) + goto OUT_PROCESS; + i2c_len += 5; + key_status = buf[i2c_len - 3]; + key_id = buf[i2c_len - 2]; + } else { + buf[5] = 0xD0; + buf[6] = 0x07; + i2c_len = (cnt - 1) * 5 + 1; + ret = + cst2xx_i2c_read_register(ts->client, &buf[5], + i2c_len); + if (ret < 0) + goto OUT_PROCESS; + i2c_len += 5; + } +#endif + + if (buf[i2c_len - 1] != 0xAB) + goto OUT_PROCESS; + } + + if ((cnt > 0) && (key_status & 0x80)) { + if (report_flag == 0xA5) + goto KEY_PROCESS; + } + +FINGER_PROCESS: + + i2c_buf[0] = 0xD0; + i2c_buf[1] = 0x00; + i2c_buf[2] = 0xAB; + ret = cst2xx_i2c_write(ts->client, i2c_buf, 3); + if (ret < 0) + hard_reset_chip(20); + + idx = 0; + cnt_up = 0; + cnt_down = 0; + for (i = 0; i < cnt; i++) { + input_x = + (unsigned int)((buf[idx + 1] << 4) | + ((buf[idx + 3] >> 4) & 0x0F)); + input_y = + (unsigned int)((buf[idx + 2] << 4) | (buf[idx + 3] & 0x0F)); + input_w = (unsigned int)(buf[idx + 4]); + sw = (buf[idx] & 0x0F) >> 1; + finger_id = (buf[idx] >> 4) & 0x0F; + + if (sw == 0x03) { + cst2xx_touch_down(ts->input, finger_id, input_x, + input_y, input_w); + cnt_down++; + } else { + cnt_up++; + cst2xx_touch_up(ts->input, finger_id); + } + idx += 5; + } + + if (cnt_down == 0) + report_flag = 0; + else + report_flag = 0xCA; + + input_sync(ts->input); + + goto XY_WORK_END; + +KEY_PROCESS: + + i2c_buf[0] = 0xD0; + i2c_buf[1] = 0x00; + i2c_buf[2] = 0xAB; + ret = cst2xx_i2c_write(ts->client, i2c_buf, 3); + if (ret < 0) + hard_reset_chip(20); +#ifdef TPD_HAVE_BUTTON + if (key_status & 0x80) { + if ((key_status & 0x7F) == 0x03) { + i = (key_id >> 4) - 1; + cst2xx_touch_down(ts->input, tpd_keys_dim_local[i][0], + tpd_keys_dim_local[i][1], 0, 0); + report_flag = 0xA5; + } else { + cst2xx_touch_up(ts->input, 0); + report_flag = 0; + } + } +#endif + + input_sync(ts->input); + + goto XY_WORK_END; + +OUT_PROCESS: + buf[0] = 0xD0; + buf[1] = 0x00; + buf[2] = 0xAB; + ret = cst2xx_i2c_write(ts->client, buf, 3); + if (ret < 0) + hard_reset_chip(20); + +XY_WORK_END: +#ifdef HYN_MONITOR + i2c_lock_flag = 0; +i2c_lock_schedule:; +#endif + + return; +} + +#ifdef HYN_MONITOR +static void hyn_monitor_worker(struct work_struct *work) +{ + int retry = 0; + int ret; + unsigned char buf[4]; + + if (i2c_lock_flag != 0) + goto MONITOR_END; + else + i2c_lock_flag = 1; + + buf[0] = 0xD0; + buf[1] = 0x4C; + + while (retry++ < 3) { + ret = cst2xx_i2c_read_register(this_ts->client, buf, 1); + if (ret > 0) + break; + + usleep_range(2000, 2010); + } + + if ((retry > 3) + || ((buf[0] != 226) && (buf[0] != 237) && (buf[0] != 240))) { + + hard_reset_chip(20); + + cst2xx_check_code(this_ts->client); + } + + i2c_lock_flag = 0; + +MONITOR_END: + queue_delayed_work(hyn_monitor_workqueue, &hyn_monitor_work, + clk_tick_cnt); +} +#endif + +#ifdef RESUME_INIT_CHIP_WORK +static void cst226_init_worker(struct work_struct *work) +{ + init_chip(this_ts->client); + cst2xx_check_code(this_ts->client); + +} +#endif + +static irqreturn_t hyn_ts_irq(int irq, void *dev_id) +{ + struct hyn_ts *ts = dev_id; + + disable_irq_nosync(ts->irq); + + if (!work_pending(&ts->work)) + queue_work(ts->wq, &ts->work); + + enable_irq(ts->irq); + return IRQ_HANDLED; +} + +static int cst226_ts_init(struct i2c_client *client, struct hyn_ts *ts) +{ + struct input_dev *input_device; + int rc = 0; + + ts->dd = &devices[ts->device_id]; + + if (ts->device_id == 0) { + ts->dd->data_size = + MAX_FINGERS * ts->dd->touch_bytes + ts->dd->touch_meta_data; + ts->dd->touch_index = 0; + } + + ts->touch_data = kzalloc(ts->dd->data_size, GFP_KERNEL); + if (!ts->touch_data) + return -ENOMEM; + + input_device = input_allocate_device(); + if (!input_device) { + rc = -ENOMEM; + goto error_alloc_dev; + } + + ts->input = input_device; + input_device->name = TP_NAME; + input_device->id.bustype = BUS_I2C; + input_device->dev.parent = &client->dev; + input_set_drvdata(input_device, ts); + + __set_bit(EV_ABS, input_device->evbit); + __set_bit(INPUT_PROP_DIRECT, input_device->propbit); + input_mt_init_slots(input_device, MAX_CONTACTS, 0); + input_set_abs_params(input_device, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(input_device, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + +#if CFG_TP_USE_CONFIG + if (cfg_xml.rotate == 1 || cfg_xml.rotate == 3) { + input_set_abs_params(input_device, ABS_MT_POSITION_Y, 0, + cfg_xml.xMax, 0, 0); + input_set_abs_params(input_device, ABS_MT_POSITION_X, 0, + cfg_xml.yMax, 0, 0); + } else { + input_set_abs_params(input_device, ABS_MT_POSITION_X, 0, + cfg_xml.xMax, 0, 0); + input_set_abs_params(input_device, ABS_MT_POSITION_Y, 0, + cfg_xml.yMax, 0, 0); + } +#else + input_set_abs_params(input_device, ABS_MT_POSITION_X, 0, TP_MAX_X, 0, + 0); + input_set_abs_params(input_device, ABS_MT_POSITION_Y, 0, TP_MAX_Y, 0, + 0); +#endif + +#ifdef HAVE_TOUCH_KEY + set_bit(EV_KEY, input_device->evbit); + input_device->evbit[0] = BIT_MASK(EV_KEY); + for (i = 0; i < ARRAY_SIZE(key_array); i++) + set_bit(key_array[i], input_device->keybit); +#endif + +#if CFG_TP_USE_CONFIG + if (gpio_irq_exist == 0) + client->irq = 4; + else if (gpio_irq_exist == 1) + client->irq = gpio_to_irq(gpio_irq); +#else + client->irq = TP_IRQ_PORT; +#endif + ts->irq = client->irq; + + ts->wq = create_singlethread_workqueue("kworkqueue_ts"); + if (!ts->wq) { + dev_err(&client->dev, "Could not create workqueue\n"); + goto error_wq_create; + } + flush_workqueue(ts->wq); + + INIT_WORK(&ts->work, hyn_ts_xy_worker); + +#ifdef RESUME_INIT_CHIP_WORK + ts->init_wq = create_singlethread_workqueue("ts_init_wq"); + if (!ts->init_wq) { + dev_err(&client->dev, + "Could not create ts_init_wq workqueue\n"); + goto error_wq_create; + } + flush_workqueue(ts->init_wq); + INIT_WORK(&ts->init_work, cst226_init_worker); +#endif + rc = input_register_device(input_device); + if (rc) + goto error_unreg_device; + + this_ts = ts; + + return 0; + +error_unreg_device: + destroy_workqueue(ts->wq); +error_wq_create: + input_free_device(input_device); +error_alloc_dev: + kfree(ts->touch_data); + return rc; +} + +static int hyn_ts_suspend(struct device *dev) +{ + flush_workqueue(this_ts->init_wq); + if (gpio_reset_exist == 1) + cst226_shutdown_low(); + msleep(20); + + msleep(20); + + return 0; +} + +static int hyn_ts_early_resume(struct device *dev) +{ + queue_work(this_ts->init_wq, &this_ts->init_work); + + power_is_on = 1; + + return 0; +} + +static int hyn_ts_resume(struct device *dev) +{ + if (power_is_on == 0) { + queue_work(this_ts->init_wq, &this_ts->init_work); + power_is_on = 1; + } + + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void hyn_ts_early_suspend(struct early_suspend *h) +{ + disable_irq_nosync(this_ts->irq); + +#ifdef SLEEP_RESUME_CLEAR_POINT +#ifdef REPORT_DATA_PROTOCOL_B + int i = 0; + + for (i = 1; i <= MAX_CONTACTS; i++) { + input_mt_slot(this_ts->input, i); + input_mt_report_slot_state(this_ts->input, MT_TOOL_FINGER, + false); + } +#endif + input_sync(this_ts->input); +#endif + + flush_workqueue(this_ts->wq); + +#ifdef HYN_MONITOR + cancel_delayed_work_sync(&hyn_monitor_work); +#endif +} + +static void hyn_ts_late_resume(struct early_suspend *h) +{ + +#ifdef HYN_MONITOR + queue_delayed_work(hyn_monitor_workqueue, &hyn_monitor_work, 500); +#endif + enable_irq(this_ts->irq); +#ifdef SLEEP_RESUME_CLEAR_POINT +#ifdef REPORT_DATA_PROTOCOL_B + int i = 0; + + for (i = 1; i <= MAX_CONTACTS; i++) { + input_mt_slot(this_ts->input, i); + input_mt_report_slot_state(this_ts->input, MT_TOOL_FINGER, + false); + } +#endif + input_sync(this_ts->input); +#endif + +} +#endif + +static int hyn_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct hyn_ts *ts; + int rc; + +#if CFG_TP_USE_CONFIG + rc = tp_get_config(client); + if (rc < 0) + return -ENODEV; +#endif + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C functionality not supported\n"); + return -ENODEV; + } + + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + hyn_client = client; + ts->client = client; + i2c_set_clientdata(client, ts); + ts->device_id = id->driver_data; + + rc = cst226_ts_init(client, ts); + if (rc < 0) { + dev_err(&client->dev, "cst226 init failed\n"); + goto error_mutex_destroy; + } + + init_chip(ts->client); + cst2xx_check_code(ts->client); + + rc = request_irq(client->irq, hyn_ts_irq, IRQF_TRIGGER_RISING, + client->name, ts); + if (rc < 0) + goto error_req_irq_fail; + +#ifdef CONFIG_HAS_EARLYSUSPEND + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = hyn_ts_early_suspend; + ts->early_suspend.resume = hyn_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif + mutex_init(&mutex); +#ifdef HYN_MONITOR + INIT_DELAYED_WORK(&hyn_monitor_work, hyn_monitor_worker); + hyn_monitor_workqueue = + create_singlethread_workqueue("hyn_monitor_workqueue"); + queue_delayed_work(hyn_monitor_workqueue, &hyn_monitor_work, 500); +#endif + + return 0; + +error_req_irq_fail: + free_irq(ts->irq, ts); + +error_mutex_destroy: + input_free_device(ts->input); + kfree(ts); + return rc; +} + +static int hyn_ts_remove(struct i2c_client *client) +{ + struct hyn_ts *ts = i2c_get_clientdata(client); + +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&ts->early_suspend); +#endif + + device_init_wakeup(&client->dev, 0); + cancel_work_sync(&ts->work); + free_irq(ts->irq, ts); + destroy_workqueue(ts->wq); + cancel_work_sync(&ts->init_work); + destroy_workqueue(ts->init_wq); + input_unregister_device(ts->input); +#ifdef HYN_MONITOR + cancel_delayed_work_sync(&hyn_monitor_work); + destroy_workqueue(hyn_monitor_workqueue); +#endif + +#if CFG_TP_USE_CONFIG + gpio_free(gpio_irq); + gpio_free(gpio_reset); +#endif + kfree(ts->touch_data); + kfree(ts); + + return 0; +} + +static const struct of_device_id hyn_match_table[] = { + {.compatible = "hyn, cst226",}, + {}, +}; + +static const struct i2c_device_id hyn_ts_id[] = { + {CST226_I2C_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, hyn_ts_id); +static unsigned short hyn_addresses[] = { + CST226_I2C_ADDR, + I2C_CLIENT_END, +}; + +static const struct dev_pm_ops tp_pm_ops = { + .resume_early = hyn_ts_early_resume, + .suspend = hyn_ts_suspend, + .resume = hyn_ts_resume, +}; + +static struct i2c_driver hyn_ts_driver = { + .driver = { + .name = CST226_I2C_NAME, + .owner = THIS_MODULE, + .pm = &tp_pm_ops, + .of_match_table = hyn_match_table, + }, + .probe = hyn_ts_probe, + .remove = hyn_ts_remove, + .id_table = hyn_ts_id, + .address_list = hyn_addresses, +}; + +module_i2c_driver(hyn_ts_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("CST2XX touchscreen controller driver"); +MODULE_AUTHOR("Ying Zhang, ying.zhang@hynitron.com.cn"); +MODULE_ALIAS("platform:HYN_ts"); -- 2.7.4