diff --git a/Documentation/ABI/testing/sysfs-device-mali b/Documentation/ABI/testing/sysfs-device-mali index 12a1667feeb2..c6326b3ca9ad 100644 --- a/Documentation/ABI/testing/sysfs-device-mali +++ b/Documentation/ABI/testing/sysfs-device-mali @@ -1,15 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2017-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software - * Foundation) and any use by you of this program is subject to the terms - * of such GNU licence. + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. * - * A copy of the licence is included with the program) and can also be obtained - * from Free Software Foundation) Inc.) 51 Franklin Street) Fifth Floor) - * Boston) MA 02110-1301) USA. + * 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, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. * */ @@ -34,16 +40,6 @@ Description: driver, On reading it provides the current DVFS sampling period, on writing a value we set the DVFS sampling period. -What: /sys/class/misc/mali%u/device/dummy_job_wa_info -Description: - This attribute is available only with platform device that - supports a Job Manager based GPU that requires a GPU workaround - to execute the dummy fragment job on all shader cores to - workaround a hang issue. - - Its a readonly attribute and on reading gives details on the - options used with the dummy workaround. - What: /sys/class/misc/mali%u/device/fw_timeout Description: This attribute is available only with mali platform @@ -78,111 +74,6 @@ Description: is supported or is powered down after suspending command stream groups. -What: /sys/class/misc/mali%u/device/js_ctx_scheduling_mode -Description: - This attribute is available only with platform device that - supports a Job Manager based GPU. This attribute is used to set - context scheduling priority for a job slot. - - On Reading it provides the currently set job slot context - priority. - - Writing 0 to this attribute sets it to the mode were - higher priority atoms will be scheduled first, regardless of - the context they belong to. Newly-runnable higher priority atoms - can preempt lower priority atoms currently running on the GPU, - even if they belong to a different context. - - Writing 1 to this attribute set it to the mode were the - highest-priority atom will be chosen from each context in turn - using a round-robin algorithm, so priority only has an effect - within the context an atom belongs to. Newly-runnable higher - priority atoms can preempt the lower priority atoms currently - running on the GPU, but only if they belong to the same context. - -What: /sys/class/misc/mali%u/device/js_scheduling_period -Description: - This attribute is available only with platform device that - supports a Job Manager based GPU. Used to set the job scheduler - tick period in nano-seconds. The Job Scheduler determines the - jobs that are run on the GPU, and for how long, Job Scheduler - makes decisions at a regular time interval determined by value - in js_scheduling_period. - -What: /sys/class/misc/mali%u/device/js_softstop_always -Description: - This attribute is available only with platform device that - supports a Job Manager based GPU. Soft-stops are disabled when - only a single context is present, this attribute is used to - enable soft-stop when only a single context is present can be - used for debug and unit-testing purposes. - -What: /sys/class/misc/mali%u/device/js_timeouts -Description: - This attribute is available only with platform device that - supports a Job Manager based GPU. It used to set the soft stop - and hard stop times for the job scheduler. - - Writing value 0 causes no change, or -1 to restore the - default timeout. - - The format used to set js_timeouts is - " - - " - - -What: /sys/class/misc/mali%u/device/lp_mem_pool_max_size -Description: - This attribute is used to set the maximum number of large pages - memory pools that the driver can contain. Large pages are of - size 2MB. On read it displays all the max size of all memory - pools and can be used to modify each individual pools as well. - -What: /sys/class/misc/mali%u/device/lp_mem_pool_size -Description: - This attribute is used to set the number of large memory pages - which should be populated, changing this value may cause - existing pages to be removed from the pool, or new pages to be - created and then added to the pool. On read it will provide - pool size for all available pools and we can modify individual - pool. - -What: /sys/class/misc/mali%u/device/mem_pool_max_size -Description: - This attribute is used to set the maximum number of small pages - for memory pools that the driver can contain. Here small pages - are of size 4KB. On read it will display the max size for all - available pools and allows us to set max size of - individual pools. - -What: /sys/class/misc/mali%u/device/mem_pool_size -Description: - This attribute is used to set the number of small memory pages - which should be populated, changing this value may cause - existing pages to be removed from the pool, or new pages to - be created and then added to the pool. On read it will provide - pool size for all available pools and we can modify individual - pool. - -What: /sys/class/misc/mali%u/device/device/mempool/ctx_default_max_size -Description: - This attribute is used to set maximum memory pool size for - all the memory pool so that the maximum amount of free memory - that each pool can hold is identical. - -What: /sys/class/misc/mali%u/device/device/mempool/lp_max_size -Description: - This attribute is used to set the maximum number of large pages - for all memory pools that the driver can contain. - Large pages are of size 2MB. - -What: /sys/class/misc/mali%u/device/device/mempool/max_size -Description: - This attribute is used to set the maximum number of small pages - for all the memory pools that the driver can contain. - Here small pages are of size 4KB. - What: /sys/class/misc/mali%u/device/pm_poweroff Description: This attribute contains the current values, represented as the diff --git a/Documentation/ABI/testing/sysfs-device-mali-coresight-source b/Documentation/ABI/testing/sysfs-device-mali-coresight-source index 58d9085b8bb6..c8453702bdd9 100644 --- a/Documentation/ABI/testing/sysfs-device-mali-coresight-source +++ b/Documentation/ABI/testing/sysfs-device-mali-coresight-source @@ -1,15 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2017-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software - * Foundation) and any use by you of this program is subject to the terms - * of such GNU licence. + * Foundation, and any use by you of this program is subject to the terms + * of such GNU license. * - * A copy of the licence is included with the program) and can also be obtained - * from Free Software Foundation) Inc.) 51 Franklin Street) Fifth Floor) - * Boston) MA 02110-1301) USA. + * 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, you can access it online at + * http://www.gnu.org/licenses/gpl-2.0.html. * */ diff --git a/Documentation/devicetree/bindings/arm/mali-valhall.txt b/Documentation/devicetree/bindings/arm/mali-valhall.txt new file mode 100644 index 000000000000..18f6af21210d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mali-valhall.txt @@ -0,0 +1,257 @@ +# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +# +# (C) COPYRIGHT 2013-2024 ARM Limited. All rights reserved. +# +# This program is free software and is provided to you under the terms of the +# GNU General Public License version 2 as published by the Free Software +# Foundation, and any use by you of this program is subject to the terms +# of such GNU license. +# +# 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, you can access it online at +# http://www.gnu.org/licenses/gpl-2.0.html. +# +# + +* ARM Mali Midgard / Bifrost devices + + +Required properties: + +- compatible : Should be mali, replacing digits with x from the back, +until malitxx, and it must end with one of: "arm,malit6xx" or +"arm,mali-midgard" or "arm,mali-bifrost" +- reg : Physical base address of the device and length of the register area. +- interrupts : Contains the three IRQ lines required by T-6xx devices +- interrupt-names : Contains the names of IRQ resources in the order they were +provided in the interrupts property. Must contain: "JOB, "MMU", "GPU". + +Optional: + +- clocks : One or more pairs of phandle to clock and clock specifier + for the Mali device. The order is important: the first clock + shall correspond to the "clk_mali" source. Other clocks are optional + and, if present, they shall correspond to domains like "shadercores", + which is available for all GPUs, or "coregroup" and "neuralengines" + which are available for newer GPUs. Also notice that the "neuralengines" + clock domain, if present, doesn't expect a corresponding regulator. +- clock-names : Shall be set to values like: "clk_mali", "shadercores", "coregroup", + "neuralengines". Only the first one is mandatory. Most GPUs + support only the first two entries. +- mali-supply : Phandle to the top level regulator for the Mali device. + Refer to +Documentation/devicetree/bindings/regulator/regulator.txt for details. +- mem-supply : Phandle to memory regulator for the Mali device. This is optional. +- operating-points-v2 : Refer to Documentation/devicetree/bindings/power/mali-opp.txt +for details. +- quirks-gpu : Used to write to the JM_CONFIG or CSF_CONFIG register. + Should be used with care. Options passed here are used to override + certain default behavior. Note: This will override 'idvs-group-size' + field in devicetree and module param 'corestack_driver_control', + therefore if 'quirks-gpu' is used then 'idvs-group-size' and + 'corestack_driver_control' value should be incorporated into 'quirks-gpu'. +- quirks-sc : Used to write to the SHADER_CONFIG register. + Should be used with care. Options passed here are used to override + certain default behavior. +- quirks-tiler : Used to write to the TILER_CONFIG register. + Should be used with care. Options passed here are used to + disable or override certain default behavior. +- quirks-mmu : Used to write to the L2_CONFIG register. + Should be used with care. Options passed here are used to + disable or override certain default behavior. +- power-model : Sets the power model parameters. Defined power models include: + "mali-simple-power-model", "mali-g51-power-model", "mali-g52-power-model", + "mali-g52_r1-power-model", "mali-g71-power-model", "mali-g72-power-model", + "mali-g76-power-model", "mali-g77-power-model", "mali-tnax-power-model", + "mali-tbex-power-model" and "mali-tbax-power-model". + - mali-simple-power-model: this model derives the GPU power usage based + on the GPU voltage scaled by the system temperature. Note: it was + designed for the Juno platform, and may not be suitable for others. + - compatible: Should be "arm,mali-simple-power-model" + - dynamic-coefficient: Coefficient, in pW/(Hz V^2), which is + multiplied by v^2*f to calculate the dynamic power consumption. + - static-coefficient: Coefficient, in uW/V^3, which is + multiplied by v^3 to calculate the static power consumption. + - ts: An array containing coefficients for the temperature + scaling factor. This is used to scale the static power by a + factor of tsf/1000000, + where tsf = ts[3]*T^3 + ts[2]*T^2 + ts[1]*T + ts[0], + and T = temperature in degrees. + - thermal-zone: A string identifying the thermal zone used for + the GPU + - temp-poll-interval-ms: the interval at which the system + temperature is polled + - mali-g*-power-model(s): unless being stated otherwise, these models derive + the GPU power usage based on performance counters, so they are more + accurate. + - compatible: Should be, as examples, "arm,mali-g51-power-model" / + "arm,mali-g72-power-model". + - scale: the dynamic power calculated by the power model is + multiplied by a factor of 'scale'. This value should be + chosen to match a particular implementation. + - min_sample_cycles: Fall back to the simple power model if the + number of GPU cycles for a given counter dump is less than + 'min_sample_cycles'. The default value of this should suffice. + * Note: when IPA is used, two separate power models (simple and counter-based) + are used at different points so care should be taken to configure + both power models in the device tree (specifically dynamic-coefficient, + static-coefficient and scale) to best match the platform. +- power-policy : Sets the GPU power policy at probe time. Available options are + "coarse_demand" and "always_on". If not set, then "coarse_demand" is used. +- system-coherency : Sets the coherency protocol to be used for coherent + accesses made from the GPU. + If not set then no coherency is used. + - 0 : ACE-Lite + - 1 : ACE + - 31 : No coherency +- ipa-model : Sets the IPA model to be used for power management. GPU probe will fail if the + model is not found in the registered models list. If no model is specified here, + a gpu-id based model is picked if available, otherwise the default model is used. + - mali-simple-power-model: Default model used on mali +- idvs-group-size : Override the IDVS group size value. Tasks are sent to + cores in groups of N + 1, so i.e. 0xF means 16 tasks. + Valid values are between 0 to 0x3F (including). +- l2-size : Override L2 cache size on GPU that supports it. Value should be larger than the minimum + size 1KiB and smaller than the maximum size. Maximum size is Hardware integration dependent. + The value passed should be of log2(Cache Size in Bytes). + For example for a 1KiB of cache size, 0xa should be passed. +- l2-hash : Override L2 hash function on GPU that supports it +- l2-hash-values : Override L2 hash function using provided hash values, on GPUs that supports it. + It is mutually exclusive with 'l2-hash'. Only one or the other must be + used in a supported GPU. +- arbiter-if : Phandle to the arbif platform device, used to provide KBASE with an interface + to the Arbiter. This is required when using arbitration; setting to a non-NULL + value will enable arbitration. + If arbitration is in use, then there should be no external GPU control. + When arbiter-if is in use then the following must not be: + - power-model (no IPA allowed with arbitration) + - #cooling-cells + - operating-points-v2 (no dvfs in kbase with arbitration) + - system-coherency with a value of 1 (no full coherency with arbitration) +- int-id-override: list of tuples defining the IDs needed to be + set and the setting coresponding to the SYSC_ALLOC register. +- propagate-bits: Used to write to L2_CONFIG.PBHA_HWU. This bitset establishes which + PBHA bits are propagated on the AXI bus. +- mma-wa-id: Sets a GPU MMU PBHA value to be used as NONCACHEABLE. GPU Page Table Entries + (PTEs) with this PBHA value set will have uncached transactions from the GPU. + Valid values are from 1 to 15. See mgm_update_gpu_pte() in + include/linux/memory_group_manager.h for the interface to configure the PTEs. Only + supported by arch 14.8.x and later GPUs. + + +Example for a Mali GPU with 1 clock and 1 regulator: + +gpu@0xfc010000 { + compatible = "arm,malit602", "arm,malit60x", "arm,malit6xx", "arm,mali-midgard"; + reg = <0xfc010000 0x4000>; + interrupts = <0 36 4>, <0 37 4>, <0 38 4>; + interrupt-names = "JOB", "MMU", "GPU"; + + clocks = <&pclk_mali>; + clock-names = "clk_mali"; + mali-supply = <&vdd_mali>; + operating-points-v2 = <&gpu_opp_table>; + power_model@0 { + compatible = "arm,mali-simple-power-model"; + static-coefficient = <2427750>; + dynamic-coefficient = <4687>; + ts = <20000 2000 (-20) 2>; + thermal-zone = "gpu"; + }; + power_model@1 { + compatible = "arm,mali-g71-power-model"; + scale = <5>; + }; + + idvs-group-size = <0x7>; + l2-size = /bits/ 8 <0x10>; + l2-hash = /bits/ 8 <0x04>; /* or l2-hash-values = <0x12345678 0x8765 0xAB>; */ +}; + +gpu_opp_table: opp_table0 { + compatible = "operating-points-v2"; + + opp@533000000 { + opp-hz = /bits/ 64 <533000000>; + opp-microvolt = <1250000>; + }; + opp@450000000 { + opp-hz = /bits/ 64 <450000000>; + opp-microvolt = <1150000>; + }; + opp@400000000 { + opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1125000>; + }; + opp@350000000 { + opp-hz = /bits/ 64 <350000000>; + opp-microvolt = <1075000>; + }; + opp@266000000 { + opp-hz = /bits/ 64 <266000000>; + opp-microvolt = <1025000>; + }; + opp@160000000 { + opp-hz = /bits/ 64 <160000000>; + opp-microvolt = <925000>; + }; + opp@100000000 { + opp-hz = /bits/ 64 <100000000>; + opp-microvolt = <912500>; + }; +}; + +Example for a Mali GPU with 2 clocks and 2 regulators: + +gpu: gpu@6e000000 { + compatible = "arm,mali-midgard"; + reg = <0x0 0x6e000000 0x0 0x200000>; + interrupts = <0 168 4>, <0 168 4>, <0 168 4>; + interrupt-names = "JOB", "MMU", "GPU"; + clocks = <&clk_mali 0>, <&clk_mali 1>; + clock-names = "clk_mali", "shadercores"; + mali-supply = <&supply0_3v3>; + mem-supply = <&supply1_3v3>; + system-coherency = <31>; + operating-points-v2 = <&gpu_opp_table>; +}; + +gpu_opp_table: opp_table0 { + compatible = "operating-points-v2", "operating-points-v2-mali"; + + opp@0 { + opp-hz = /bits/ 64 <50000000>; + opp-hz-real = /bits/ 64 <50000000>, /bits/ 64 <45000000>; + opp-microvolt = <820000>, <800000>; + opp-core-mask = /bits/ 64 <0xf>; + }; + opp@1 { + opp-hz = /bits/ 64 <40000000>; + opp-hz-real = /bits/ 64 <40000000>, /bits/ 64 <35000000>; + opp-microvolt = <720000>, <700000>; + opp-core-mask = /bits/ 64 <0x7>; + }; + opp@2 { + opp-hz = /bits/ 64 <30000000>; + opp-hz-real = /bits/ 64 <30000000>, /bits/ 64 <25000000>; + opp-microvolt = <620000>, <700000>; + opp-core-mask = /bits/ 64 <0x3>; + }; +}; + +Example for a Mali GPU supporting PBHA configuration via DTB (default): + +gpu@0xfc010000 { + ... + pbha { + int-id-override = <2 0x32>, <9 0x05>, <16 0x32>; + propagate-bits = /bits/ 8 <0x03>; + mma-wa-id = <2>; + }; + ... +}; diff --git a/arch/arm/boot/dts/rockchip/Makefile b/arch/arm/boot/dts/rockchip/Makefile index b00c09e1ad42..c081ceb8d01d 100644 --- a/arch/arm/boot/dts/rockchip/Makefile +++ b/arch/arm/boot/dts/rockchip/Makefile @@ -58,11 +58,17 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rv1126b-evb1-v10-bt-sco.dtb \ rv1126b-evb1-v10-dual-4k.dtb \ rv1126b-evb1-v10-dv.dtb \ + rv1126b-evb1-v10-fastboot-emmc.dtb \ + rv1126b-evb1-v10-fastboot-spi-nand.dtb \ + rv1126b-evb1-v10-fastboot-spi-nor.dtb \ rv1126b-evb1-v10-spi-nor.dtb \ + rv1126b-evb1-v11.dtb \ + rv1126b-evb1-v11-dual-4k.dtb \ rv1126b-evb2-v10.dtb \ rv1126b-evb2-v10-mcu-k350c4516t.dtb \ rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb \ rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb \ + rv1126b-evb2-v10-tb-400w.dtb \ rv1126b-evb3-v10.dtb \ rv1126b-evb4-v10.dtb \ rv1126b-iotest-v10.dtb \ diff --git a/arch/arm/boot/dts/rockchip/rk3506g-demo-display-control.dts b/arch/arm/boot/dts/rockchip/rk3506g-demo-display-control.dts index 81df7b8ed38b..8a25c12633c0 100644 --- a/arch/arm/boot/dts/rockchip/rk3506g-demo-display-control.dts +++ b/arch/arm/boot/dts/rockchip/rk3506g-demo-display-control.dts @@ -584,14 +584,12 @@ | RKPM_24M_OSC_DIS | RKPM_32K_CLK | RKPM_32K_SRC_RC - | RKPM_PWM0_CH0_CORE_PWREN ) >; rockchip,apios-suspend = < (0 - | RKPM_PWREN_CORE_GPIO0C1 | RKPM_PWREN_CORE_ACT_HIGH - | RKPM_PWREN_SLEEP_GPIO0B5 | RKPM_PWREN_SLEEP_ACT_HIGH + | RKPM_PWREN_SLEEP_GPIO0C1 | RKPM_PWREN_SLEEP_ACT_HIGH ) >; }; diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts new file mode 100644 index 000000000000..ae214ef870ac --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts" + +/ { + model = "Rockchip RV1126B EVB1 V10 Fastboot Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; +}; diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts new file mode 100644 index 000000000000..d96e9b3845bd --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts" + +/ { + model = "Rockchip RV1126B EVB1 V10 Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot-spi-nand", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; +}; diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts new file mode 100644 index 000000000000..43e000f8e094 --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts" + +/ { + model = "Rockchip RV1126B EVB1 V10 Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot-spi-nand", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (20 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4a040000 (10 * 0x00100000)>; +}; diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts new file mode 100644 index 000000000000..56e6c3b1177a --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v11-dual-4k.dts" diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11.dts new file mode 100644 index 000000000000..1b65e3ffc1c7 --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb1-v11.dts @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb1-v11.dts" diff --git a/arch/arm/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts b/arch/arm/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts new file mode 100644 index 000000000000..5d1bfda82ece --- /dev/null +++ b/arch/arm/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "arm64/rockchip/rv1126b-evb2-v10-tb-400w.dts" + +/ { + model = "Rockchip RV1126B EVB2 V10 TB 400W Board"; + compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b"; +}; + +&ramdisk_r { + reg = <0x48c40000 (30 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4aa40000 (20 * 0x00100000)>; +}; diff --git a/arch/arm/configs/rv1126b-aov.config b/arch/arm/configs/rv1126b-aov.config new file mode 100644 index 000000000000..ad3e46bc5392 --- /dev/null +++ b/arch/arm/configs/rv1126b-aov.config @@ -0,0 +1,72 @@ +# CONFIG_ETHERNET is not set +CONFIG_EXTCON=y +CONFIG_INPUT=y +# CONFIG_MDIO_DEVICE is not set +# CONFIG_PHYLIB is not set +CONFIG_SND_SOC_RK_DSM=y +CONFIG_VIDEO_CAM_SLEEP_WAKEUP=y +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_HID is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_RC_CORE is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSOR_DEVICE is not set +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +# CONFIG_SND_SOC_WM8962 is not set diff --git a/arch/arm/configs/rv1126b-cvr-fastboot.config b/arch/arm/configs/rv1126b-cvr-fastboot.config new file mode 100644 index 000000000000..b34193462bee --- /dev/null +++ b/arch/arm/configs/rv1126b-cvr-fastboot.config @@ -0,0 +1,1126 @@ +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CONFIGFS_FS=m +CONFIG_CRC16=y +CONFIG_CRYPTO=y +CONFIG_DAX=y +CONFIG_DRM=y +CONFIG_ELF_CORE=y +CONFIG_EROFS_FS=y +CONFIG_EXT4_FS=m +CONFIG_EXTCON=y +CONFIG_FILE_LOCKING=y +CONFIG_INPUT=y +CONFIG_JFFS2_FS=y +CONFIG_KCMP=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_XZ is not set +CONFIG_LIBCRC32C=y +CONFIG_MMC=y +CONFIG_MSDOS_FS=m +CONFIG_MSDOS_PARTITION=y +CONFIG_MTD_BLOCK=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y +CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=m +CONFIG_RK_DMABUF_PROCFS=y +CONFIG_ROCKCHIP_DVBM=y +CONFIG_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_ROCKCHIP_MULTI_RGA=y +CONFIG_ROCKCHIP_RAMDISK=y +CONFIG_ROCKCHIP_RGA_PROC_FS=y +CONFIG_ROCKCHIP_THUNDER_BOOT=y +CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK=y +CONFIG_ROCKCHIP_VENDOR_STORAGE=m +# CONFIG_SLUB_SYSFS is not set +# CONFIG_SND_SIMPLE_CARD is not set +CONFIG_SND_SOC_DUMMY_CODEC=m +CONFIG_SND_SOC_RK_DSM=m +CONFIG_SND_SOC_ROCKCHIP=m +CONFIG_SND_SOC_ROCKCHIP_ASRC=m +CONFIG_SND_SOC_ROCKCHIP_PDM_V2=m +CONFIG_SND_SOC_ROCKCHIP_SAI=m +CONFIG_SPI=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_USB_SUPPORT=y +CONFIG_VFAT_FS=m +CONFIG_VIDEOBUF2_DMA_SG=m +# CONFIG_VIDEO_RK_IRCUT is not set +CONFIG_VIDEO_ROCKCHIP_AIISP=y +CONFIG_VIDEO_ROCKCHIP_AVSP=y +CONFIG_VIDEO_ROCKCHIP_CIF=y +CONFIG_VIDEO_ROCKCHIP_FEC=y +CONFIG_VIDEO_ROCKCHIP_ISP=y +CONFIG_VIDEO_ROCKCHIP_VPSS=y +CONFIG_VIDEO_SC200AI=y +CONFIG_VIDEO_SC450AI=y +CONFIG_VIDEO_SC850SL=y +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD3552R is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD74413R is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADA4250 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADRF6780 is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_AFE4403 is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_AS3935 is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_KTD253 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_QCOM_WLED is not set +# CONFIG_BMA220 is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_CHARGER_BQ24190 is not set +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_UTILS=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_MANAGER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZSTD is not set +# CONFIG_DLM is not set +# CONFIG_DM9051 is not set +# CONFIG_DRM_ANALOGIX_ANX6345 is not set +# CONFIG_DRM_ANALOGIX_ANX7625 is not set +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_ARMADA is not set +CONFIG_DRM_BRIDGE=y +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_CDNS_MHDP8546 is not set +# CONFIG_DRM_CHIPONE_ICN6211 is not set +# CONFIG_DRM_CHRONTEL_CH7033 is not set +# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set +# CONFIG_DRM_DEBUG_MM is not set +# CONFIG_DRM_DISPLAY_CONNECTOR is not set +# CONFIG_DRM_DP is not set +CONFIG_DRM_DW_MIPI_DSI=y +# CONFIG_DRM_EDID is not set +# CONFIG_DRM_ETNAVIV is not set +# CONFIG_DRM_EXYNOS is not set +# CONFIG_DRM_FSL_DCU is not set +CONFIG_DRM_GEM_DMA_HELPER=y +# CONFIG_DRM_GM12U320 is not set +# CONFIG_DRM_GUD is not set +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_SIL164 is not set +CONFIG_DRM_IGNORE_IOTCL_PERMIT=y +# CONFIG_DRM_ITE_IT6161 is not set +# CONFIG_DRM_ITE_IT6505 is not set +# CONFIG_DRM_ITE_IT66121 is not set +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_KOMEDA is not set +# CONFIG_DRM_LEGACY is not set +# CONFIG_DRM_LIMA is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_LOGICVC is not set +# CONFIG_DRM_LONTIUM_LT8912B is not set +# CONFIG_DRM_LONTIUM_LT9211 is not set +# CONFIG_DRM_LONTIUM_LT9611 is not set +# CONFIG_DRM_LONTIUM_LT9611UXC is not set +# CONFIG_DRM_LVDS_CODEC is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_MAXIM_MAX96745 is not set +# CONFIG_DRM_MAXIM_MAX96755F is not set +# CONFIG_DRM_MCDE is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_NOMODESET=y +# CONFIG_DRM_NWL_MIPI_DSI is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_OMAP is not set +CONFIG_DRM_PANEL=y +# CONFIG_DRM_PANEL_ABT_Y030XX067A is not set +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_BOE_BF060Y8M_AJ0 is not set +# CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +CONFIG_DRM_PANEL_BRIDGE=y +# CONFIG_DRM_PANEL_DSI_CM is not set +# CONFIG_DRM_PANEL_EBBG_FT8719 is not set +# CONFIG_DRM_PANEL_EDP is not set +# CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9341 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_EJ030NA is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_JDI_R63452 is not set +# CONFIG_DRM_PANEL_KHADAS_TS050 is not set +# CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set +# CONFIG_DRM_PANEL_LG_LB035Q02 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_MAXIM_MAX96752F is not set +# CONFIG_DRM_PANEL_MAXIM_MAX96772 is not set +# CONFIG_DRM_PANEL_MIPI_DBI is not set +# CONFIG_DRM_PANEL_NEC_NL8048HL11 is not set +# CONFIG_DRM_PANEL_NEWVISION_NV3052C is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35560 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35950 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT36672A is not set +# CONFIG_DRM_PANEL_NOVATEK_NT39016 is not set +# CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20 is not set +# CONFIG_DRM_PANEL_SAMSUNG_DB7430 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D27A1 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63M0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_SOFEF00 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS037V7DW01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SHARP_LS060T1SX01 is not set +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_PANEL_SIMPLE_OF_ONLY=y +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +# CONFIG_DRM_PANEL_SONY_ACX565AKM is not set +# CONFIG_DRM_PANEL_SONY_TULIP_TRULY_NT35521 is not set +# CONFIG_DRM_PANEL_TDO_TL070WSH30 is not set +# CONFIG_DRM_PANEL_TPO_TD028TTEC1 is not set +# CONFIG_DRM_PANEL_TPO_TD043MTEA1 is not set +# CONFIG_DRM_PANEL_TPO_TPG110 is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_WIDECHIPS_WS2401 is not set +# CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set +# CONFIG_DRM_PANFROST is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_PARADE_PS8640 is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_RCAR_DW_HDMI is not set +# CONFIG_DRM_RCAR_USE_LVDS is not set +# CONFIG_DRM_RCAR_USE_MIPI_DSI is not set +# CONFIG_DRM_RK1000_TVE is not set +CONFIG_DRM_ROCKCHIP=y +# CONFIG_DRM_ROCKCHIP_VKMS is not set +# CONFIG_DRM_ROHM_BU18XL82 is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SIMPLEDRM is not set +# CONFIG_DRM_SIMPLE_BRIDGE is not set +# CONFIG_DRM_SSD130X is not set +# CONFIG_DRM_STI is not set +# CONFIG_DRM_STM is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TIDSS is not set +# CONFIG_DRM_TILCDC is not set +# CONFIG_DRM_TI_DLPC3433 is not set +# CONFIG_DRM_TI_SN65DSI83 is not set +# CONFIG_DRM_TI_SN65DSI86 is not set +# CONFIG_DRM_TI_TFP410 is not set +# CONFIG_DRM_TI_TPD12S015 is not set +# CONFIG_DRM_TOSHIBA_TC358762 is not set +# CONFIG_DRM_TOSHIBA_TC358764 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TOSHIBA_TC358768 is not set +# CONFIG_DRM_TOSHIBA_TC358775 is not set +# CONFIG_DRM_TVE200 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_EROFS_FS_DEBUG is not set +# CONFIG_EROFS_FS_XATTR is not set +# CONFIG_EROFS_FS_ZIP is not set +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_EZX_PCAP is not set +CONFIG_FAT_DEFAULT_CODEPAGE=936 +CONFIG_FAT_DEFAULT_IOCHARSET="cp936" +CONFIG_FAT_DEFAULT_UTF8=y +CONFIG_FAT_FS=m +CONFIG_FB_CMDLINE=y +CONFIG_FS_DAX=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=m +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_FXOS8700_SPI is not set +CONFIG_GENERIC_PHY_MIPI_DPHY=y +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_HI8435 is not set +CONFIG_HID=m +# CONFIG_HIDRAW is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +# CONFIG_HID_ALPS is not set +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_CREATIVE_SB0540 is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_ELECOM is not set +# CONFIG_HID_ELO is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +CONFIG_HID_GENERIC=m +# CONFIG_HID_GFRM is not set +# CONFIG_HID_GLORIOUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LETSKETCH is not set +# CONFIG_HID_MACALLY is not set +# CONFIG_HID_MAGICMOUSE is not set +# CONFIG_HID_MALTRON is not set +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_MCP2221 is not set +# CONFIG_HID_MEGAWORLD_FF is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_MULTITOUCH is not set +# CONFIG_HID_NTI is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +# CONFIG_HID_PID is not set +# CONFIG_HID_PLANTRONICS is not set +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_PXRC is not set +# CONFIG_HID_RAZER is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SEMITEK is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_SIGMAMICRO is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPRE is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_VIEWSONIC is not set +# CONFIG_HID_VIVALDI is not set +# CONFIG_HID_VRC2 is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_XIAOMI is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HISI_HIKEY_USB is not set +# CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +CONFIG_INITCALL_ASYNC=y +# CONFIG_INITRAMFS_FORCE is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_ICM42670_SPI is not set +# CONFIG_INV_MPU6050_SPI is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_LZO is not set +# CONFIG_JFFS2_RTIME is not set +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_KEYBOARD_ADC=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KS8851 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_LMK04832 is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2688 is not set +# CONFIG_LTC2983 is not set +# CONFIG_LTE_GDM724X is not set +CONFIG_LZ4_DECOMPRESS=y +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DW=m +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_PLTFM=m +CONFIG_MMC_DW_ROCKCHIP=m +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_QUEUE_DEPTH=1 +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MOST is not set +# CONFIG_MOXTET is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MSE102X is not set +CONFIG_MTD_BLKDEVS=m +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +# CONFIG_MTD_SPI_NAND is not set +CONFIG_MTD_SPI_NOR=m +# CONFIG_MTD_SPI_NOR_ATMEL is not set +# CONFIG_MTD_SPI_NOR_BOYA is not set +# CONFIG_MTD_SPI_NOR_CATALYST is not set +# CONFIG_MTD_SPI_NOR_DEVICE_AUTOSELECT is not set +# CONFIG_MTD_SPI_NOR_DOSILICON is not set +# CONFIG_MTD_SPI_NOR_EON is not set +# CONFIG_MTD_SPI_NOR_ESMT is not set +# CONFIG_MTD_SPI_NOR_EVERSPIN is not set +# CONFIG_MTD_SPI_NOR_FMSH is not set +# CONFIG_MTD_SPI_NOR_FUJITSU is not set +CONFIG_MTD_SPI_NOR_GIGADEVICE=y +# CONFIG_MTD_SPI_NOR_INTEL is not set +# CONFIG_MTD_SPI_NOR_ISSI is not set +CONFIG_MTD_SPI_NOR_MACRONIX=y +CONFIG_MTD_SPI_NOR_MISC=y +# CONFIG_MTD_SPI_NOR_NORMEM is not set +# CONFIG_MTD_SPI_NOR_PUYA is not set +# CONFIG_MTD_SPI_NOR_SPANSION is not set +# CONFIG_MTD_SPI_NOR_SST is not set +# CONFIG_MTD_SPI_NOR_STMICRO is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPI_NOR_WINBOND=y +# CONFIG_MTD_SPI_NOR_XILINX is not set +# CONFIG_MTD_SPI_NOR_XMC is not set +# CONFIG_MTD_SPI_NOR_XTX is not set +# CONFIG_MTD_SST25L is not set +CONFIG_NET_VENDOR_ADI=y +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_NVME_TARGET is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=m +# CONFIG_PHY_ROCKCHIP_NANENG_USB2 is not set +# CONFIG_PI433 is not set +# CONFIG_PWRSEQ_EMMC is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_RC_CORE is not set +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_GZIP is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_ZSTD is not set +CONFIG_REGMAP_SPI=y +# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_ANALOGIX_DP is not set +# CONFIG_ROCKCHIP_CDN_DP is not set +# CONFIG_ROCKCHIP_DP_MST_AUX_CLIENT is not set +# CONFIG_ROCKCHIP_DRM_DIRECT_SHOW is not set +# CONFIG_ROCKCHIP_DRM_TVE is not set +# CONFIG_ROCKCHIP_DW_DP is not set +# CONFIG_ROCKCHIP_DW_HDCP2 is not set +# CONFIG_ROCKCHIP_DW_HDMI is not set +CONFIG_ROCKCHIP_DW_MIPI_DSI=y +# CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST is not set +# CONFIG_ROCKCHIP_INNO_HDMI is not set +# CONFIG_ROCKCHIP_LVDS is not set +# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set +CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=m +# CONFIG_ROCKCHIP_PANEL_NOTIFIER is not set +# CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set +CONFIG_ROCKCHIP_RGA_DEBUGGER=y +CONFIG_ROCKCHIP_RGB=y +# CONFIG_ROCKCHIP_RK3066_HDMI is not set +# CONFIG_ROCKCHIP_RKNPU_DRM_GEM is not set +CONFIG_ROCKCHIP_THUNDER_BOOT_MMC=y +CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y +# CONFIG_ROCKCHIP_VCONN is not set +CONFIG_ROCKCHIP_VOP=y +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSOR_DEVICE is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=m +# CONFIG_SND_SOC_ROCKCHIP_SPI_CODEC is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_WM8731_SPI is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SPI is not set +# CONFIG_SND_USB is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AX88796C is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_FSPI is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_SPI is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_ROCKCHIP_SLAVE is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_TINYDRM_HX8357D is not set +# CONFIG_TINYDRM_ILI9163 is not set +# CONFIG_TINYDRM_ILI9225 is not set +# CONFIG_TINYDRM_ILI9341 is not set +# CONFIG_TINYDRM_ILI9486 is not set +# CONFIG_TINYDRM_MI0283QT is not set +# CONFIG_TINYDRM_REPAPER is not set +# CONFIG_TINYDRM_ST7586 is not set +# CONFIG_TINYDRM_ST7735R is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_9551R is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELAN5515 is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FT5726 is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set +# CONFIG_TOUCHSCREEN_GSLX680_PAD is not set +CONFIG_TOUCHSCREEN_GT1X=y +# CONFIG_TOUCHSCREEN_GT9XX is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HIMAX_CHIPSET is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYN is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set +# CONFIG_TOUCHSCREEN_IMAGIS is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_PARADE is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_W9013 is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TYPEC is not set +# CONFIG_UHID is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_USB=m +# CONFIG_USBIP_CORE is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_AUDIO is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_COMMON=m +CONFIG_USB_CONFIGFS=m +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_EEM is not set +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_HID=y +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +CONFIG_USB_CONFIGFS_F_UAC1=y +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_UVC=y +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +CONFIG_USB_CONFIGFS_RNDIS=y +# CONFIG_USB_CONFIGFS_SERIAL is not set +CONFIG_USB_CONFIGFS_UEVENT=y +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_DWC3=m +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_HOST is not set +CONFIG_USB_DWC3_OF_SIMPLE=m +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FUSB300 is not set +CONFIG_USB_F_FS=m +CONFIG_USB_F_HID=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_UAC1=m +CONFIG_USB_F_UAC2=m +CONFIG_USB_F_UVC=m +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_VBUS_DRAW=2 +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_HCD_TEST_MODE is not set +CONFIG_USB_HID=m +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LEGOTOWER is not set +CONFIG_USB_LIBCOMPOSITE=m +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET_DRIVERS is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PLATFORM=m +# CONFIG_USB_ONBOARD_HUB is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RAW_GADGET is not set +CONFIG_USB_ROLE_SWITCH=m +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TMC is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_U_AUDIO=m +CONFIG_USB_U_ETHER=m +# CONFIG_USB_WDM is not set +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_PCI_RENESAS is not set +CONFIG_USB_XHCI_PLATFORM=m +# CONFIG_USB_YUREX is not set +# CONFIG_USB_ZERO is not set +CONFIG_VIDEOMODE_HELPERS=y +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +# CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP is not set +CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP=y +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_XILLYUSB is not set +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/rv1126b-cvr.config b/arch/arm/configs/rv1126b-cvr.config new file mode 100644 index 000000000000..ef45f4e43418 --- /dev/null +++ b/arch/arm/configs/rv1126b-cvr.config @@ -0,0 +1,1090 @@ +CONFIG_CONFIGFS_FS=y +CONFIG_CRC16=y +CONFIG_CRYPTO=y +CONFIG_DEBUG_FS=y +CONFIG_ELF_CORE=y +CONFIG_EXFAT_FS=y +CONFIG_EXPORTFS_BLOCK_OPS=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_FILE_LOCKING=y +CONFIG_HARDLOCKUP_DETECTOR=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_MUX=y +CONFIG_INPUT=y +CONFIG_IPV6=m +CONFIG_JFFS2_FS=y +CONFIG_KCMP=y +CONFIG_KEYS=y +CONFIG_MMC=y +CONFIG_MSDOS_PARTITION=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_UBI=y +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NVMEM_SYSFS=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y +CONFIG_RK_CMA_PROCFS=y +CONFIG_RK_DMABUF_PROCFS=y +CONFIG_RK_MEMBLOCK_PROCFS=y +CONFIG_ROCKCHIP_DEBUG=y +CONFIG_ROCKCHIP_RGA_PROC_FS=y +CONFIG_ROCKCHIP_VENDOR_STORAGE=y +CONFIG_SND_SOC_DUMMY_CODEC=y +CONFIG_SND_SOC_RK817=y +CONFIG_SND_SOC_RK_DSM=y +CONFIG_SND_SOC_ROCKCHIP_ASRC=y +CONFIG_SND_SOC_ROCKCHIP_PDM_V2=y +CONFIG_SOFTLOCKUP_DETECTOR=y +CONFIG_SPI=y +CONFIG_USB_SUPPORT=y +CONFIG_VFAT_FS=y +CONFIG_VIDEOBUF2_DMA_SG=y +CONFIG_VIDEO_CAM_SLEEP_WAKEUP=y +CONFIG_VIDEO_GC2053=m +CONFIG_VIDEO_GC8613=m +CONFIG_VIDEO_IMX415=m +CONFIG_VIDEO_IMX586=m +CONFIG_VIDEO_OS04A10=m +CONFIG_VIDEO_PS5458=m +# CONFIG_VIDEO_RK_IRCUT is not set +CONFIG_VIDEO_ROCKCHIP_FEC=y +CONFIG_VIDEO_SC200AI=m +CONFIG_VIDEO_SC3336=m +CONFIG_VIDEO_SC401AI=m +CONFIG_VIDEO_SC4336=m +CONFIG_VIDEO_SC450AI=m +CONFIG_VIDEO_SC530AI=m +CONFIG_VIDEO_SC635HAI=m +CONFIG_VIDEO_SC850SL=m +CONFIG_VIDEO_TECHPOINT=m +CONFIG_WIRELESS=y +CONFIG_WLAN=y +# CONFIG_6LOWPAN is not set +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD3552R is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD74413R is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADA4250 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADRF6780 is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_AFE4403 is not set +# CONFIG_AFS_FS is not set +# CONFIG_APPLE_MFI_FASTCHARGE is not set +# CONFIG_AS3935 is not set +CONFIG_ASN1=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +# CONFIG_BCMDHD is not set +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BMA220 is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_BMI160_SPI is not set +CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_CEPH_FS is not set +CONFIG_CFG80211=m +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_CRDA_SUPPORT=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CIFS is not set +CONFIG_CLZ_TAB=y +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CODA_FS is not set +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_CRYPTO_842 is not set +CONFIG_CRYPTO_ACOMP2=y +# CONFIG_CRYPTO_ADIANTUM is not set +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +# CONFIG_CRYPTO_AEGIS128 is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CFB=m +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +CONFIG_CRYPTO_CMAC=m +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_CTR=m +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set +# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set +# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +CONFIG_CRYPTO_DEV_ROCKCHIP=m +CONFIG_CRYPTO_DEV_ROCKCHIP_CE=y +CONFIG_CRYPTO_DEV_ROCKCHIP_DEV=m +# CONFIG_CRYPTO_DEV_SAFEXCEL is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +CONFIG_CRYPTO_ENGINE=m +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HASH_INFO=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_HMAC is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_LIB_AES=m +CONFIG_CRYPTO_LIB_ARC4=m +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_DES=m +CONFIG_CRYPTO_LIB_SHA256=m +CONFIG_CRYPTO_LIB_UTILS=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=m +# CONFIG_CRYPTO_MICHAEL_MIC is not set +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_OFB=m +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_RMD160 is not set +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RSA=y +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA1_ARM is not set +CONFIG_CRYPTO_SHA256=m +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +CONFIG_CRYPTO_SKCIPHER=m +CONFIG_CRYPTO_SKCIPHER2=y +# CONFIG_CRYPTO_SM2 is not set +CONFIG_CRYPTO_SM3=m +# CONFIG_CRYPTO_SM3_GENERIC is not set +CONFIG_CRYPTO_SM4=m +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +CONFIG_CRYPTO_XTS=m +# CONFIG_CRYPTO_XXHASH is not set +CONFIG_CRYPTO_ZSTD=y +CONFIG_DEBUG_FS_ALLOW_ALL=y +# CONFIG_DEBUG_FS_ALLOW_NONE is not set +# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set +# CONFIG_DLM is not set +# CONFIG_DM9051 is not set +# CONFIG_DMA_MAP_BENCHMARK is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_ECRYPT_FS is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_ENCX24J600 is not set +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" +# CONFIG_EXT4_DEBUG is not set +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_EZX_PCAP is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +CONFIG_FAT_FS=y +# CONFIG_FIPS_SIGNATURE_SELFTEST is not set +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_FXOS8700_SPI is not set +# CONFIG_GCOV_KERNEL is not set +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +CONFIG_GRACE_PERIOD=y +# CONFIG_GUP_TEST is not set +CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU=y +# CONFIG_HI8435 is not set +# CONFIG_HID is not set +# CONFIG_HID_PID is not set +# CONFIG_HISI_HIKEY_USB is not set +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_CP2615 is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TINY_USB is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_DA7280_HAPTICS is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_GPIO_VIBRA is not set +# CONFIG_INPUT_IQS269A is not set +# CONFIG_INPUT_IQS626A is not set +# CONFIG_INPUT_IQS7222 is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_MATRIXKMAP is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_RK805_PWRKEY=y +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INV_ICM42600_SPI is not set +CONFIG_INV_ICM42670=y +CONFIG_INV_ICM42670_SPI=y +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IPV6_IOAM6_LWTUNNEL is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_RPL_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_VTI is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_LZO is not set +# CONFIG_JFFS2_RTIME is not set +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_KEYBOARD_ADC=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYS_REQUEST_CACHE is not set +# CONFIG_KEY_DH_OPERATIONS is not set +# CONFIG_KS7010 is not set +# CONFIG_KS8851 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_LMK04832 is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_LOCKUP_DETECTOR=y +# CONFIG_LOCK_EVENT_COUNTS is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2688 is not set +# CONFIG_LTC2983 is not set +# CONFIG_LTE_GDM724X is not set +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MAC80211=m +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_HAS_RC=y +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MAC80211_MESH is not set +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_MANAGER_SBS is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MDIO_MVUSB is not set +# CONFIG_MEDIA_USB_SUPPORT is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=y +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_QUEUE_DEPTH=1 +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MOST is not set +# CONFIG_MOXTET is not set +CONFIG_MPILIB=y +# CONFIG_MPL115_SPI is not set +# CONFIG_MSE102X is not set +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +CONFIG_MTD_NAND_BBT_USING_FLASH=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NAND_ATO=y +CONFIG_MTD_SPI_NAND_BIWIN=y +CONFIG_MTD_SPI_NAND_DEVICE_AUTOSELECT=y +CONFIG_MTD_SPI_NAND_DOSILICON=y +CONFIG_MTD_SPI_NAND_ESMT=y +CONFIG_MTD_SPI_NAND_ETRON=y +CONFIG_MTD_SPI_NAND_FMSH=y +CONFIG_MTD_SPI_NAND_FORESEE=y +CONFIG_MTD_SPI_NAND_GIGADEVICE=y +CONFIG_MTD_SPI_NAND_GSTO=y +CONFIG_MTD_SPI_NAND_HIKSEMI=y +CONFIG_MTD_SPI_NAND_HYF=y +CONFIG_MTD_SPI_NAND_JSC=y +CONFIG_MTD_SPI_NAND_MACRONIX=y +CONFIG_MTD_SPI_NAND_MICRON=y +CONFIG_MTD_SPI_NAND_PARAGON=y +CONFIG_MTD_SPI_NAND_SILICONGO=y +CONFIG_MTD_SPI_NAND_SKYHIGH=y +CONFIG_MTD_SPI_NAND_TOSHIBA=y +CONFIG_MTD_SPI_NAND_UNIM=y +CONFIG_MTD_SPI_NAND_WINBOND=y +CONFIG_MTD_SPI_NAND_XINCUN=y +CONFIG_MTD_SPI_NAND_XTX=y +CONFIG_MTD_SPI_NAND_ZBIT=y +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_ATMEL is not set +# CONFIG_MTD_SPI_NOR_BOYA is not set +# CONFIG_MTD_SPI_NOR_CATALYST is not set +# CONFIG_MTD_SPI_NOR_DEVICE_AUTOSELECT is not set +# CONFIG_MTD_SPI_NOR_DOSILICON is not set +# CONFIG_MTD_SPI_NOR_EON is not set +# CONFIG_MTD_SPI_NOR_ESMT is not set +# CONFIG_MTD_SPI_NOR_EVERSPIN is not set +# CONFIG_MTD_SPI_NOR_FMSH is not set +# CONFIG_MTD_SPI_NOR_FUJITSU is not set +CONFIG_MTD_SPI_NOR_GIGADEVICE=y +# CONFIG_MTD_SPI_NOR_INTEL is not set +# CONFIG_MTD_SPI_NOR_ISSI is not set +CONFIG_MTD_SPI_NOR_MACRONIX=y +CONFIG_MTD_SPI_NOR_MISC=y +# CONFIG_MTD_SPI_NOR_NORMEM is not set +# CONFIG_MTD_SPI_NOR_PUYA is not set +# CONFIG_MTD_SPI_NOR_SPANSION is not set +# CONFIG_MTD_SPI_NOR_SST is not set +# CONFIG_MTD_SPI_NOR_STMICRO is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPI_NOR_WINBOND=y +# CONFIG_MTD_SPI_NOR_XILINX is not set +# CONFIG_MTD_SPI_NOR_XMC is not set +# CONFIG_MTD_SPI_NOR_XTX is not set +# CONFIG_MTD_SST25L is not set +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_NETDEVSIM is not set +CONFIG_NET_VENDOR_ADI=y +# CONFIG_NFSD is not set +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_NFS_DISABLE_UDP_SUPPORT=y +CONFIG_NFS_FS=y +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_NVME_TARGET is not set +# CONFIG_OCFS2_FS is not set +CONFIG_OID_REGISTRY=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +# CONFIG_PHY_ROCKCHIP_NANENG_USB2 is not set +# CONFIG_PI433 is not set +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set +# CONFIG_PLFXLC is not set +# CONFIG_PRINTK_INDEX is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_PWRSEQ_EMMC is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_R8188EU is not set +# CONFIG_R8712U is not set +# CONFIG_RC_CORE is not set +CONFIG_REGMAP_SPI=y +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_RMI4_CORE is not set +# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set +CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=y +# CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set +CONFIG_ROCKCHIP_RGA_DEBUGGER=y +# CONFIG_ROCKCHIP_RGA_DEBUG_FS is not set +# CONFIG_ROCKCHIP_RKNPU_DEBUG_FS is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTL8723BS is not set +# CONFIG_RTLLIB is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSOR_DEVICE is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SGL_ALLOC=y +# CONFIG_SHRINKER_DEBUG is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set +# CONFIG_SMB_SERVER is not set +# CONFIG_SND_BCD2000 is not set +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=y +# CONFIG_SND_SOC_ROCKCHIP_SPI_CODEC is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_WM8731_SPI is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_VARIAX is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AX88796C is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +CONFIG_SPI_ROCKCHIP=y +# CONFIG_SPI_ROCKCHIP_FLEXBUS_FSPI is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_SPI is not set +# CONFIG_SPI_ROCKCHIP_MISCDEV is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_ROCKCHIP_SLAVE is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_DEBUG is not set +CONFIG_SUNRPC_GSS=y +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +CONFIG_SYSTEM_DATA_VERIFICATION=y +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_9551R is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_COLIBRI_VF50 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELAN5515 is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FT5726 is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set +# CONFIG_TOUCHSCREEN_GSLX680_PAD is not set +CONFIG_TOUCHSCREEN_GT1X=y +# CONFIG_TOUCHSCREEN_GT9XX is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_HIMAX_CHIPSET is not set +# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYN is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_ILITEK is not set +# CONFIG_TOUCHSCREEN_IMAGIS is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MSG2638 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_PARADE is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_W9013 is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set +# CONFIG_TRUSTED_KEYS is not set +# CONFIG_TYPEC is not set +# CONFIG_UBIFS_ATIME_SUPPORT is not set +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +# CONFIG_UBIFS_FS_AUTHENTICATION is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_SECURITY=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_ZSTD is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_USB=y +# CONFIG_USBIP_CORE is not set +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_AUDIO is not set +CONFIG_USB_AUTOSUSPEND_DELAY=2 +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_CDNS_SUPPORT is not set +# CONFIG_USB_CHAOSKEY is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_COMMON=y +CONFIG_USB_CONFIGFS=y +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_EEM is not set +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_HID=y +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +# CONFIG_USB_CONFIGFS_F_MIDI is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +CONFIG_USB_CONFIGFS_F_UAC1=y +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_UVC=y +# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set +# CONFIG_USB_CONFIGFS_NCM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_SERIAL is not set +CONFIG_USB_CONFIGFS_UEVENT=y +# CONFIG_USB_CONN_GPIO is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DUMMY_HCD is not set +# CONFIG_USB_DWC2 is not set +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set +# CONFIG_USB_DWC3_HOST is not set +CONFIG_USB_DWC3_OF_SIMPLE=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_FEW_INIT_RETRIES is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FUSB300 is not set +CONFIG_USB_F_FS=y +CONFIG_USB_F_HID=y +CONFIG_USB_F_UAC1=y +CONFIG_USB_F_UAC2=y +CONFIG_USB_F_UVC=y +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 +CONFIG_USB_GADGET_VBUS_DRAW=500 +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_G_WEBCAM is not set +# CONFIG_USB_HCD_TEST_MODE is not set +# CONFIG_USB_HID is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1301 is not set +# CONFIG_USB_ISP1760 is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_LEGOTOWER is not set +CONFIG_USB_LIBCOMPOSITE=y +# CONFIG_USB_LINK_LAYER_TEST is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_ONBOARD_HUB is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set +# CONFIG_USB_OTG_PRODUCTLIST is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_RAW_GADGET is not set +CONFIG_USB_ROLE_SWITCH=y +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_TMC is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_U_AUDIO=y +# CONFIG_USB_WDM is not set +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_PCI_RENESAS is not set +CONFIG_USB_XHCI_PLATFORM=y +# CONFIG_USB_YUREX is not set +# CONFIG_USB_ZERO is not set +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_MAX9286 is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +# CONFIG_VIDEO_S5C73M3 is not set +# CONFIG_VIRT_WIFI is not set +# CONFIG_VT6656 is not set +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PRIV=y +CONFIG_WEXT_PROC=y +# CONFIG_WFX is not set +CONFIG_WIFI_BUILD_MODULE=y +# CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR is not set +# CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is not set +CONFIG_WIRELESS_EXT=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_MICROCHIP is not set +CONFIG_WLAN_VENDOR_PURELIFI=y +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +CONFIG_WLAN_VENDOR_SILABS=y +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WL_ROCKCHIP=m +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_XILLYUSB is not set +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +# CONFIG_ZRAM is not set +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/arch/arm/configs/rv1126b-evb.config b/arch/arm/configs/rv1126b-evb.config index 8b0149902338..9a74d75f4196 100644 --- a/arch/arm/configs/rv1126b-evb.config +++ b/arch/arm/configs/rv1126b-evb.config @@ -31,7 +31,6 @@ CONFIG_RK_CMA_PROCFS=y CONFIG_RK_DMABUF_PROCFS=y CONFIG_RK_MEMBLOCK_PROCFS=y CONFIG_ROCKCHIP_DEBUG=y -CONFIG_ROCKCHIP_OPP=y CONFIG_ROCKCHIP_RGA_PROC_FS=y CONFIG_ROCKCHIP_VENDOR_STORAGE=y CONFIG_SND_SOC_DUMMY_CODEC=y @@ -843,6 +842,7 @@ CONFIG_TOUCHSCREEN_GT1X=y # CONFIG_TOUCHSCREEN_HIDEEP is not set # CONFIG_TOUCHSCREEN_HIMAX_CHIPSET is not set # CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set +# CONFIG_TOUCHSCREEN_HYN is not set # CONFIG_TOUCHSCREEN_ILI210X is not set # CONFIG_TOUCHSCREEN_ILITEK is not set # CONFIG_TOUCHSCREEN_IMAGIS is not set diff --git a/arch/arm/configs/rv1126b-fastboot.config b/arch/arm/configs/rv1126b-fastboot.config index 0a84152f88f2..6c54b1bdd8db 100644 --- a/arch/arm/configs/rv1126b-fastboot.config +++ b/arch/arm/configs/rv1126b-fastboot.config @@ -1,24 +1,24 @@ CONFIG_BLK_DEV_INITRD=y -CONFIG_CRC16=m +CONFIG_CRC16=y CONFIG_CRYPTO=y CONFIG_DAX=y +CONFIG_ELF_CORE=y CONFIG_EROFS_FS=y -# CONFIG_ETHERNET is not set CONFIG_EXT4_FS=m +CONFIG_EXTCON=y CONFIG_FILE_LOCKING=y +CONFIG_INPUT=y CONFIG_JFFS2_FS=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_XZ is not set CONFIG_LIBCRC32C=y -CONFIG_MAILBOX=y -# CONFIG_MDIO_DEVICE is not set CONFIG_MMC=y CONFIG_MSDOS_FS=m CONFIG_MSDOS_PARTITION=y CONFIG_MTD_BLOCK=m CONFIG_NLS_CODEPAGE_936=m -# CONFIG_PHYLIB is not set CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y +CONFIG_RK_DMABUF_PROCFS=y CONFIG_ROCKCHIP_DVBM=y CONFIG_ROCKCHIP_HW_DECOMPRESS=y CONFIG_ROCKCHIP_MULTI_RGA=y @@ -28,18 +28,26 @@ CONFIG_ROCKCHIP_THUNDER_BOOT=y CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK=y CONFIG_ROCKCHIP_VENDOR_STORAGE=m # CONFIG_SLUB_SYSFS is not set -CONFIG_SND_SIMPLE_CARD=m -CONFIG_SND_SIMPLE_CARD_UTILS=m +# CONFIG_SND_SIMPLE_CARD is not set +CONFIG_SND_SOC_DUMMY_CODEC=m +CONFIG_SND_SOC_RK_DSM=m CONFIG_SND_SOC_ROCKCHIP=m +CONFIG_SND_SOC_ROCKCHIP_ASRC=m +CONFIG_SND_SOC_ROCKCHIP_PDM_V2=m CONFIG_SND_SOC_ROCKCHIP_SAI=m -CONFIG_SND_SOC_RV1106=m CONFIG_SPI=y +CONFIG_SQUASHFS_LZ4=y CONFIG_VFAT_FS=m +# CONFIG_VIDEO_RK_IRCUT is not set +CONFIG_VIDEO_ROCKCHIP_AIISP=y +CONFIG_VIDEO_ROCKCHIP_AVSP=y CONFIG_VIDEO_ROCKCHIP_CIF=y +CONFIG_VIDEO_ROCKCHIP_FEC=y CONFIG_VIDEO_ROCKCHIP_ISP=y CONFIG_VIDEO_ROCKCHIP_VPSS=y CONFIG_VIDEO_SC200AI=y CONFIG_VIDEO_SC450AI=y +CONFIG_VIDEO_SC850SL=y # CONFIG_AD2S1200 is not set # CONFIG_AD2S1210 is not set # CONFIG_AD2S90 is not set @@ -109,16 +117,14 @@ CONFIG_VIDEO_SC450AI=y # CONFIG_ADXRS290 is not set # CONFIG_ADXRS450 is not set # CONFIG_AFE4403 is not set -# CONFIG_ALTERA_MBOX is not set -# CONFIG_ARM_MHU is not set -# CONFIG_ARM_MHU_V2 is not set -# CONFIG_ARM_SCPI_PROTOCOL is not set # CONFIG_AS3935 is not set # CONFIG_BMA220 is not set # CONFIG_BMC150_MAGN_SPI is not set # CONFIG_BMI088_ACCEL is not set # CONFIG_BMI160_SPI is not set # CONFIG_BSD_DISKLABEL is not set +# CONFIG_CHARGER_BQ24190 is not set +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y # CONFIG_CRYPTO_842 is not set # CONFIG_CRYPTO_ADIANTUM is not set # CONFIG_CRYPTO_AEGIS128 is not set @@ -215,8 +221,11 @@ CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y # CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_XXHASH is not set # CONFIG_CRYPTO_ZSTD is not set +# CONFIG_DM9051 is not set # CONFIG_EEPROM_93XX46 is not set # CONFIG_EEPROM_AT25 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set # CONFIG_EROFS_FS_DEBUG is not set # CONFIG_EROFS_FS_XATTR is not set # CONFIG_EROFS_FS_ZIP is not set @@ -224,6 +233,14 @@ CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y # CONFIG_EXT4_FS_POSIX_ACL is not set # CONFIG_EXT4_FS_SECURITY is not set CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXTCON_ADC_JACK is not set +# CONFIG_EXTCON_FSA9480 is not set +# CONFIG_EXTCON_GPIO is not set +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_PTN5150 is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +# CONFIG_EXTCON_USB_GPIO is not set # CONFIG_EZX_PCAP is not set CONFIG_FAT_DEFAULT_CODEPAGE=936 CONFIG_FAT_DEFAULT_IOCHARSET="cp936" @@ -241,10 +258,27 @@ CONFIG_FS_MBCACHE=m # CONFIG_GPIO_PISOSR is not set # CONFIG_GPIO_XRA1403 is not set # CONFIG_HI8435 is not set +# CONFIG_HID is not set +# CONFIG_I2C_HID_OF is not set +# CONFIG_I2C_HID_OF_ELAN is not set +# CONFIG_I2C_HID_OF_GOODIX is not set # CONFIG_IIO_SSP_SENSORHUB is not set CONFIG_INITCALL_ASYNC=y # CONFIG_INITRAMFS_FORCE is not set CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INPUT_EVBUG is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_KEYBOARD=y +# CONFIG_INPUT_MATRIXKMAP is not set +# CONFIG_INPUT_MISC is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INV_ICM42600_SPI is not set # CONFIG_INV_ICM42670_SPI is not set # CONFIG_INV_MPU6050_SPI is not set @@ -264,6 +298,36 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_RUBIN is not set # CONFIG_JFFS2_SUMMARY is not set CONFIG_JFFS2_ZLIB=y +CONFIG_KEYBOARD_ADC=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_CYPRESS_SF is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PINEPHONE is not set +# CONFIG_KEYBOARD_QT1050 is not set +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KS8851 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set # CONFIG_LMK04832 is not set # CONFIG_LTC1660 is not set @@ -271,8 +335,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_LTC2632 is not set # CONFIG_LTC2688 is not set # CONFIG_LTC2983 is not set -# CONFIG_MAILBOX_POLL_PERIOD_US is not set -# CONFIG_MAILBOX_TEST is not set +CONFIG_LZ4_DECOMPRESS=y # CONFIG_MAX1027 is not set # CONFIG_MAX11100 is not set # CONFIG_MAX1118 is not set @@ -322,6 +385,7 @@ CONFIG_MMC_QUEUE_DEPTH=1 # CONFIG_MMC_USDHI6ROL0 is not set # CONFIG_MOXTET is not set # CONFIG_MPL115_SPI is not set +# CONFIG_MSE102X is not set CONFIG_MTD_BLKDEVS=m # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_MCHP23K256 is not set @@ -357,11 +421,12 @@ CONFIG_MTD_SPI_NOR_WINBOND=y # CONFIG_MTD_SPI_NOR_XMC is not set # CONFIG_MTD_SPI_NOR_XTX is not set # CONFIG_MTD_SST25L is not set +CONFIG_NET_VENDOR_ADI=y # CONFIG_PI433 is not set -# CONFIG_PL320_MBOX is not set -# CONFIG_PLATFORM_MHU is not set # CONFIG_PWRSEQ_EMMC is not set CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_RC_CORE is not set # CONFIG_RD_BZIP2 is not set # CONFIG_RD_GZIP is not set # CONFIG_RD_LZ4 is not set @@ -371,16 +436,15 @@ CONFIG_PWRSEQ_SIMPLE=y # CONFIG_RD_ZSTD is not set CONFIG_REGMAP_SPI=y # CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_RMI4_CORE is not set # CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST is not set -# CONFIG_ROCKCHIP_MBOX is not set # CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=m # CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set +# CONFIG_ROCKCHIP_REMOTECTL is not set CONFIG_ROCKCHIP_RGA_DEBUGGER=y CONFIG_ROCKCHIP_THUNDER_BOOT_MMC=y -# CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE is not set CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y -# CONFIG_RPMSG_QCOM_GLINK_RPM is not set # CONFIG_RTC_DRV_DS1302 is not set # CONFIG_RTC_DRV_DS1305 is not set # CONFIG_RTC_DRV_DS1343 is not set @@ -399,15 +463,21 @@ CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y # CONFIG_SCA3300 is not set # CONFIG_SDIO_UART is not set # CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_SENSORS_LIS3_SPI is not set # CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SENSOR_DEVICE is not set # CONFIG_SERIAL_MAX3100 is not set # CONFIG_SERIAL_MAX310X is not set +CONFIG_SND_JACK_INPUT_DEV=y # CONFIG_SND_SOC_ADAU1372_SPI is not set # CONFIG_SND_SOC_ADAU1761_SPI is not set # CONFIG_SND_SOC_AK4104 is not set # CONFIG_SND_SOC_CS35L41_SPI is not set # CONFIG_SND_SOC_CS35L45_SPI is not set # CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set # CONFIG_SND_SOC_ES8328_SPI is not set # CONFIG_SND_SOC_PCM179X_SPI is not set # CONFIG_SND_SOC_PCM186X_SPI is not set @@ -415,6 +485,7 @@ CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y # CONFIG_SND_SOC_PCM3168A_SPI is not set # CONFIG_SND_SOC_PCM512x_SPI is not set # CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +CONFIG_SND_SOC_ROCKCHIP_MULTICODECS=m # CONFIG_SND_SOC_ROCKCHIP_SPI_CODEC is not set # CONFIG_SND_SOC_SSM2602_SPI is not set # CONFIG_SND_SOC_TLV320AIC23_SPI is not set @@ -423,11 +494,13 @@ CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y # CONFIG_SND_SOC_WM8731_SPI is not set # CONFIG_SND_SOC_WM8770 is not set # CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8962 is not set # CONFIG_SND_SOC_ZL38060 is not set # CONFIG_SND_SPI is not set # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_SPI_ALTERA is not set # CONFIG_SPI_AMD is not set +# CONFIG_SPI_AX88796C is not set # CONFIG_SPI_AXI_SPI_ENGINE is not set # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_CADENCE is not set diff --git a/arch/arm/configs/rv1126b-ipc.config b/arch/arm/configs/rv1126b-ipc.config index c2e72a2f6547..80900a2ccda4 100644 --- a/arch/arm/configs/rv1126b-ipc.config +++ b/arch/arm/configs/rv1126b-ipc.config @@ -4,7 +4,6 @@ CONFIG_MSDOS_PARTITION=y CONFIG_MTD_BLOCK=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_ROCKCHIP_OPP=y CONFIG_ROCKCHIP_RGA_PROC_FS=y CONFIG_SPI=y CONFIG_VFAT_FS=y diff --git a/arch/arm/configs/rv1126b-nand.config b/arch/arm/configs/rv1126b-nand.config index c356b4f35bfd..9f4c2f0163c5 100644 --- a/arch/arm/configs/rv1126b-nand.config +++ b/arch/arm/configs/rv1126b-nand.config @@ -1,6 +1,81 @@ CONFIG_CRC16=y CONFIG_CRYPTO=y CONFIG_MTD_UBI=y +CONFIG_SPI=y +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD3552R is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD74413R is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADA4250 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADRF6780 is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_AFE4403 is not set +# CONFIG_AS3935 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_BMI160_SPI is not set # CONFIG_CRYPTO_842 is not set CONFIG_CRYPTO_ACOMP2=y # CONFIG_CRYPTO_ADIANTUM is not set @@ -103,14 +178,204 @@ CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y # CONFIG_CRYPTO_XTS is not set # CONFIG_CRYPTO_XXHASH is not set # CONFIG_CRYPTO_ZSTD is not set +# CONFIG_DM9051 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_FXOS8700_SPI is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_HI8435 is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_ICM42670_SPI is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_KS8851 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_LMK04832 is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2688 is not set +# CONFIG_LTC2983 is not set CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MOXTET is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MSE102X is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +CONFIG_MTD_NAND_BBT_USING_FLASH=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NAND_ATO=y +CONFIG_MTD_SPI_NAND_BIWIN=y +CONFIG_MTD_SPI_NAND_DEVICE_AUTOSELECT=y +CONFIG_MTD_SPI_NAND_DOSILICON=y +CONFIG_MTD_SPI_NAND_ESMT=y +CONFIG_MTD_SPI_NAND_ETRON=y +CONFIG_MTD_SPI_NAND_FMSH=y +CONFIG_MTD_SPI_NAND_FORESEE=y +CONFIG_MTD_SPI_NAND_GIGADEVICE=y +CONFIG_MTD_SPI_NAND_GSTO=y +CONFIG_MTD_SPI_NAND_HIKSEMI=y +CONFIG_MTD_SPI_NAND_HYF=y +CONFIG_MTD_SPI_NAND_JSC=y +CONFIG_MTD_SPI_NAND_MACRONIX=y +CONFIG_MTD_SPI_NAND_MICRON=y +CONFIG_MTD_SPI_NAND_PARAGON=y +CONFIG_MTD_SPI_NAND_SILICONGO=y +CONFIG_MTD_SPI_NAND_SKYHIGH=y +CONFIG_MTD_SPI_NAND_TOSHIBA=y +CONFIG_MTD_SPI_NAND_UNIM=y +CONFIG_MTD_SPI_NAND_WINBOND=y +CONFIG_MTD_SPI_NAND_XINCUN=y +CONFIG_MTD_SPI_NAND_XTX=y +CONFIG_MTD_SPI_NAND_ZBIT=y +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_SST25L is not set CONFIG_MTD_UBI_BEB_LIMIT=20 CONFIG_MTD_UBI_BLOCK=y # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set CONFIG_MTD_UBI_WL_THRESHOLD=4096 +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_PI433 is not set +# CONFIG_QCA7000_SPI is not set +CONFIG_REGMAP_SPI=y +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set CONFIG_SGL_ALLOC=y +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +# CONFIG_SND_SOC_ROCKCHIP_SPI_CODEC is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_WM8731_SPI is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SPI is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AX88796C is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_FSPI is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_SPI is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_ROCKCHIP_SLAVE is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set # CONFIG_UBIFS_ATIME_SUPPORT is not set CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_ADVANCED_COMPR=y @@ -120,6 +385,9 @@ CONFIG_UBIFS_FS_SECURITY=y CONFIG_UBIFS_FS_XATTR=y CONFIG_UBIFS_FS_ZLIB=y # CONFIG_UBIFS_FS_ZSTD is not set +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +# CONFIG_VIDEO_S5C73M3 is not set CONFIG_ZLIB_DEFLATE=y CONFIG_ZLIB_INFLATE=y # CONFIG_ZRAM is not set diff --git a/arch/arm/configs/rv1126b-rndis.config b/arch/arm/configs/rv1126b-rndis.config index b3d39b93ea11..9c0c5e431e4b 100644 --- a/arch/arm/configs/rv1126b-rndis.config +++ b/arch/arm/configs/rv1126b-rndis.config @@ -1,5 +1,6 @@ -CONFIG_CONFIGFS_FS=y +CONFIG_CONFIGFS_FS=m CONFIG_EXTCON=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=m CONFIG_USB_SUPPORT=y CONFIG_VIDEOBUF2_DMA_SG=m # CONFIG_APPLE_MFI_FASTCHARGE is not set @@ -12,6 +13,7 @@ CONFIG_VIDEOBUF2_DMA_SG=m # CONFIG_EXTCON_RT8973A is not set # CONFIG_EXTCON_SM5502 is not set # CONFIG_EXTCON_USB_GPIO is not set +# CONFIG_HISI_HIKEY_USB is not set # CONFIG_I2C_CP2615 is not set # CONFIG_I2C_DIOLAN_U2C is not set # CONFIG_I2C_ROBOTFUZZ_OSIF is not set @@ -55,13 +57,13 @@ CONFIG_USB_CONFIGFS=m # CONFIG_USB_CONFIGFS_ECM_SUBSET is not set # CONFIG_USB_CONFIGFS_EEM is not set CONFIG_USB_CONFIGFS_F_FS=y -# CONFIG_USB_CONFIGFS_F_HID is not set +CONFIG_USB_CONFIGFS_F_HID=y # CONFIG_USB_CONFIGFS_F_LB_SS is not set # CONFIG_USB_CONFIGFS_F_MIDI is not set # CONFIG_USB_CONFIGFS_F_PRINTER is not set -# CONFIG_USB_CONFIGFS_F_UAC1 is not set +CONFIG_USB_CONFIGFS_F_UAC1=y # CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set -# CONFIG_USB_CONFIGFS_F_UAC2 is not set +CONFIG_USB_CONFIGFS_F_UAC2=y CONFIG_USB_CONFIGFS_F_UVC=y # CONFIG_USB_CONFIGFS_MASS_STORAGE is not set # CONFIG_USB_CONFIGFS_NCM is not set @@ -76,12 +78,16 @@ CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DUMMY_HCD is not set # CONFIG_USB_DWC2 is not set CONFIG_USB_DWC3=m -# CONFIG_USB_DWC3_DUAL_ROLE is not set -CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_DUAL_ROLE=y +# CONFIG_USB_DWC3_GADGET is not set # CONFIG_USB_DWC3_HOST is not set CONFIG_USB_DWC3_OF_SIMPLE=m # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_EHSET_TEST_FIXTURE is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_EMI62 is not set @@ -94,7 +100,10 @@ CONFIG_USB_DWC3_OF_SIMPLE=m # CONFIG_USB_FUNCTIONFS is not set # CONFIG_USB_FUSB300 is not set CONFIG_USB_F_FS=m +CONFIG_USB_F_HID=m CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_UAC1=m +CONFIG_USB_F_UAC2=m CONFIG_USB_F_UVC=m CONFIG_USB_GADGET=m # CONFIG_USB_GADGETFS is not set @@ -138,7 +147,8 @@ CONFIG_USB_LIBCOMPOSITE=m # CONFIG_USB_MV_UDC is not set # CONFIG_USB_NET2272 is not set # CONFIG_USB_NET_DRIVERS is not set -# CONFIG_USB_OHCI_HCD is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PLATFORM=m # CONFIG_USB_ONBOARD_HUB is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set @@ -149,9 +159,10 @@ CONFIG_USB_LIBCOMPOSITE=m # CONFIG_USB_R8A66597 is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_RAW_GADGET is not set -# CONFIG_USB_ROLE_SWITCH is not set +CONFIG_USB_ROLE_SWITCH=m # CONFIG_USB_SERIAL is not set # CONFIG_USB_SEVSEG is not set +# CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_SNP_UDC_PLAT is not set # CONFIG_USB_TEST is not set @@ -159,9 +170,13 @@ CONFIG_USB_LIBCOMPOSITE=m # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_ULPI is not set # CONFIG_USB_ULPI_BUS is not set +CONFIG_USB_U_AUDIO=m CONFIG_USB_U_ETHER=m # CONFIG_USB_WDM is not set -# CONFIG_USB_XHCI_HCD is not set +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_PCI_RENESAS is not set +CONFIG_USB_XHCI_PLATFORM=m # CONFIG_USB_YUREX is not set # CONFIG_USB_ZERO is not set # CONFIG_XILLYUSB is not set diff --git a/arch/arm/configs/rv1126b-tb.config b/arch/arm/configs/rv1126b-tb.config new file mode 100644 index 000000000000..7a542462da2b --- /dev/null +++ b/arch/arm/configs/rv1126b-tb.config @@ -0,0 +1,464 @@ +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CRYPTO=y +CONFIG_DAX=y +CONFIG_EROFS_FS=y +# CONFIG_ETHERNET is not set +CONFIG_JFFS2_FS=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_XZ is not set +CONFIG_LIBCRC32C=y +CONFIG_MAILBOX=y +# CONFIG_MDIO_DEVICE is not set +CONFIG_MMC=y +CONFIG_MTD_BLOCK=y +# CONFIG_PHYLIB is not set +CONFIG_PHY_ROCKCHIP_CSI2_DPHY=y +CONFIG_ROCKCHIP_DVBM=y +CONFIG_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_ROCKCHIP_MULTI_RGA=y +CONFIG_ROCKCHIP_RAMDISK=y +CONFIG_ROCKCHIP_RGA_PROC_FS=y +CONFIG_ROCKCHIP_RKNPU=y +CONFIG_ROCKCHIP_THUNDER_BOOT=y +CONFIG_ROCKCHIP_THUNDER_BOOT_DEFER_FREE_MEMBLOCK=y +CONFIG_ROCKCHIP_VENDOR_STORAGE=y +# CONFIG_SLUB_SYSFS is not set +CONFIG_SPI=y +CONFIG_VIDEO_ROCKCHIP_AIISP=y +CONFIG_VIDEO_ROCKCHIP_AVSP=y +CONFIG_VIDEO_ROCKCHIP_CIF=y +CONFIG_VIDEO_ROCKCHIP_ISP=y +CONFIG_VIDEO_ROCKCHIP_VPSS=y +CONFIG_VIDEO_SC200AI=y +CONFIG_VIDEO_SC450AI=y +# CONFIG_AD2S1200 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_AD2S90 is not set +# CONFIG_AD3552R is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5766 is not set +# CONFIG_AD5770R is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7124 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7266 is not set +# CONFIG_AD7280 is not set +# CONFIG_AD7292 is not set +# CONFIG_AD7293 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD74413R is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7606_IFACE_SPI is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7768_1 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD7949 is not set +# CONFIG_AD8366 is not set +# CONFIG_AD8801 is not set +# CONFIG_AD9523 is not set +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set +# CONFIG_ADA4250 is not set +# CONFIG_ADF4350 is not set +# CONFIG_ADF4371 is not set +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADIS16240 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16460 is not set +# CONFIG_ADIS16475 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_ADMV1013 is not set +# CONFIG_ADMV4420 is not set +# CONFIG_ADRF6780 is not set +# CONFIG_ADXL313_SPI is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_ADXL355_SPI is not set +# CONFIG_ADXL367_SPI is not set +# CONFIG_ADXL372_SPI is not set +# CONFIG_ADXRS290 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_AFE4403 is not set +# CONFIG_ALTERA_MBOX is not set +# CONFIG_ARM_MHU is not set +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set +# CONFIG_AS3935 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_BMI088_ACCEL is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_ADIANTUM is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_AES_ARM is not set +# CONFIG_CRYPTO_AES_TI is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_ARIA is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_BLAKE2B is not set +# CONFIG_CRYPTO_BLAKE2S_ARM is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CFB is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_CRC32 is not set +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_CURVE25519 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_DH is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_ECDH is not set +# CONFIG_CRYPTO_ECDSA is not set +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_ECRDSA is not set +# CONFIG_CRYPTO_ESSIV is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_HCTR2 is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_CRYPTO_JITTERENTROPY is not set +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set +CONFIG_CRYPTO_LIB_UTILS=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_MANAGER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_OFB is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_PCRYPT is not set +# CONFIG_CRYPTO_POLY1305 is not set +# CONFIG_CRYPTO_POLY1305_ARM is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RSA is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA1_ARM is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SM2 is not set +# CONFIG_CRYPTO_SM3_GENERIC is not set +# CONFIG_CRYPTO_SM4_GENERIC is not set +# CONFIG_CRYPTO_STREEBOG is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_VMAC is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_XXHASH is not set +# CONFIG_CRYPTO_ZSTD is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EROFS_FS_DEBUG is not set +# CONFIG_EROFS_FS_XATTR is not set +# CONFIG_EROFS_FS_ZIP is not set +# CONFIG_EZX_PCAP is not set +CONFIG_FS_DAX=y +CONFIG_FS_IOMAP=y +# CONFIG_FXLS8962AF_SPI is not set +# CONFIG_FXOS8700_SPI is not set +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set +# CONFIG_HI8435 is not set +# CONFIG_IIO_SSP_SENSORHUB is not set +CONFIG_INITCALL_ASYNC=y +# CONFIG_INITRAMFS_FORCE is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INV_ICM42600_SPI is not set +# CONFIG_INV_ICM42670_SPI is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_LMK04832 is not set +# CONFIG_LTC1660 is not set +# CONFIG_LTC2496 is not set +# CONFIG_LTC2632 is not set +# CONFIG_LTC2688 is not set +# CONFIG_LTC2983 is not set +CONFIG_MAILBOX_POLL_PERIOD_US=y +# CONFIG_MAILBOX_TEST is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX11205 is not set +# CONFIG_MAX1241 is not set +# CONFIG_MAX31856 is not set +# CONFIG_MAX31865 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3911 is not set +# CONFIG_MCP41010 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4922 is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_INTEL_M10_BMC is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_OCELOT is not set +# CONFIG_MFD_RK806_SPI is not set +# CONFIG_MFD_RSMU_SPI is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_CQHCI is not set +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=m +# CONFIG_MMC_HSQ is not set +# CONFIG_MMC_MTK is not set +CONFIG_MMC_QUEUE_DEPTH=1 +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_TEST is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MOXTET is not set +# CONFIG_MPL115_SPI is not set +CONFIG_MTD_BLKDEVS=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_MCHP48L640 is not set +# CONFIG_MTD_SPI_NAND is not set +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_ATMEL is not set +# CONFIG_MTD_SPI_NOR_BOYA is not set +# CONFIG_MTD_SPI_NOR_CATALYST is not set +# CONFIG_MTD_SPI_NOR_DEVICE_AUTOSELECT is not set +# CONFIG_MTD_SPI_NOR_DOSILICON is not set +# CONFIG_MTD_SPI_NOR_EON is not set +# CONFIG_MTD_SPI_NOR_ESMT is not set +# CONFIG_MTD_SPI_NOR_EVERSPIN is not set +# CONFIG_MTD_SPI_NOR_FMSH is not set +# CONFIG_MTD_SPI_NOR_FUJITSU is not set +CONFIG_MTD_SPI_NOR_GIGADEVICE=y +# CONFIG_MTD_SPI_NOR_INTEL is not set +# CONFIG_MTD_SPI_NOR_ISSI is not set +CONFIG_MTD_SPI_NOR_MACRONIX=y +CONFIG_MTD_SPI_NOR_MISC=y +# CONFIG_MTD_SPI_NOR_NORMEM is not set +# CONFIG_MTD_SPI_NOR_PUYA is not set +# CONFIG_MTD_SPI_NOR_SPANSION is not set +# CONFIG_MTD_SPI_NOR_SST is not set +# CONFIG_MTD_SPI_NOR_STMICRO is not set +# CONFIG_MTD_SPI_NOR_SWP_DISABLE is not set +CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y +# CONFIG_MTD_SPI_NOR_SWP_KEEP is not set +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPI_NOR_WINBOND=y +# CONFIG_MTD_SPI_NOR_XILINX is not set +# CONFIG_MTD_SPI_NOR_XMC is not set +CONFIG_MTD_SPI_NOR_XTX=y +# CONFIG_MTD_SST25L is not set +# CONFIG_PI433 is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PLATFORM_MHU is not set +# CONFIG_PWRSEQ_EMMC is not set +CONFIG_PWRSEQ_SIMPLE=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_GZIP is not set +# CONFIG_RD_LZ4 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_ZSTD is not set +CONFIG_REGMAP_SPI=y +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_ROCKCHIP_HW_DECOMPRESS_TEST is not set +CONFIG_ROCKCHIP_MBOX=y +# CONFIG_ROCKCHIP_MBOX_DEMO is not set +# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set +# CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE is not set +# CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set +CONFIG_ROCKCHIP_RGA_DEBUGGER=y +CONFIG_ROCKCHIP_THUNDER_BOOT_MMC=y +CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE=y +CONFIG_ROCKCHIP_THUNDER_BOOT_SFC=y +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +# CONFIG_RPMSG_ROCKCHIP_MBOX is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_MCP795 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_SCA3000 is not set +# CONFIG_SCA3300 is not set +# CONFIG_SDIO_UART is not set +# CONFIG_SENSORS_HMC5843_SPI is not set +# CONFIG_SENSORS_RM3100_SPI is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SND_SOC_ADAU1372_SPI is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_CS35L41_SPI is not set +# CONFIG_SND_SOC_CS35L45_SPI is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3060_SPI is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RK3399_GRU_SOUND is not set +# CONFIG_SND_SOC_ROCKCHIP_SPI_CODEC is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X_SPI is not set +# CONFIG_SND_SOC_WM8731_SPI is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_ZL38060 is not set +# CONFIG_SND_SPI is not set +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AMD is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_CADENCE_QUADSPI is not set +# CONFIG_SPI_CADENCE_XSPI is not set +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_LOOPBACK_TEST is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_MICROCHIP_CORE is not set +# CONFIG_SPI_MICROCHIP_CORE_QSPI is not set +# CONFIG_SPI_MUX is not set +# CONFIG_SPI_MXIC is not set +# CONFIG_SPI_NXP_FLEXSPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_FSPI is not set +# CONFIG_SPI_ROCKCHIP_FLEXBUS_SPI is not set +CONFIG_SPI_ROCKCHIP_SFC=y +# CONFIG_SPI_ROCKCHIP_SLAVE is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_SIFIVE is not set +# CONFIG_SPI_SLAVE is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS124S08 is not set +# CONFIG_TI_ADS131E08 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8344 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC7311 is not set +# CONFIG_TI_DAC7612 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_TI_TSC2046 is not set +# CONFIG_USB_MAX3420_UDC is not set +# CONFIG_USB_MAX3421_HCD is not set +# CONFIG_VIDEO_GS1662 is not set +# CONFIG_VIDEO_ROCKCHIP_PREISP is not set +CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP=y +CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_SETUP=y +# CONFIG_VIDEO_S5C73M3 is not set +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/rv1126b-wakeup.config b/arch/arm/configs/rv1126b-wakeup.config deleted file mode 100644 index bcb2874830e8..000000000000 --- a/arch/arm/configs/rv1126b-wakeup.config +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_INPUT=y -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_GPIO=y -CONFIG_SND_JACK_INPUT_DEV=y diff --git a/arch/arm/configs/rv1126b_defconfig b/arch/arm/configs/rv1126b_defconfig index 4a9994383bc1..41a3e4cd39dd 100644 --- a/arch/arm/configs/rv1126b_defconfig +++ b/arch/arm/configs/rv1126b_defconfig @@ -175,6 +175,7 @@ CONFIG_ROCKCHIP_IOMMU=y CONFIG_CPU_RV1126B=y CONFIG_ROCKCHIP_AMP=y CONFIG_ROCKCHIP_CPUINFO=y +CONFIG_ROCKCHIP_OPP=y CONFIG_ROCKCHIP_PM_DOMAINS=y CONFIG_ROCKCHIP_SYSTEM_MONITOR=y CONFIG_FIQ_DEBUGGER=y diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 17b7de71aa21..144da30f1e8e 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -173,6 +173,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet-k108.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet-rkg11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-rk817-tablet-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566pro-evb2-lp4x-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-dual-channel-lvds.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dtb @@ -297,12 +298,15 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-test2-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-test2-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-test3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-test5-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-toybrick-d0-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v20.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v20-amp.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v20-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v20-ufs.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v21.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576-vehicle-evb-v21-mcu.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576s-evb1-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576s-evb1-v10-linux.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3576s-tablet-v10.dtb @@ -377,14 +381,22 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-tablet-rk806-single-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-tablet-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-tablet-v11.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-amp.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-bt-sco.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-dual-4k.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-dv.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-fastboot-emmc.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-fastboot-spi-nand.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-fastboot-spi-nor.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v10-spi-nor.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb1-v11-dual-4k.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-aov-dual-cam.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-mcu-k350c4516t.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-rgb-Q7050ITH2641AA1T.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb2-v10-tb-400w.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb3-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-evb4-v10.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rv1126b-iotest-v10.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3562-dictpen-test3-v20.dts b/arch/arm64/boot/dts/rockchip/rk3562-dictpen-test3-v20.dts index 6bac83ca1421..026c74f4172e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-dictpen-test3-v20.dts +++ b/arch/arm64/boot/dts/rockchip/rk3562-dictpen-test3-v20.dts @@ -919,6 +919,26 @@ power-supply = <&vcc3v3_lcd>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + + power-supply = <&vcc3v3_lcd>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c5 { @@ -1012,6 +1032,22 @@ <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3562-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3562-evb.dtsi index c1ac45ec00fd..df67dca3040f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562-evb.dtsi @@ -505,6 +505,29 @@ */ power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + /* + * power-supply should switche to vcc3v3_lcd1_n + * when mipi panel is connected to dsi1. + */ + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &jpegd { @@ -526,6 +549,22 @@ <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3562-iotest-lp3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3562-iotest-lp3-v10.dtsi index 7f2c5fcdaab8..e8b8c8dc0851 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-iotest-lp3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562-iotest-lp3-v10.dtsi @@ -492,6 +492,29 @@ */ power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + /* + * power-supply should switche to vcc3v3_lcd1_n + * when mipi panel is connected to dsi1. + */ + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &pinctrl { @@ -507,6 +530,22 @@ <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3562-test1-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3562-test1-ddr3-v10.dtsi index 41df5362afd6..54c21e6a7c30 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-test1-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562-test1-ddr3-v10.dtsi @@ -227,6 +227,29 @@ power-supply = <&vcc3v3_lcd_n>; }; +&hynitron { + compatible = "hyn,3240"; + reg = <0x5a>; + /* + * power-supply should switche to vcc3v3_lcd1_n + * when mipi panel is connected to dsi1. + */ + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; +}; + &mdio0 { rgmii_phy: phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; @@ -262,6 +285,22 @@ <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3562-toybrick.dtsi b/arch/arm64/boot/dts/rockchip/rk3562-toybrick.dtsi index e179e6fe346d..1abaedaa14e3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3562-toybrick.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3562-toybrick.dtsi @@ -293,6 +293,29 @@ interrupts = ; wakeup-source; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + /* + * power-supply should switche to vcc3v3_lcd1_n + * when mipi panel is connected to dsi1. + */ + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &mdio0 { @@ -342,6 +365,22 @@ <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb-mipitest-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb-mipitest-v10.dtsi index fbce9e23b4ca..aa9a2c4490f5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb-mipitest-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb-mipitest-v10.dtsi @@ -227,6 +227,11 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + status = "disabled"; + power-supply = <&vcc3v3_lcd0_n>; +}; + &hdmi { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi index 421b2841808b..cd4b78b7cd6a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb1-ddr4-v10.dtsi @@ -226,6 +226,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c2 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10-eink.dts b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10-eink.dts index 83546eef6529..a44590ab8155 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10-eink.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10-eink.dts @@ -150,6 +150,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &hdmi { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi index f537e877216c..6582cc855d1c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb2-lp4x-v10.dtsi @@ -405,6 +405,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &mipi_csi2 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb3-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb3-ddr3-v10.dtsi index 772469cd9f5f..7baa5463ef6e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb3-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb3-ddr3-v10.dtsi @@ -188,6 +188,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c2 { status = "okay"; pinctrl-0 = <&i2c2m1_xfer>; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-evb5-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-evb5-lp4x-v10.dtsi index f8ca3d3fba4b..1cff49e6ea92 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-evb5-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3566-evb5-lp4x-v10.dtsi @@ -172,6 +172,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c5 { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink-w103.dts b/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink-w103.dts index e9fe59d0286d..dc093654ffa1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink-w103.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-rk817-eink-w103.dts @@ -790,6 +790,8 @@ cy,vkeys_x = <1404>; cy,vkeys_y = <1872>; + cy,max_x = <1872>; + cy,max_y = <1404>; cy,revert_x = <0>; cy,revert_y = <0>; cy,xy_exchange = <0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dts b/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dts new file mode 100644 index 000000000000..f8f4514ac1d3 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dts @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +#include "rk3566pro-evb2-lp4x-v10.dtsi" +#include "rk3568-android.dtsi" + +/* vp0 for HDMI, vp1 for rgb */ +&vp0 { + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER0 | 1 << ROCKCHIP_VOP2_ESMART0 | 1 << ROCKCHIP_VOP2_SMART0)>; + rockchip,primary-plane = ; +}; + +&vp1 { + rockchip,plane-mask = <(1 << ROCKCHIP_VOP2_CLUSTER1 | 1 << ROCKCHIP_VOP2_ESMART1 | 1 << ROCKCHIP_VOP2_SMART1)>; + rockchip,primary-plane = ; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dtsi new file mode 100644 index 000000000000..9e89355fe1af --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566pro-evb2-lp4x-v10.dtsi @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include "rk3566pro.dtsi" +#include "rk3566-evb.dtsi" + +/ { + model = "Rockchip RK3566PRO EVB2 LP4X V10 Board"; + compatible = "rockchip,rk3566pro-evb2-lp4x-v10", "rockchip,rk3566pro", "rockchip,rk3566"; + + vcc_camera: vcc-camera-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&camera_pwr>; + regulator-name = "vcc_camera"; + enable-active-high; + regulator-always-on; + regulator-boot-on; + }; + + vcc3v3_pcie: vcc3v3-pcie { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pcie"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>; + startup-delay-us = <5000>; + vin-supply = <&dc_12v>; + }; +}; + +&bt_sound { + status = "disabled"; + simple-audio-card,cpu { + sound-dai = <&i2s2_2ch>; + }; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu_rk860>; +}; + +&bus_npu { + pvtm-supply = <&vdd_cpu_rk860>; +}; + +&combphy1_usq { + status = "okay"; +}; + +&combphy2_psq { + status = "okay"; +}; + +&csi2_dphy_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + /* + * dphy0 only used for full mode, + * full mode and split mode are mutually exclusive + */ + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + dphy0_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&gc8034_out>; + data-lanes = <1 2 3 4>; + }; + + mipi_in_ucam1: endpoint@2 { + reg = <2>; + remote-endpoint = <&ov5695_out>; + data-lanes = <1 2>; + }; + + mipi_in_ucam2: endpoint@3 { + reg = <3>; + remote-endpoint = <&gc5025_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + dphy0_out: endpoint@1 { + reg = <1>; + remote-endpoint = <&isp0_in_dphy0>; + }; + }; + }; +}; + +&csi2_dphy1 { + status = "disabled"; + + /* + * dphy1 only used for split mode, + * can be used concurrently with dphy2 + * full mode and split mode are mutually exclusive + */ + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + dphy1_in: endpoint@1 { + reg = <1>; + //remote-endpoint = <&ov5695_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + dphy1_out: endpoint@1 { + reg = <1>; + remote-endpoint = <&isp0_in>; + }; + }; + }; +}; + +&csi2_dphy2 { + status = "disabled"; + + /* + * dphy2 only used for split mode, + * can be used concurrently with dphy1 + * full mode and split mode are mutually exclusive + */ + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + dphy2_in: endpoint@1 { + reg = <1>; + //remote-endpoint = <&gc5025_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + dphy2_out: endpoint@1 { + reg = <1>; + remote-endpoint = <&mipi_csi2_input>; + }; + }; + }; +}; + +/* + * video_phy0 needs to be enabled + * when dsi0 is enabled + */ +&dsi0 { + status = "okay"; +}; + +&dsi0_in_vp0 { + status = "disabled"; +}; + +&dsi0_in_vp1 { + status = "okay"; +}; + +&dsi0_panel { + power-supply = <&vcc3v3_lcd0_n>; + reset-gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&lcd0_rst_gpio>; +}; + +&gmac1 { + phy-mode = "rgmii"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>; + assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&cru CLK_MAC1_2TOP>; + assigned-clock-rates = <0>, <125000000>; + + pinctrl-names = "default"; + pinctrl-0 = <&gmac1m1_miim + &gmac1m1_tx_bus2 + &gmac1m1_rx_bus2 + &gmac1m1_rgmii_clk + &gmac1m1_rgmii_bus>; + + tx_delay = <0x4f>; + rx_delay = <0x25>; + + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&i2c0 { + vdd_cpu_rk860: rk8600@40{ + compatible = "rockchip,rk8600"; + reg = <0x40>; + vin-supply = <&vcc5v0_sys>; + regulator-compatible = "rk860x-reg"; + regulator-name = "vdd_cpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1390000>; + regulator-init-microvolt = <900000>; + regulator-ramp-delay = <2300>; + rockchip,suspend-voltage-selector = <1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c2 { + status = "okay"; + pinctrl-0 = <&i2c2m1_xfer>; + + /* split mode: lane0/1 */ + ov5695: ov5695@36 { + status = "okay"; + compatible = "ovti,ov5695"; + reg = <0x36>; + clocks = <&cru CLK_CIF_OUT>; + clock-names = "xvclk"; + power-domains = <&power RK3568_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <&cif_clk>; + reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; + /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/ + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "TongJu"; + rockchip,camera-module-lens-name = "CHT842-MD"; + port { + ov5695_out: endpoint { + remote-endpoint = <&mipi_in_ucam1>; + data-lanes = <1 2>; + }; + }; + }; + + /* split mode: lane:2/3 */ + gc5025: gc5025@37 { + status = "okay"; + compatible = "galaxycore,gc5025"; + reg = <0x37>; + clocks = <&pmucru CLK_WIFI>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&refclk_pins>; + reset-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + power-domains = <&power RK3568_PD_VI>; + /*power-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;*/ + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "front"; + rockchip,camera-module-name = "TongJu"; + rockchip,camera-module-lens-name = "CHT842-MD"; + port { + gc5025_out: endpoint { + remote-endpoint = <&mipi_in_ucam2>; + data-lanes = <1 2>; + }; + }; + }; + + /* full mode: lane0-3 */ + gc8034: gc8034@37 { + compatible = "galaxycore,gc8034"; + status = "okay"; + reg = <0x37>; + clocks = <&cru CLK_CIF_OUT>; + clock-names = "xvclk"; + power-domains = <&power RK3568_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <&cif_clk>; + reset-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "RK-CMK-8M-2-v1"; + rockchip,camera-module-lens-name = "CK8401"; + port { + gc8034_out: endpoint { + remote-endpoint = <&dphy0_in>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&i2c4 { + /* i2c4 sda conflict with camera pwdn */ + status = "disabled"; + + /* + * gc2145 needs to be disabled, + * when gmac1 is enabled; + * pinctrl conflicts; + */ + gc2145: gc2145@3c { + status = "disabled"; + compatible = "galaxycore,gc2145"; + reg = <0x3c>; + clocks = <&cru CLK_CIF_OUT>; + clock-names = "xvclk"; + power-domains = <&power RK3568_PD_VI>; + pinctrl-names = "default"; + /* conflict with gmac1m1_rgmii_pins & cif_clk*/ + pinctrl-0 = <&cif_clk &cif_dvp_clk &cif_dvp_bus16>; + + /*avdd-supply = <&vcc2v8_dvp>;*/ + /*dovdd-supply = <&vcc1v8_dvp>;*/ + /*dvdd-supply = <&vcc1v8_dvp>;*/ + + /*reset-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>;*/ + pwdn-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CameraKing"; + rockchip,camera-module-lens-name = "Largan"; + port { + gc2145_out: endpoint { + remote-endpoint = <&dvp_in_bcam>; + }; + }; + }; +}; + +&i2s2_2ch { + pinctrl-0 = <&i2s2m0_sclktx &i2s2m0_lrcktx &i2s2m0_sdi &i2s2m0_sdo>; + rockchip,bclk-fs = <32>; + status = "disabled"; +}; + +&mdio1 { + rgmii_phy0: phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + }; +}; + +/* + * power-supply should switche to vcc3v3_lcd1_n + * when mipi panel is connected to dsi1. + */ +>1x { + power-supply = <&vcc3v3_lcd0_n>; +}; + +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + +&mipi_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&dphy2_out>; + data-lanes = <1 2>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in>; + data-lanes = <1 2>; + }; + }; + }; +}; + +&video_phy0 { + status = "okay"; +}; + +&video_phy1 { + status = "disabled"; +}; + +&pcie2x1 { + reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + cam { + camera_pwr: camera-pwr { + rockchip,pins = + /* camera power en */ + <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = <2 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + wireless-bluetooth { + uart1_gpios: uart1-gpios { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lcd0 { + lcd0_rst_gpio: lcd0-rst-gpio { + rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + lcd1 { + lcd1_rst_gpio: lcd1-rst-gpio { + rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_dvp { + status = "disabled"; + + port { + /* Parallel bus endpoint */ + dvp_in_bcam: endpoint { + remote-endpoint = <&gc2145_out>; + bus-width = <8>; + vsync-active = <0>; + hsync-active = <1>; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + + port { + cif_mipi_in: endpoint { + remote-endpoint = <&mipi_csi2_output>; + data-lanes = <1 2>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp0_in: endpoint@0 { + reg = <0>; + remote-endpoint = <&dphy1_out>; + }; + isp0_in_dphy0: endpoint@1 { + reg = <1>; + remote-endpoint = <&dphy0_out>; + }; + }; +}; + +&route_dsi0 { + //status = "disabled"; + status = "okay"; + connect = <&vp1_out_dsi0>; +}; + +&sdmmc2 { + status = "disabled"; +}; + +&sdmmc1 { + max-frequency = <150000000>; + supports-sdio; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdio_pwrseq { + reset-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>; +}; + +&spdif_8ch { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spdifm1_tx>; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn>; +}; + +&vcc3v3_lcd0_n { + gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; + +&vcc3v3_lcd1_n { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + enable-active-high; +}; +&wireless_wlan { + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_irq>; + WIFI,host_wake-gpios = <&gpio2 RK_PB2 GPIO_ACTIVE_HIGH>; +}; + +&work_led { + gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>; +}; + +&wireless_bluetooth { + compatible = "bluetooth-platdata"; + clocks = <&rk809 1>; + clock-names = "ext_clock"; + //wifi-bt-power-toggle; + uart_rts-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart1m0_rtsn>; + pinctrl-1 = <&uart1_gpios>; + BT,reset-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>; + BT,wake-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + BT,wake_host-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3566pro.dtsi b/arch/arm64/boot/dts/rockchip/rk3566pro.dtsi new file mode 100644 index 000000000000..f51ff6197678 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3566pro.dtsi @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rk356x.dtsi" + +/ { + compatible = "rockchip,rk3566pro", "rockchip,rk3566"; +}; + +&pipegrf { + compatible = "rockchip,rk3566-pipe-grf", "syscon"; +}; + +&power { + power-domain@RK3568_PD_PIPE { + reg = ; + clocks = <&cru PCLK_PIPE>; + pm_qos = <&qos_pcie2x1>, + <&qos_sata1>, + <&qos_sata2>, + <&qos_usb3_0>, + <&qos_usb3_1>; + #power-domain-cells = <0>; + }; +}; + +&rkisp { + rockchip,iq-feature = /bits/ 64 <0x1BFBF7FE67FF>; +}; + +&usbdrd_dwc3 { + phys = <&u2phy0_otg>; + phy-names = "usb2-phy"; + extcon = <&usb2phy0>; + maximum-speed = "high-speed"; + snps,dis_u2_susphy_quirk; + snps,usb2-lpm-disable; +}; + +/delete-node/ &route_edp; +/delete-node/ &vp0_out_edp; +/delete-node/ &vp1_out_edp; +/delete-node/ &edp; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts index 93b3082315da..ceb7191ec0ac 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts @@ -15,6 +15,13 @@ goodix,irq-gpio = <&gpio0 RK_PA4 IRQ_TYPE_LEVEL_LOW>; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd0_n>; + reset-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts index 672a92e58fc5..617723eb0c3d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts @@ -12,6 +12,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts index 6fb57aa5aaef..2550c72e6081 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts @@ -16,6 +16,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts index 8623a53f1f75..ec9deefa68ec 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts @@ -12,6 +12,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts index f0c391a82ff4..7ba8b7e342dc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts @@ -16,6 +16,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts index 93bed18b809e..9c17e6b83a6a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts @@ -46,6 +46,13 @@ goodix,irq-gpio = <&gpio0 RK_PA4 IRQ_TYPE_LEVEL_LOW>; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd0_n>; + reset-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts index 42fa4a5ffd91..33e95593bfa8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts @@ -47,6 +47,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts index 16d185cb7ad6..2678e89d812f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts @@ -15,6 +15,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { assigned-clocks = <&pmucru CLK_WIFI>; assigned-clock-rates = <24000000>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts index bb24a93a3e82..5e0699d21460 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts @@ -47,6 +47,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts index be6c3984dc46..92ae266f5cab 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts @@ -48,6 +48,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2_rk628 { panel-backlight = <&backlight>; panel-power-supply = <&vcc3v3_lcd0_n>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi index 8c66b7cdd253..d485546b0866 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi @@ -396,6 +396,7 @@ reset-delay-ms = <60>; enable-delay-ms = <60>; prepare-delay-ms = <60>; + init-delay-ms = <10>; unprepare-delay-ms = <60>; disable-delay-ms = <60>; width-mm = <68>; @@ -730,6 +731,7 @@ reset-delay-ms = <60>; enable-delay-ms = <60>; prepare-delay-ms = <60>; + init-delay-ms = <10>; unprepare-delay-ms = <60>; disable-delay-ms = <60>; width-mm = <68>; @@ -1378,6 +1380,24 @@ goodix,rst-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio0 RK_PB5 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c5 { @@ -1494,6 +1514,22 @@ <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; sdio-pwrseq { diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi index 71ef9923fd5b..eb7a0f11be19 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-ddr4-v10.dtsi @@ -263,6 +263,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c4 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb2-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb2-lp4x-v10.dtsi index 6014c202902a..52eca29e3cb5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb2-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb2-lp4x-v10.dtsi @@ -211,6 +211,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c3 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb5-ddr4-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb5-ddr4-v10.dtsi index b6489df63ad6..24f8a056adf4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb5-ddr4-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb5-ddr4-v10.dtsi @@ -264,6 +264,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c3 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb6-ddr3-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-evb6-ddr3-v10.dtsi index 7cb503247058..3e4ab34912c5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb6-ddr3-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb6-ddr3-v10.dtsi @@ -111,6 +111,10 @@ power-supply = <&vcc3v3_lcd0_n>; }; +&hynitron { + power-supply = <&vcc3v3_lcd0_n>; +}; + &i2c2 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-toybrick-sd0-mipi-tx0.dtsi b/arch/arm64/boot/dts/rockchip/rk3568-toybrick-sd0-mipi-tx0.dtsi index 7dbcf6439898..f4e5f89ca58f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-toybrick-sd0-mipi-tx0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568-toybrick-sd0-mipi-tx0.dtsi @@ -45,6 +45,25 @@ goodix,rst-gpio = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio4 RK_PC2 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + status = "okay"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio4 RK_PC3 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &pwm14{ @@ -72,5 +91,21 @@ <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>, <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10-camera.dtsi b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10-camera.dtsi index 199c55ce54bf..f1d7201b5568 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10-camera.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10-camera.dtsi @@ -44,6 +44,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &combphy0_us { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10.dtsi index 78cb019fe9be..17f5a7a21e2b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-evb-lp4x-v10.dtsi @@ -49,6 +49,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c0 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-v1-evb-lp4x-v10.dtsi b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-v1-evb-lp4x-v10.dtsi index 5e2b2f976ae8..cef8cc061679 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568m-serdes-v1-evb-lp4x-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3568m-serdes-v1-evb-lp4x-v10.dtsi @@ -49,6 +49,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c0 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi index 27f5e6e97990..98e821597a54 100644 --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi @@ -220,8 +220,10 @@ cpuinfo { compatible = "rockchip,cpuinfo"; - nvmem-cells = <&otp_id>, <&otp_cpu_version>, <&cpu_code>; - nvmem-cell-names = "id", "cpu-version", "cpu-code"; + nvmem-cells = <&otp_id>, <&otp_cpu_version>, <&cpu_code>, + <&specification_serial_number>, <&remark_spec_serial_number>; + nvmem-cell-names = "id", "cpu-version", "cpu-code", + "specification_serial_number", "remark_spec_serial_number"; }; display_subsystem: display-subsystem { diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-evb.dtsi index 6ebe308941aa..4f1e40575025 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb.dtsi @@ -270,6 +270,7 @@ reset-delay-ms = <10>; enable-delay-ms = <10>; prepare-delay-ms = <10>; + init-delay-ms = <10>; unprepare-delay-ms = <10>; disable-delay-ms = <60>; width-mm = <68>; @@ -627,6 +628,25 @@ goodix,rst-gpio = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio0 RK_PC5 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + status = "disabled"; + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c2 { @@ -683,6 +703,22 @@ <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; wireless-bluetooth { diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-dv.dts b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-dv.dts index c64a5fefe615..d10fd17bbbb6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-dv.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1-v10-dv.dts @@ -163,6 +163,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c2 { status = "okay"; /delete-node/ husb311@4e; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb1.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-evb1.dtsi index c3f2fb9f2adc..864d5044564d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-evb1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb1.dtsi @@ -312,6 +312,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c2 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-evb2.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-evb2.dtsi index 1b73b3465081..f7996f95cc48 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-evb2.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-evb2.dtsi @@ -10,6 +10,7 @@ /delete-node/ &leds; /delete-node/ >1x; +/delete-node/ &hynitron; / { es8388_sound: es8388-sound { @@ -570,4 +571,3 @@ wifi_chip_type = "ap6398s"; status = "okay"; }; - diff --git a/arch/arm64/boot/dts/rockchip/rk3576-industry-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-industry-evb.dtsi index 2e6edb9d86ca..f0a8d28978f5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-industry-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-industry-evb.dtsi @@ -131,6 +131,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c3 { status = "okay"; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-industry.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-industry.dtsi index 618f6225420e..f4d362dc66dc 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-industry.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-industry.dtsi @@ -585,6 +585,25 @@ goodix,rst-gpio = <&gpio2 RK_PA5 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio2 RK_PA4 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + status = "disabled"; + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &iep { @@ -632,6 +651,22 @@ <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>, <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-iotest.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-iotest.dtsi index 8a068c93e58f..b79d66911393 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-iotest.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-iotest.dtsi @@ -64,7 +64,7 @@ regulator-name = "vcc3v3_lcd0_n"; regulator-boot-on; enable-active-high; - gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; + gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>; vin-supply = <&vcc_3v3_s0>; }; @@ -128,6 +128,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &route_hdmi { status = "disabled"; connect = <&vp0_out_hdmi>; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi index 8bce5e14d03b..a5b4dcb02218 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-pinctrl.dtsi @@ -5482,7 +5482,7 @@ pmic_pins: pmic-pins { rockchip,pins = /* pmic_int */ - <0 RK_PA6 9 &pcfg_pull_up>, + <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, /* pmic_sleep */ <0 RK_PA4 9 &pcfg_pull_none>; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-test1.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-test1.dtsi index 7fe5cf36f11b..bf3b58281e70 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-test1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-test1.dtsi @@ -281,6 +281,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c0 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-test2-cam-dcphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-test2-cam-dcphy0.dtsi new file mode 100644 index 000000000000..e9ba8dbc2f7c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-test2-cam-dcphy0.dtsi @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_ucam5: endpoint@6 { + reg = <6>; + remote-endpoint = <&ov50c40_out>; + data-lanes = <1 2 3>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c8 { + status = "okay"; + pinctrl-0 = <&i2c8m3_xfer>; + + aw8601: aw8601@c { + compatible = "awinic,aw8601"; + status = "okay"; + reg = <0x0c>; + rockchip,vcm-start-current = <56>; + rockchip,vcm-rated-current = <96>; + rockchip,vcm-step-mode = <4>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + }; + + ov50c40: ov50c40@36 { + compatible = "ovti,ov50c40"; + status = "okay"; + reg = <0x36>; + clocks = <&cru CLK_MIPI_CAMERAOUT_M0>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0m0_clk0>; + power-domains = <&power RK3576_PD_VI>; + avdd-supply = <&vcc_mipicsi0>; + reset-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "HZGA06"; + rockchip,camera-module-lens-name = "ZE0082C1"; + eeprom-ctrl = <&otp_eeprom>; + lens-focus = <&aw8601>; + port { + ov50c40_out: endpoint { + remote-endpoint = <&mipi_in_ucam5>; + bus-type = <1>; + data-lanes = <1 2 3>; + }; + }; + }; + + otp_eeprom: otp_eeprom@50 { + compatible = "rk,otp_eeprom"; + status = "okay"; + reg = <0x50>; + }; +}; + +&mipidcphy0 { + status = "okay"; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "okay"; + + port { + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp_vir0>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; + +&rkisp_vir0_sditf { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-test2-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-test2-v10.dts index 10b438f95a7d..2cb25e930114 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-test2-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3576-test2-v10.dts @@ -9,6 +9,7 @@ #include "rk3576.dtsi" #include "rk3576-test2.dtsi" #include "rk3576-android.dtsi" +#include "rk3576-test2-cam-dcphy0.dtsi" / { model = "Rockchip RK3576 TEST2 V10 Board"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-test2.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-test2.dtsi index acfc8de07199..2edbdeb1b327 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-test2.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-test2.dtsi @@ -154,6 +154,16 @@ pinctrl-names = "default"; pinctrl-0 = <&usb_otg0_pwren>; }; + + vcc_mipicsi0: vcc-mipicsi0-regulator { + compatible = "regulator-fixed"; + gpio = <&gpio3 RK_PB6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipicsi0_pwr>; + regulator-name = "vcc_mipicsi0"; + enable-active-high; + regulator-boot-on; + }; }; &backlight { @@ -806,6 +816,14 @@ }; &pinctrl { + cam { + mipicsi0_pwr: mipicsi0-pwr { + rockchip,pins = + /* camera power en */ + <3 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + lcd { lcd_rst_gpio: lcd-rst-gpio { rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-test5.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-test5.dtsi index 90cff8fd1a25..75e6b0b9bf14 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-test5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-test5.dtsi @@ -163,6 +163,11 @@ power-supply = <&vcc3v3_lcd_n>; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c2 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dcphy0.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dcphy0.dtsi new file mode 100644 index 000000000000..f1e4b25a20c9 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dcphy0.dtsi @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_ucam0: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx415_out0>; + data-lanes = <1 2 3 4>; + }; + + mipi_in_ucam1: endpoint@2 { + reg = <2>; + remote-endpoint = <&ov50c40_out0>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c9 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c9m2_xfer>; + + imx415_dcphy0: imx415@1a { + compatible = "sony,imx415"; + reg = <0x1a>; + clocks = <&cru CLK_MIPI_CAMERAOUT_M0>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0m1_clk0>; + power-domains = <&power RK3576_PD_VI>; + power-gpios = <&gpio2 RK_PD0 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2022-PX1"; + rockchip,camera-module-lens-name = "IR0147-50IRC-8M-F20"; + port { + imx415_out0: endpoint { + remote-endpoint = <&mipi_in_ucam0>; + data-lanes = <1 2 3 4>; + }; + }; + }; + + aw8601_0: aw8601@c { + compatible = "awinic,aw8601"; + status = "okay"; + reg = <0x0c>; + rockchip,vcm-start-current = <56>; + rockchip,vcm-rated-current = <96>; + rockchip,vcm-step-mode = <4>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + }; + + otp_eeprom_0: otp_eeprom@50 { + compatible = "rk,otp_eeprom"; + status = "okay"; + reg = <0x50>; + }; + + ov50c40_dcph0: ov50c40@36 { + compatible = "ovti,ov50c40"; + reg = <0x36>; + clocks = <&cru CLK_MIPI_CAMERAOUT_M0>; + clock-names = "xvclk"; + power-domains = <&power RK3576_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0m1_clk0>; + pwdn-gpios = <&gpio2 RK_PD0 GPIO_ACTIVE_LOW>;// must be high at last + reset-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_LOW>;// must be high at last + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "HZGA06"; + rockchip,camera-module-lens-name = "ZE0082C1-RK3568"; + eeprom-ctrl = <&otp_eeprom_0>; + lens-focus = <&aw8601_0>; + port { + ov50c40_out0: endpoint { + remote-endpoint = <&mipi_in_ucam1>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "okay"; + + port { + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp_vir0>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; + +&rkisp_vir0_sditf { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dphy3.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dphy3.dtsi new file mode 100644 index 000000000000..031c6e160f44 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-cam-dphy3.dtsi @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy1_hw { + status = "okay"; +}; + +&csi2_dphy3 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_ucam30: endpoint@1 { + reg = <1>; + remote-endpoint = <&imx415_out1>; + data-lanes = <1 2 3 4>; + }; + + mipi_in_ucam31: endpoint@2 { + reg = <2>; + remote-endpoint = <&ov50c40_out1>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy3_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi3_csi2_input>; + }; + }; + }; +}; + +&i2c6 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c6m1_xfer>; + + imx415_dphy3: imx415@1a { + compatible = "sony,imx415"; + reg = <0x1a>; + clocks = <&cru CLK_MIPI_CAMERAOUT_M2>; + clock-names = "xvclk"; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk2m1_clk2>; + power-domains = <&power RK3576_PD_VI>; + power-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_LOW>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2022-PX1"; + rockchip,camera-module-lens-name = "IR0147-50IRC-8M-F20"; + port { + imx415_out1: endpoint { + remote-endpoint = <&mipi_in_ucam30>; + data-lanes = <1 2 3 4>; + }; + }; + }; + + aw8601_1: aw8601@c { + compatible = "awinic,aw8601"; + status = "okay"; + reg = <0x0c>; + rockchip,vcm-start-current = <56>; + rockchip,vcm-rated-current = <96>; + rockchip,vcm-step-mode = <4>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + }; + + otp_eeprom_1: otp_eeprom@50 { + compatible = "rk,otp_eeprom"; + status = "okay"; + reg = <0x50>; + }; + + ov50c40_dphy3: ov50c40@36 { + compatible = "ovti,ov50c40"; + reg = <0x36>; + clocks = <&cru CLK_MIPI_CAMERAOUT_M2>; + clock-names = "xvclk"; + power-domains = <&power RK3576_PD_VI>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk2m1_clk2>; + pwdn-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_LOW>;// must be high at last + reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_LOW>;// must be high at last + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "HZGA06"; + rockchip,camera-module-lens-name = "ZE0082C1-RK3568"; + eeprom-ctrl = <&otp_eeprom_1>; + lens-focus = <&aw8601_1>; + port { + ov50c40_out1: endpoint { + remote-endpoint = <&mipi_in_ucam31>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&mipi3_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy3_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi3_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi3_in>; + }; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds3 { + status = "okay"; + + port { + cif_mipi3_in: endpoint { + remote-endpoint = <&mipi3_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds3_sditf { + status = "okay"; + + port { + mipi_lvds3_sditf: endpoint { + remote-endpoint = <&isp_vir1>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir1 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir1: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds3_sditf>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-toybrick-d0-linux.dts b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-d0-linux.dts new file mode 100644 index 000000000000..7f2586307fd6 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-toybrick-d0-linux.dts @@ -0,0 +1,1480 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2024 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include +#include +#include "rk3576.dtsi" +#include "rk3576-linux.dtsi" +#include "rk3576-pinctrl.dtsi" +#include "rk3576-toybrick-cam-dcphy0.dtsi" +#include "rk3576-toybrick-cam-dphy3.dtsi" + +/ { + model = "Rockchip RK3576 TOYBRICK D0 Board"; + compatible = "rockchip,rk3576-toybrick-d0", "rockchip,rk3576"; + + reserved_memory: reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + vendor_storage_rm: vendor-storage-rm@00000000 { + compatible = "rockchip,vendor-storage-rm"; + reg = <0x0 0x0 0x0 0x0>; + }; + }; + vendor_storage: vendor-storage { + compatible = "rockchip,ram-vendor-storage"; + memory-region = <&vendor_storage_rm>; + status = "okay"; + }; + backlight: backlight { + compatible = "pwm-backlight"; + pwms = <&pwm1_6ch_1 0 25000 0>; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + fan1 { + compatible = "pwm-fan"; + pwms = <&pwm1_6ch_4 0 40000 0>; + cooling-levels = <0 80 170 255>; + }; + + // leds: gpio-leds { + // compatible = "gpio-leds"; + // pinctrl-names = "default"; + // pinctrl-0 =<&leds_gpio>; + + // led@1 { + // gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; + // label = "heartbeat"; + // linux,default-trigger = "heartbeat"; + // }; + // }; + + leds: leds { + compatible = "gpio-leds"; + work_led: work { + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; + label = "heartbeat"; + linux,default-trigger = "heartbeat"; + }; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&hym8563>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_poweren_gpio>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + post-power-on-delay-ms = <200>; + reset-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>; + }; + + vbus_typec_power: vbus-typec-power { + compatible = "regulator-fixed"; + regulator-name = "vbus_typec_power"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + vcc_5v0_sys_s5: vcc-5v0-sys-s5 { + compatible = "regulator-fixed"; + regulator-name = "vcc_5v0_sys_s5"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vbus_typec_power>; + }; + + vcc_2v0_pldo_s3: vcc-2v0-pldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_2v0_pldo_s3"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + vin-supply = <&vcc_5v0_sys_s5>; + }; + + vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vcc_5v0_sys_s5>; + }; + + vcc5v0_usb30_host1: vcc5v0-usb30-host1 { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb30_host1"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc_5v0_sys_s5>; + enable-active-high; + gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&usb_host_pwren>; + }; + + // vcc5v0_usb_otg0: vcc5v0-usb-otg0 { + // compatible = "regulator-fixed"; + // regulator-name = "vcc5v0_usb_otg0"; + // regulator-boot-on; + // regulator-always-on; + // regulator-min-microvolt = <5000000>; + // regulator-max-microvolt = <5000000>; + // vin-supply = <&vcc_5v0_sys_s5>; + // enable-active-high; + // gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>; + // pinctrl-names = "default"; + // pinctrl-0 = <&usb_otg_pwren>; + // }; + + vcc_3v3_sd: vcc-3v3-sd { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sd"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + enable-active-high; + gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&sd_pwren>; + }; + + vcc_3v3_pcie: vcc-3v3-pcie { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_pcie"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_5v0_sys_s5>; + enable-active-high; + gpio = <&gpio2 RK_PC7 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pwren>; + }; + + vcc_3v3_s0: vcc-3v3-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_s0"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc_3v3_s3>; + }; + + vcc3v3_lcd_n: vcc3v3-lcd0-n { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_lcd0_n"; + regulator-boot-on; + enable-active-high; + gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc_3v3_s0>; + }; + + wireless_bluetooth: wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart7m0_rtsn>, <&bt_reset_gpio>, <&bt_host_wake_irq>, <&bt_wake_gpio>; + pinctrl-1 = <&uart7_gpios>; + BT,reset-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; + BT,wake-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; + BT,wake_host-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless_wlan: wireless-wlan { + compatible = "wlan-platdata"; + wifi_chip_type = "ap6275p"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_host_wake_irq>; + WIFI,host_wake-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; + // WIFI,poweren-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_psu { + status = "okay"; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_lit_s0>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_big_s0>; +}; + +&display_subsystem { + clocks = <&hdptxphy_hdmi>; + clock-names = "hdmi0_phy_pll"; +}; + +&dsi { + status = "disabled"; + //rockchip,lane-rate = <1000>; + dsi_panel: panel@0 { + status = "okay"; + compatible = "simple-panel-dsi"; + reg = <0>; + power-supply = <&vcc3v3_lcd_n>; + backlight = <&backlight>; + reset-delay-ms = <10>; + enable-delay-ms = <10>; + prepare-delay-ms = <10>; + unprepare-delay-ms = <10>; + disable-delay-ms = <60>; + width-mm = <68>; + height-mm = <121>; + dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET)>; + dsi,format = ; + dsi,lanes = <4>; + panel-init-sequence = [ + 23 00 02 FE 21 + 23 00 02 04 00 + 23 00 02 00 64 + 23 00 02 2A 00 + 23 00 02 26 64 + 23 00 02 54 00 + 23 00 02 50 64 + 23 00 02 7B 00 + 23 00 02 77 64 + 23 00 02 A2 00 + 23 00 02 9D 64 + 23 00 02 C9 00 + 23 00 02 C5 64 + 23 00 02 01 71 + 23 00 02 27 71 + 23 00 02 51 71 + 23 00 02 78 71 + 23 00 02 9E 71 + 23 00 02 C6 71 + 23 00 02 02 89 + 23 00 02 28 89 + 23 00 02 52 89 + 23 00 02 79 89 + 23 00 02 9F 89 + 23 00 02 C7 89 + 23 00 02 03 9E + 23 00 02 29 9E + 23 00 02 53 9E + 23 00 02 7A 9E + 23 00 02 A0 9E + 23 00 02 C8 9E + 23 00 02 09 00 + 23 00 02 05 B0 + 23 00 02 31 00 + 23 00 02 2B B0 + 23 00 02 5A 00 + 23 00 02 55 B0 + 23 00 02 80 00 + 23 00 02 7C B0 + 23 00 02 A7 00 + 23 00 02 A3 B0 + 23 00 02 CE 00 + 23 00 02 CA B0 + 23 00 02 06 C0 + 23 00 02 2D C0 + 23 00 02 56 C0 + 23 00 02 7D C0 + 23 00 02 A4 C0 + 23 00 02 CB C0 + 23 00 02 07 CF + 23 00 02 2F CF + 23 00 02 58 CF + 23 00 02 7E CF + 23 00 02 A5 CF + 23 00 02 CC CF + 23 00 02 08 DD + 23 00 02 30 DD + 23 00 02 59 DD + 23 00 02 7F DD + 23 00 02 A6 DD + 23 00 02 CD DD + 23 00 02 0E 15 + 23 00 02 0A E9 + 23 00 02 36 15 + 23 00 02 32 E9 + 23 00 02 5F 15 + 23 00 02 5B E9 + 23 00 02 85 15 + 23 00 02 81 E9 + 23 00 02 AD 15 + 23 00 02 A9 E9 + 23 00 02 D3 15 + 23 00 02 CF E9 + 23 00 02 0B 14 + 23 00 02 33 14 + 23 00 02 5C 14 + 23 00 02 82 14 + 23 00 02 AA 14 + 23 00 02 D0 14 + 23 00 02 0C 36 + 23 00 02 34 36 + 23 00 02 5D 36 + 23 00 02 83 36 + 23 00 02 AB 36 + 23 00 02 D1 36 + 23 00 02 0D 6B + 23 00 02 35 6B + 23 00 02 5E 6B + 23 00 02 84 6B + 23 00 02 AC 6B + 23 00 02 D2 6B + 23 00 02 13 5A + 23 00 02 0F 94 + 23 00 02 3B 5A + 23 00 02 37 94 + 23 00 02 64 5A + 23 00 02 60 94 + 23 00 02 8A 5A + 23 00 02 86 94 + 23 00 02 B2 5A + 23 00 02 AE 94 + 23 00 02 D8 5A + 23 00 02 D4 94 + 23 00 02 10 D1 + 23 00 02 38 D1 + 23 00 02 61 D1 + 23 00 02 87 D1 + 23 00 02 AF D1 + 23 00 02 D5 D1 + 23 00 02 11 04 + 23 00 02 39 04 + 23 00 02 62 04 + 23 00 02 88 04 + 23 00 02 B0 04 + 23 00 02 D6 04 + 23 00 02 12 05 + 23 00 02 3A 05 + 23 00 02 63 05 + 23 00 02 89 05 + 23 00 02 B1 05 + 23 00 02 D7 05 + 23 00 02 18 AA + 23 00 02 14 36 + 23 00 02 42 AA + 23 00 02 3D 36 + 23 00 02 69 AA + 23 00 02 65 36 + 23 00 02 8F AA + 23 00 02 8B 36 + 23 00 02 B7 AA + 23 00 02 B3 36 + 23 00 02 DD AA + 23 00 02 D9 36 + 23 00 02 15 74 + 23 00 02 3F 74 + 23 00 02 66 74 + 23 00 02 8C 74 + 23 00 02 B4 74 + 23 00 02 DA 74 + 23 00 02 16 9F + 23 00 02 40 9F + 23 00 02 67 9F + 23 00 02 8D 9F + 23 00 02 B5 9F + 23 00 02 DB 9F + 23 00 02 17 DC + 23 00 02 41 DC + 23 00 02 68 DC + 23 00 02 8E DC + 23 00 02 B6 DC + 23 00 02 DC DC + 23 00 02 1D FF + 23 00 02 19 03 + 23 00 02 47 FF + 23 00 02 43 03 + 23 00 02 6E FF + 23 00 02 6A 03 + 23 00 02 94 FF + 23 00 02 90 03 + 23 00 02 BC FF + 23 00 02 B8 03 + 23 00 02 E2 FF + 23 00 02 DE 03 + 23 00 02 1A 35 + 23 00 02 44 35 + 23 00 02 6B 35 + 23 00 02 91 35 + 23 00 02 B9 35 + 23 00 02 DF 35 + 23 00 02 1B 45 + 23 00 02 45 45 + 23 00 02 6C 45 + 23 00 02 92 45 + 23 00 02 BA 45 + 23 00 02 E0 45 + 23 00 02 1C 55 + 23 00 02 46 55 + 23 00 02 6D 55 + 23 00 02 93 55 + 23 00 02 BB 55 + 23 00 02 E1 55 + 23 00 02 22 FF + 23 00 02 1E 68 + 23 00 02 4C FF + 23 00 02 48 68 + 23 00 02 73 FF + 23 00 02 6F 68 + 23 00 02 99 FF + 23 00 02 95 68 + 23 00 02 C1 FF + 23 00 02 BD 68 + 23 00 02 E7 FF + 23 00 02 E3 68 + 23 00 02 1F 7E + 23 00 02 49 7E + 23 00 02 70 7E + 23 00 02 96 7E + 23 00 02 BE 7E + 23 00 02 E4 7E + 23 00 02 20 97 + 23 00 02 4A 97 + 23 00 02 71 97 + 23 00 02 97 97 + 23 00 02 BF 97 + 23 00 02 E5 97 + 23 00 02 21 B5 + 23 00 02 4B B5 + 23 00 02 72 B5 + 23 00 02 98 B5 + 23 00 02 C0 B5 + 23 00 02 E6 B5 + 23 00 02 25 F0 + 23 00 02 23 E8 + 23 00 02 4F F0 + 23 00 02 4D E8 + 23 00 02 76 F0 + 23 00 02 74 E8 + 23 00 02 9C F0 + 23 00 02 9A E8 + 23 00 02 C4 F0 + 23 00 02 C2 E8 + 23 00 02 EA F0 + 23 00 02 E8 E8 + 23 00 02 24 FF + 23 00 02 4E FF + 23 00 02 75 FF + 23 00 02 9B FF + 23 00 02 C3 FF + 23 00 02 E9 FF + 23 00 02 FE 3D + 23 00 02 00 04 + 23 00 02 FE 23 + 23 00 02 08 82 + 23 00 02 0A 00 + 23 00 02 0B 00 + 23 00 02 0C 01 + 23 00 02 16 00 + 23 00 02 18 02 + 23 00 02 1B 04 + 23 00 02 19 04 + 23 00 02 1C 81 + 23 00 02 1F 00 + 23 00 02 20 03 + 23 00 02 23 04 + 23 00 02 21 01 + 23 00 02 54 63 + 23 00 02 55 54 + 23 00 02 6E 45 + 23 00 02 6D 36 + 23 00 02 FE 3D + 23 00 02 55 78 + 23 00 02 FE 20 + 23 00 02 26 30 + 23 00 02 FE 3D + 23 00 02 20 71 + 23 00 02 50 8F + 23 00 02 51 8F + 23 00 02 FE 00 + 23 00 02 35 00 + 05 78 01 11 + 05 00 01 29 + ]; + + panel-exit-sequence = [ + 05 00 01 28 + 05 00 01 10 + ]; + + disp_timings0: display-timings { + native-mode = <&dsi_timing0>; + dsi_timing0: timing0 { + clock-frequency = <132000000>; + hactive = <1080>; + vactive = <1920>; + hfront-porch = <15>; + hsync-len = <4>; + hback-porch = <30>; + vfront-porch = <15>; + vsync-len = <2>; + vback-porch = <15>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + panel_in_dsi: endpoint { + remote-endpoint = <&dsi_out_panel>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + dsi_out_panel: endpoint { + remote-endpoint = <&panel_in_dsi>; + }; + }; + }; + +}; + +&dsi_in_vp0 { + status = "disabled"; +}; + +&dsi_in_vp1 { + status = "disabled"; +}; + +&dsi_in_vp2 { + status = "disabled"; +}; + +&dsi_in_vopl { + status = "disabled"; +}; + +&gmac0 { + /* Use rgmii-rxid mode to disable rx delay inside Soc */ + phy-mode = "rgmii-rxid"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + pinctrl-names = "default"; + pinctrl-0 = <ð0m0_miim + ð0m0_tx_bus2 + ð0m0_rx_bus2 + ð0m0_rgmii_clk + ð0m0_rgmii_bus + ðm0_clk0_25m_out>; + + tx_delay = <0x21>; + /* rx_delay = <0x3f>; */ + + phy-handle = <&rgmii_phy0>; + status = "okay"; +}; + +&gmac1 { + /* Use rgmii-rxid mode to disable rx delay inside Soc */ + phy-mode = "rgmii-rxid"; + clock_in_out = "output"; + + snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + /* Reset time is 20ms, 100ms for rtl8211f */ + snps,reset-delays-us = <0 20000 100000>; + + pinctrl-names = "default"; + pinctrl-0 = <ð1m1_miim + ð1m1_tx_bus2 + ð1m1_rx_bus2 + ð1m1_rgmii_clk + ð1m1_rgmii_bus + ðm1_clk1_25m_out>; + + tx_delay = <0x22>; + /* rx_delay = <0x3f>; */ + + phy-handle = <&rgmii_phy1>; + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu_s0>; + status = "okay"; +}; + +&hdmi { + status = "okay"; + enable-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; + rockchip,sda-falling-delay-ns = <360>; +}; + +&hdmi_in_vp0 { + status = "okay"; +}; + +&hdptxphy_hdmi { + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0m1_xfer>; + status = "okay"; + + gt1x: gt1x@14 { + status = "okay"; + compatible = "goodix,gt1x"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio>; + goodix,rst-gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio0 RK_PC5 IRQ_TYPE_LEVEL_LOW>; + power-supply = <&vcc3v3_lcd_n>; + }; + + hynitron: hynitron@5a { + status = "okay"; + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; +}; + +&i2c1 { + status = "okay"; + + rk806: pmic@23 { + compatible = "rockchip,rk806"; + reg = <0x23>; + + interrupt-parent = <&gpio0>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + + pinctrl-names = "default", "pmic-power-off"; + pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; + pinctrl-1 = <&rk806_dvs1_pwrdn>; + + /* 2800mv-3500mv */ + low_voltage_threshold = <3000>; + /* 2700mv-3400mv */ + shutdown_voltage_threshold = <2700>; + /* 140 160 */ + shutdown_temperture_threshold = <160>; + hotdie_temperture_threshold = <115>; + + /* PWRON_ON_TIME: 0:500mS; 1:20mS */ + pwron-on-time-500ms; + + /* 0: restart PMU; + * 1: reset all the power off reset registers, + * forcing the state to switch to ACTIVE mode; + * 2: Reset all the power off reset registers, + * forcing the state to switch to ACTIVE mode, + * and simultaneously pull down the RESETB PIN for 5mS before releasing + */ + pmic-reset-func = <1>; + /* buck5 external feedback resister disable */ + buck5-feedback-disable; + + vcc1-supply = <&vcc_5v0_sys_s5>; + vcc2-supply = <&vcc_5v0_sys_s5>; + vcc3-supply = <&vcc_5v0_sys_s5>; + vcc4-supply = <&vcc_5v0_sys_s5>; + vcc5-supply = <&vcc_5v0_sys_s5>; + vcc6-supply = <&vcc_5v0_sys_s5>; + vcc7-supply = <&vcc_5v0_sys_s5>; + vcc8-supply = <&vcc_5v0_sys_s5>; + vcc9-supply = <&vcc_5v0_sys_s5>; + vcc10-supply = <&vcc_5v0_sys_s5>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc_5v0_sys_s5>; + vcc13-supply = <&vcc_1v1_nldo_s3>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc_5v0_sys_s5>; + + pwrkey { + status = "okay"; + }; + + pinctrl_rk806: pinctrl_rk806 { + gpio-controller; + #gpio-cells = <2>; + + rk806_dvs1_null: rk806_dvs1_null { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs1_slp: rk806_dvs1_slp { + pins = "gpio_pwrctrl1"; + function = "pin_fun1"; + }; + + rk806_dvs1_pwrdn: rk806_dvs1_pwrdn { + pins = "gpio_pwrctrl1"; + function = "pin_fun2"; + }; + + rk806_dvs1_rst: rk806_dvs1_rst { + pins = "gpio_pwrctrl1"; + function = "pin_fun3"; + }; + + rk806_dvs2_null: rk806_dvs2_null { + pins = "gpio_pwrctrl2"; + function = "pin_fun0"; + }; + + rk806_dvs2_slp: rk806_dvs2_slp { + pins = "gpio_pwrctrl2"; + function = "pin_fun1"; + }; + + rk806_dvs2_pwrdn: rk806_dvs2_pwrdn { + pins = "gpio_pwrctrl2"; + function = "pin_fun2"; + }; + + rk806_dvs2_rst: rk806_dvs2_rst { + pins = "gpio_pwrctrl2"; + function = "pin_fun3"; + }; + + rk806_dvs2_dvs: rk806_dvs2_dvs { + pins = "gpio_pwrctrl2"; + function = "pin_fun4"; + }; + + rk806_dvs2_gpio: rk806_dvs2_gpio { + pins = "gpio_pwrctrl2"; + function = "pin_fun5"; + }; + + rk806_dvs3_null: rk806_dvs3_null { + pins = "gpio_pwrctrl3"; + function = "pin_fun0"; + }; + + rk806_dvs3_slp: rk806_dvs3_slp { + pins = "gpio_pwrctrl3"; + function = "pin_fun1"; + }; + + rk806_dvs3_pwrdn: rk806_dvs3_pwrdn { + pins = "gpio_pwrctrl3"; + function = "pin_fun2"; + }; + + rk806_dvs3_rst: rk806_dvs3_rst { + pins = "gpio_pwrctrl3"; + function = "pin_fun3"; + }; + + rk806_dvs3_dvs: rk806_dvs3_dvs { + pins = "gpio_pwrctrl3"; + function = "pin_fun4"; + }; + + rk806_dvs3_gpio: rk806_dvs3_gpio { + pins = "gpio_pwrctrl3"; + function = "pin_fun5"; + }; + }; + + regulators { + vdd_cpu_big_s0: DCDC_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <850000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_big_s0"; + regulator-enable-ramp-delay = <400>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_npu_s0: DCDC_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_lit_s0: DCDC_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <850000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_cpu_lit_s0"; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vcc_3v3_s3: DCDC_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc_3v3_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vdd_gpu_s0: DCDC_REG5 { + regulator-boot-on; + regulator-init-microvolt = <750000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <900000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-enable-ramp-delay = <400>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <850000>; + }; + }; + + vddq_ddr_s0: DCDC_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vddq_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_logic_s0: vdd_log_mem_s0: DCDC_REG7 { + regulator-always-on; + regulator-boot-on; + regulator-init-microvolt = <750000>; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <800000>; + regulator-name = "vdd_logic_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_s3: DCDC_REG8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd2_ddr_s3: DCDC_REG9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vdd_ddr_s0: DCDC_REG10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vdd_ddr_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_1v8_s0: PLDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v8_cam: PLDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcc_1v8_cam"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_1v2_s0: PLDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-name = "vdda_1v2_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca3v3_codec: PLDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcca3v3_codec"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: PLDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vccio_sd_s0"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcca1v8_pldo6_s3: PLDO_REG6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "vcca1v8_pldo6_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: NLDO_REG1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdda_ddr_pll_s0: NLDO_REG2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdda_ddr_pll_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda0v75_hdmi_s0: NLDO_REG3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdda0v75_hdmi_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v85_s0: NLDO_REG4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdda_0v85_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdda_0v75_s0: NLDO_REG5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "vdda_0v75_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&i2c7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c7m2_xfer>; + + hym8563: hym8563@51 { + compatible = "haoyu,hym8563"; + reg = <0x51>; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "hym8563"; + pinctrl-names = "default"; + pinctrl-0 = <&rtc_int>; + + interrupt-parent = <&gpio0>; + interrupts = ; + wakeup-source; + }; +}; + +&iep { + status = "okay"; +}; + +&iep_mmu { + status = "okay"; +}; + +&jpegd { + status = "okay"; +}; + +&jpege { + status = "okay"; +}; + +&jpeg_mmu { + status = "okay"; +}; + +&mdio0 { + rgmii_phy0: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + clocks = <&cru REFCLKO25M_GMAC0_OUT>; + }; +}; + +&mdio1 { + rgmii_phy1: phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + clocks = <&cru REFCLKO25M_GMAC1_OUT>; + }; +}; + +&mipidcphy0 { + status = "okay"; +}; + +&mpp_srv { + status = "okay"; +}; + +&pcie0 { + rockchip,skip-scan-in-resume; + reset-gpios = <&gpio4 RK_PC7 GPIO_ACTIVE_HIGH>; + vpcie3v3-supply = <&vcc_3v3_pcie>; + status = "okay"; +}; + +&pinctrl { + hym8563 { + rtc_int: rtc-int { + rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + gpio-leds { + leds_gpio: leds-gpio { + rockchip,pins = <3 16 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + pcie { + pcie_reset_gpio: pcie-reset-gpio { + rockchip,pins = <4 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>; + }; + pcie_wake_gpio: pcie-wake-gpio { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + pcie_pwren: pcie-pwren { + rockchip,pins = <2 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sd { + sd_pwren: sd-pwren { + rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + touch { + touch_gpio: touch-gpio { + rockchip,pins = + <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>, + <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + usb { + usb_host_pwren: usb-host-pwren { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + // usb_otg_pwren: usb-otg-pwren { + // rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + // }; + }; + + wireless-bluetooth { + uart7_gpios: uart7-gpios { + rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>; + }; + bt_host_wake_irq: bt-host-wake-irq { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + bt_reset_gpio: bt-reset-gpio { + rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + bt_wake_gpio: bt-wake-gpio { + rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + wireless-wlan { + wifi_host_wake_irq: wifi-host-wake-irq { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + wifi_poweren_gpio: wifi-poweren-gpio { + rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm1_6ch_1 { + status = "okay"; + pinctrl-0 = <&pwm1m0_ch1>; +}; + +&pwm1_6ch_4 { + status = "okay"; + pinctrl-0 = <&pwm1m0_ch4>; +}; + +&rga2_core0 { + status = "okay"; +}; + +&rga2_core0_mmu { + status = "okay"; +}; + +&rga2_core1 { + status = "okay"; +}; + +&rga2_core1_mmu { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu_s0>; + status = "okay"; +}; + +&rknpu_mmu { + status = "okay"; +}; + +&rkvenc_ccu { + status = "okay"; +}; + +&rkvenc0 { + status = "okay"; +}; + +&rkvenc0_mmu { + status = "okay"; +}; + +&rkvenc1 { + status = "okay"; +}; + +&rkvenc1_mmu { + status = "okay"; + +}; + +&rkvdec { + status = "okay"; +}; + +&rkvdec_mmu { + status = "okay"; +}; + +&route_dsi { + status = "disabled"; + connect = <&vp1_out_dsi>; +}; + +&route_hdmi { + status = "okay"; + connect = <&vp0_out_hdmi>; +}; + +&sai2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&sai2m1_lrck + &sai2m1_sclk + &sai2m1_sdi + &sai2m1_sdo>; +}; + +&saradc { + status = "okay"; + vref-supply = <&vcca_1v8_s0>; +}; + +&sdhci { + bus-width = <8>; + no-sdio; + no-sd; + non-removable; + max-frequency = <200000000>; + mmc-hs400-1_8v; + mmc-hs400-enhanced-strobe; + full-pwr-cycle-in-suspend; + status = "okay"; +}; + +&sdio { + max-frequency = <150000000>; + no-sd; + no-mmc; + bus-width = <4>; + disable-wp; + cap-sd-highspeed; + cap-sdio-irq; + keep-power-in-suspend; + mmc-pwrseq = <&sdio_pwrseq>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1m1_bus4 &sdmmc1m1_clk &sdmmc1m1_cmd>; + sd-uhs-sdr104; + status = "okay"; +}; + +&sdmmc { + supports-sd; + status = "okay"; +}; + +&rockchip_suspend { + status = "okay"; +}; + +&uart7 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7m0_xfer &uart7m0_ctsn>; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy1 { + status = "okay"; +}; + +&u2phy0_otg { + status = "okay"; +}; + +&u2phy1_otg { + phy-supply = <&vcc5v0_usb30_host1>; + status = "okay"; +}; + +&ufs { + reset-gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&usbdp_phy { + status = "okay"; +}; + +&usbdp_phy_dp { + status = "disabled"; +}; + +&usbdp_phy_u3 { + status = "okay"; +}; + +&usb_drd0_dwc3 { + dr_mode = "peripheral"; + extcon = <&u2phy0>; + status = "okay"; +}; + +&usb_drd1_dwc3 { + dr_mode = "host"; + // extcon = <&u2phy1>; + status = "okay"; +}; + +&vdpp { + status = "okay"; +}; + +&vop { + status = "okay"; + vop-supply = <&vdd_logic_s0>; +}; + +&vop_mmu { + status = "okay"; +}; + +&vp2 { + assigned-clocks = <&cru DCLK_VP2_SRC>; + assigned-clock-parents = <&cru PLL_VPLL>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-ox03c10.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-ox03c10.dtsi new file mode 100644 index 000000000000..54b52de232ec --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-maxim-max96712-dphy0-ox03c10.dtsi @@ -0,0 +1,1037 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ +#include + +/* ox03c10 hdr mode enable */ +#define OX03C10_HDR_ENABLE 0 + +#if (OX03C10_HDR_ENABLE != 0) +/* ox03c10 hdr operating mode */ +#define OX03C10_HDR3_DCG_VS_12BIT 0 +#define OX03C10_HDR3_DCG_SPD_12BIT 1 + +#define OX03C10_HDR_MODE OX03C10_HDR3_DCG_VS_12BIT +#endif /* OX03C10_HDR_ENABLE */ + +/* Multiple raw sensor link to RK ISP: 0 = disable, 1 = enable */ +#define MULTI_RAW_SENSOR_LINK_TO_ISP 1 + +/ { + max96712_dphy0_osc: max96712-dphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dphy0-osc"; + }; + + max96712_dphy0_vcc1v2: max96712-dphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_vcc1v8: max96712-dphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dphy0_pwdn_regulator: max96712-dphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_pwdn"; + gpio = <&gpio2 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dphy0_poc_regulator: max96712-dphy0-poc0-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dphy0_poc"; + gpio = <&i2c7_nca9539_gpio 15 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dphy0_vcc12v_buck1>; + }; +}; + +&csi2_dphy0_hw { + status = "okay"; +}; + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi1_csi2_input>; + }; + }; + }; +}; + +&i2c7 { + max96712_dphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dphy0_errb>, <&max96712_dphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dphy0_vcc1v8>; + pwdn-supply = <&max96712_dphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dphy0_out: endpoint { + remote-endpoint = <&mipi_dphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + +#if (OX03C10_HDR_ENABLE == 0) + bus-format = ; + bpp = <10>; + exp-def = <0x0200>; + hts-def = <0x10fe>; + vts-def = <0x055c>; // 0x02ae * 2 +#else + bus-format = ; + bpp = <12>; + exp-def = <0x0200>; + hts-def = <0x10fe>; + vts-def = <0x055c>; // 0x02ae * 2 +#endif /* OX03C10_HDR_ENABLE */ + sensor-width = <1920>; + sensor-height = <1080>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + +#if MULTI_RAW_SENSOR_LINK_TO_ISP + remote-routing-to-isp = <1>; /* remote camera route to ISP */ +#endif + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT +#if (OX03C10_HDR_ENABLE == 0) + 09 0D 2b 00 00 // SRC0 VC = 0, DT = RAW10 + 09 0E 2b 00 00 // DST0 VC = 0, DT = RAW10 +#else + 09 0D 2c 00 00 // SRC0 VC = 0, DT = RAW12 + 09 0E 2c 00 00 // DST0 VC = 0, DT = RAW12 +#endif /* OX03C10_HDR_ENABLE */ + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT +#if (OX03C10_HDR_ENABLE == 0) + 09 4D 2b 00 00 // SRC0 VC = 0, DT = RAW10 + 09 4E 6b 00 00 // DST0 VC = 1, DT = RAW10 +#else + 09 4D 2c 00 00 // SRC0 VC = 0, DT = RAW12 + 09 4E 6c 00 00 // DST0 VC = 1, DT = RAW12 +#endif /* OX03C10_HDR_ENABLE */ + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT +#if (OX03C10_HDR_ENABLE == 0) + 09 8D 2b 00 00 // SRC0 VC = 0, DT = RAW10 + 09 8E ab 00 00 // DST0 VC = 2, DT = RAW10 +#else + 09 8D 2c 00 00 // SRC0 VC = 0, DT = RAW12 + 09 8E ac 00 00 // DST0 VC = 2, DT = RAW12 +#endif /* OX03C10_HDR_ENABLE */ + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT +#if (OX03C10_HDR_ENABLE == 0) + 09 CD 2b 00 00 // SRC0 VC = 0, DT = RAW10 + 09 CE eb 00 00 // DST0 VC = 3, DT = RAW10 +#else + 09 CD 2c 00 00 // SRC0 VC = 0, DT = RAW12 + 09 CE ec 00 00 // DST0 VC = 3, DT = RAW12 +#endif /* OX03C10_HDR_ENABLE */ + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 05 70 0c 00 00 // PIO06_SLEW = 00: MFP4 Rise and fall time speed setting, 00 is fastest + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 0a // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dphy0_cam0: ox03c10@31 { + compatible = "maxim,ovti,ox03c10"; + reg = <0x31>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + +#if (OX03C10_HDR_ENABLE != 0) + rockchip,camera-hdr-mode = <7>; // HDR_COMPR + + /* hdr operating mode + * 0: OX03C10_HDR3_DCG_VS_12BIT + * 1: OX03C10_HDR3_DCG_SPD_12BIT + */ + hdr-operating-mode = ; // 0 ~ 1 +#endif /* OX03C10_HDR_ENABLE */ + + /* port config start */ + port { + max96712_dphy0_cam0_out: endpoint { +#if MULTI_RAW_SENSOR_LINK_TO_ISP + remote-endpoint = <&mipi_lvds1_sditf_in>; +#endif + + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 05 70 0c 00 00 // PIO06_SLEW = 00: MFP4 Rise and fall time speed setting, 00 is fastest + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 0a // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dphy0_cam1: ox03c10@32 { + compatible = "maxim,ovti,ox03c10"; + reg = <0x32>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + +#if (OX03C10_HDR_ENABLE != 0) + rockchip,camera-hdr-mode = <7>; // HDR_COMPR + + /* hdr operating mode + * 0: OX03C10_HDR3_DCG_VS_12BIT + * 1: OX03C10_HDR3_DCG_SPD_12BIT + */ + hdr-operating-mode = ; // 0 ~ 1 +#endif /* OX03C10_HDR_ENABLE */ + + /* port config start */ + port { + max96712_dphy0_cam1_out: endpoint { +#if MULTI_RAW_SENSOR_LINK_TO_ISP + remote-endpoint = <&mipi_lvds1_sditf_vir1_in>; +#endif + + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 05 70 0c 00 00 // PIO06_SLEW = 00: MFP4 Rise and fall time speed setting, 00 is fastest + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 0a // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dphy0_cam2: ox03c10@33 { + compatible = "maxim,ovti,ox03c10"; + reg = <0x33>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + +#if (OX03C10_HDR_ENABLE != 0) + rockchip,camera-hdr-mode = <7>; // HDR_COMPR + + /* hdr operating mode + * 0: OX03C10_HDR3_DCG_VS_12BIT + * 1: OX03C10_HDR3_DCG_SPD_12BIT + */ + hdr-operating-mode = ; // 0 ~ 1 +#endif /* OX03C10_HDR_ENABLE */ + + /* port config start */ + port { + max96712_dphy0_cam2_out: endpoint { +#if MULTI_RAW_SENSOR_LINK_TO_ISP + remote-endpoint = <&mipi_lvds1_sditf_vir2_in>; +#endif + + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 05 70 0c 00 00 // PIO06_SLEW = 00: MFP4 Rise and fall time speed setting, 00 is fastest + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 0a // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dphy0_cam3: ox03c10@34 { + compatible = "maxim,ovti,ox03c10"; + reg = <0x34>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + +#if (OX03C10_HDR_ENABLE != 0) + rockchip,camera-hdr-mode = <7>; // HDR_COMPR + + /* hdr operating mode + * 0: OX03C10_HDR3_DCG_VS_12BIT + * 1: OX03C10_HDR3_DCG_SPD_12BIT + */ + hdr-operating-mode = ; // 0 ~ 1 +#endif /* OX03C10_HDR_ENABLE */ + + /* port config start */ + port { + max96712_dphy0_cam3_out: endpoint { +#if MULTI_RAW_SENSOR_LINK_TO_ISP + remote-endpoint = <&mipi_lvds1_sditf_vir3_in>; +#endif + + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi1_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi1_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi1_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1 { + status = "okay"; + +#if MULTI_RAW_SENSOR_LINK_TO_ISP + camera-over-bridge; // serdes multi raw camera to isp +#endif + + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi1_in: endpoint { + remote-endpoint = <&mipi1_csi2_output>; + }; + }; +}; + +#if MULTI_RAW_SENSOR_LINK_TO_ISP +&rkcif_mipi_lvds1_sditf { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_cam0_out>; + data-lanes = <1 2 3 4>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf: endpoint@0 { + reg = <0>; + remote-endpoint = <&isp_vir0_in0>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1_sditf_vir1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir1_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_cam1_out>; + data-lanes = <1 2 3 4>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir1: endpoint@0 { + reg = <0>; + remote-endpoint = <&isp_vir1_in0>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1_sditf_vir2 { + address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir2_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_cam2_out>; + data-lanes = <1 2 3 4>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir2: endpoint { + remote-endpoint = <&isp_vir2_in0>; + }; + }; + }; +}; + +&rkcif_mipi_lvds1_sditf_vir3 { + address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir3_in: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dphy0_cam3_out>; + data-lanes = <1 2 3 4>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + mipi_lvds1_sditf_vir3: endpoint { + remote-endpoint = <&isp_vir3_in0>; + }; + }; + }; +}; +#endif /* MULTI_RAW_SENSOR_LINK_TO_ISP */ + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +#if MULTI_RAW_SENSOR_LINK_TO_ISP +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir0_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds1_sditf>; + }; + }; +}; + +&rkisp_vir1 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir1_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds1_sditf_vir1>; + }; + }; +}; + +&rkisp_vir2 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir2_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds1_sditf_vir2>; + }; + }; +}; + +&rkisp_vir3 { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir3_in0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds1_sditf_vir3>; + }; + }; +}; +#endif /* MULTI_RAW_SENSOR_LINK_TO_ISP */ + +&pinctrl { + max96712-dphy0 { + max96712_dphy0_pwdn: max96712-dphy0-pwdn { + rockchip,pins = <2 RK_PA3 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dphy0_errb: max96712-dphy0-errb { + rockchip,pins = <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dphy0_lock: max96712-dphy0-lock { + rockchip,pins = <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-serdes-mfd-display-maxim-2.5k.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-serdes-mfd-display-maxim-2.5k.dtsi new file mode 100644 index 000000000000..9c319d96c39c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20-serdes-mfd-display-maxim-2.5k.dtsi @@ -0,0 +1,1710 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/ { + + dp2lvds_backlight0: dp2lvds_backlight0 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + edp2lvds_backlight0: edp2lvds_backlight0 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; +}; + +&backlight { + pwms = <&pwm1_6ch_1 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl0_enable_pin>; + //enable-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&combphy0_ps { + status = "okay"; +}; + +&combphy1_psu { + status = "okay"; +}; + +&dp { + //split-mode; + force-hpd; + + status = "okay"; +}; + +&dp0 { + status = "okay"; + + ports { + port@1 { + reg = <1>; + + dp_out_i2c5_max96749: endpoint { + remote-endpoint = <&i2c5_max96749_from_dp>; + }; + }; + }; +}; + +&dp0_in_vp0 { + status = "okay"; +}; + +&dp0_in_vp1 { + status = "disabled"; +}; + +&dp0_in_vp2 { + status = "disabled"; +}; + +&dp2lvds_backlight0 { + pwms = <&i2c5_r7f701_pwm 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl2_enable_pin>; + //enable-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +/* + * mipi_dcphy needs to be enabled + * when dsi is enabled + */ +&dsi { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + dsi_out_i2c8_max96789: endpoint { + remote-endpoint = <&i2c8_max96789_from_dsi>; + }; + }; + }; +}; + +&dsi_in_vp0 { + status = "disabled"; +}; + +&dsi_in_vp1 { + status = "okay"; +}; + +&dsi_in_vp2 { + status = "disabled"; +}; + +&edp { + //split-mode; + force-hpd; + status = "disabled"; + + ports { + port@1 { + reg = <1>; + + edp_out_i2c3_max96749: endpoint { + remote-endpoint = <&i2c3_max96749_from_edp>; + }; + }; + }; + +}; + +&edp_in_vp0 { + status = "disabled"; +}; + +&edp_in_vp1 { + status = "disabled"; +}; + +&edp_in_vp2 { + status = "disabled"; +}; + +&edp2lvds_backlight0 { + pwms = <&pwm0_2ch_0 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl4_enable_pin>; + //enable-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + status = "disabled"; +}; + +&hdmi { + status = "disabled"; +}; + + +&hdptxphy { + status = "disabled"; +}; + +&hdptxphy_hdmi { + status = "okay"; +}; + + +&i2c8 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8m2_xfer>; + clock-frequency = <400000>; + + i2c8_max96789: i2c8-max96789@42 { + compatible = "maxim,max96789"; + reg = <0x42>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8_serdes_pins>; + lock-gpios = <&gpio3 RK_PA2 GPIO_ACTIVE_HIGH>; + sel-mipi; + id-serdes-bridge-split = <0x01>; + status = "okay"; + + serdes-init-sequence = [ + //Independent 11_07_17-56 Using MAX96789/91/F (GMSL-1/2) + //Disable Video pipe + 0002 0003 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 008a + //Address Value of I2C SRC_B + 0044 008c + //Address Value of I2C DST_B + 0045 008c + //Set Stream for DSI Port A && assign pipeX + 0053 0010 + //Set Stream for DSI Port B && assign pipeY + 0057 0021 + //Clock Select, X for portA, Y/Z for PortB + 0308 0076 + //Start DSI-A Port + 0311 0001 + //Set Port A Lane Mapping + 0332 004E + //Set Port B Lane Mapping + 0333 00E4 + //Set GMSL type + 0004 00F2 + //Number of Lanes + 0331 0033 + //Set phy_config + 0330 0006 + //Set soft_dtx_en + 031C 0098 + //Set soft_dtx + 0321 0024 + //Set soft_dty_en + 031D 0098 + //Set soft_dty_ + 0322 0024 + //Init Default + 0326 00E4 + //HSYNC_WIDTH_L + 0385 0038 + //VSYNC_WIDTH_L + 0386 0008 + //HSYNC_WIDTH_H/VSYNC_WIDTH_H + 0387 0000 + //VFP_L + 03A5 00C8 + //VBP_H + 03A7 0000 + //VFP_H/VBP_L + 03A6 0020 + //VRES_L + 03A8 00D0 + //VRES_H + 03A9 0002 + //HFP_L + 03AA 0038 + //HBP_H + 03AC 0002 + //HFP_H/HBP_L + 03AB 0000 + //HRES_L + 03AD 0080 + //HRES_H + 03AE 0007 + //Disable FIFO/DESKEW_EN + 03A4 00C0 + //HSYNC_WIDTH_L + 0395 0038 + //VSYNC_WIDTH_L + 0396 0008 + //HSYNC_WIDTH_H/VSYNC_WIDTH_H + 0397 0000 + //VFP_L + 03B1 00C8 + //VBP_H + 03B3 0000 + //VFP_H/VBP_L + 03B2 0020 + //VRES_L + 03B4 00D0 + //VRES_H + 03B5 0002 + //HFP_L + 03B6 0038 + //HBP_H + 03B8 0002 + //HFP_H/HBP_L + 03B7 0000 + //HRES_L + 03B9 0080 + //HRES_H + 03BA 0007 + //Disable FIFO/DESKEW_EN + 03B0 00C0 + //Turn on video pipe + 0002 0033 + //Enable splitter mode reset one shot + 0010 0021 + ffff f000 //0xf000 ms delay + ]; + + i2c8_max96789_pinctrl: i2c8-max96789-pinctrl { + compatible = "maxim,max96789-pinctrl"; + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c8_max96789_pinctrl_pins>; + pinctrl-1 = <&i2c8_max96789_pinctrl_pins>; + status = "okay"; + i2c8_max96789_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96789_I2C"; + function = "MAX96789_I2C"; + }; + lcd-bl-pwm { + pins = "MAX96789_MFP7"; + function = "SER_TXID4_TO_DES"; + }; + tp-int { + pins = "MAX96789_MFP8"; + function = "DES_RXID8_TO_SER"; + }; + lcd-bl-pwm-split { + pins = "MAX96789_MFP16"; + function = "SER_TXID4_TO_DES"; + }; + tp-int-split { + pins = "MAX96789_MFP14"; + function = "DES_RXID14_TO_SER"; + }; + }; + + i2c8_max96789_gpio: i2c8-max96789-gpio { + compatible = "maxim,max96789-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c8_max96789_pinctrl 0 160 20>; + }; + }; + + i2c8_max96789_bridge: i2c8-max96789-bridge { + compatible = "maxim,max96789-bridge"; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + i2c8_max96789_from_dsi: endpoint { + remote-endpoint = <&dsi_out_i2c8_max96789>; + }; + }; + + port@1 { + reg = <1>; + i2c8_max96789_out_i2c8_max96752: endpoint { + remote-endpoint = <&i2c8_max96752_from_i2c8_max96789>; + }; + }; + }; + }; + + }; + + i2c8_max96752: i2c8-max96752@4a { + compatible = "maxim,max96752"; + reg = <0x4a>; + //reg-hw = <0x4a>; + id-serdes-panel-split = <0x01>; + link = <0x01>; + status = "okay"; + + serdes-init-sequence = [ + /*max96752 dual oLDI output*/ + 0002 0043 + 0073 0031 + 007b 0031 + 007d 0038 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 0090 + + 0050 0000 + 01ce 004e + 01ea 0004 + ]; + + i2c8_max96752_pinctrl: i2c8-max96752-pinctrl { + compatible = "maxim,max96752-pinctrl"; + pinctrl-names = "default","init","sleep"; + pinctrl-0 = <&i2c8_max96752_panel_pins>; + pinctrl-1 = <&i2c8_max96752_panel_pins>; + pinctrl-2 = <&i2c8_max96752_panel_sleep_pins>; + status = "okay"; + + i2c8_max96752_panel_pins: panel-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_HIGH"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_HIGH"; + }; + lcd-bias-en { + pins = "MAX96752_GPIO7"; + function = "DES_TXID7_OUTPUT_HIGH"; + }; + lcd-vdd-en { + pins = "MAX96752_GPIO6"; + function = "DES_TXID6_OUTPUT_HIGH"; + }; + tp-int { + pins = "MAX96752_GPIO2"; + function = "DES_TXID8_TO_SER"; + }; + 40ms-delay { + pins = "MAX96752_GPIO15"; + function = "DELAY_40MS"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_HIGH"; + }; + lcd-bl-pwm { + pins = "MAX96752_GPIO4"; + function = "SER_TO_DES_RXID4"; + }; + }; + + i2c8_max96752_panel_sleep_pins: panel-sleep-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_LOW"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_LOW"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_LOW"; + }; + }; + + i2c8_max96752_gpio: i2c8-max96752-gpio { + compatible = "maxim,max96752-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c8_max96752_pinctrl 0 180 15>; + }; + }; + + i2c8_max96752_panel: i2c8-max96752-panel { + compatible = "maxim,max96752-panel"; + status = "okay"; + + backlight = <&backlight>; + panel-size= <346 194>; + + panel-timing { + clock-frequency = <115000000>; + hactive = <1920>; + vactive = <720>; + hfront-porch = <56>; + hsync-len = <32>; + hback-porch = <56>; + vfront-porch = <200>; + vsync-len = <2>; + vback-porch = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + i2c8_max96752_from_i2c8_max96789: endpoint { + remote-endpoint = <&i2c8_max96789_out_i2c8_max96752>; + }; + }; + }; + }; + }; + + + i2c8_himax: i2c8-himax@45 { + compatible = "himax,hxcommon"; + reg = <0x45>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&touch_gpio_dsi>; + pinctrl-1 = <&touch_gpio_dsi>; + himax,location = "himax-touch-dsi"; + himax,irq-gpio = <&gpio3 RK_PA3 IRQ_TYPE_EDGE_FALLING>; + himax,rst-gpio = <&i2c8_max96752_gpio 5 GPIO_ACTIVE_LOW>; + himax,panel-coords = <0 1920 0 720>; + himax,display-coords = <0 1920 0 720>; + status = "okay"; + }; +}; + +&i2c5 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c5m3_xfer>; + clock-frequency = <400000>; + status = "okay"; + + i2c5_max96749: i2c5-max96749@42 { + compatible = "maxim,max96749"; + reg = <0x42>; + dual-link; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_serdes_pins>; + lock-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + //Set TX_STR_SEL_X to 0 + 00A3 0000 + //Set TX_STR_SEL_Y to 1 + 00A7 0001 + //Set TX_STR_SEL_Z to 2 + 00AB 0002 + //Set TX_STR_SEL_U to 3 + 00AF 0003 + + //INFOFR TX_SRC_ID0:1:2 + 00C2 0001 + //CC TX_SRC_ID0:1:2 + 00D2 0002 + //IIC X TX_SRC_ID0:1:2 + 00EA 0001 + //IIC Y TX_SRC_ID0:1:2 + 00F2 0002 + + 00B2 0003 + 00BA 0003 + 00CA 0003 + 00C2 0003 + 00D2 0003 + 00DA 0003 + 00E2 0003 + 00EA 0003 + 00F2 0003 + //Set X_VID_LINK_SEL to 0 + 0100 0061 + //Set Y_VID_LINK_SEL to 1 + 0110 0063 + //Set Z_VID_LINK_SEL to 0 + 0120 0061 + //Set U_VID_LINK_SEL to 1 + 0130 0063 + + //ASYM_WR_B_MUX_Y + 05CE 0037 + //ASYM_WAIT_LINE_FOR_READ_X + 04D1 00F8 + //ASYM_WAIT_LINE_FOR_READ_Y + 05D1 00F8 + //ASYM_VID_EN_W_VS_X + 04CF 00BF + //ASYM_VID_EN_W_VS_Y + 05CF 00BF + //ASYM_FR2FR_CTRL_EN_X + 04D1 00FC + //ASYM_FR2FR_CTRL_EN_Y + 05D1 00FC + //ALT_VTG_EN_X + 04CE 002F + //AUTO_VTG_CFG_X + 04CE 000F + //ALT_VTG_EN_Y + 05CE 0027 + //AUTO_VTG_CFG_Y + 05CE 0007 + //X_M_l + 04C0 0000 + //X_M_m + 04C1 00E1 + //X_M_h + 04C2 004B + //X_N_l + 04C3 00C8 + //X_N_m + 04C4 0008 + //X_N_h + 04C5 0007 + //X_X_OFFSET_l + 04C6 0000 + //X_X_OFFSET_h + 04C7 0000 + //X_X_MAX_l + 04C8 0000 + //X_X_MAX_h + 04C9 000A + //X_Y_MAX_l + 04CA 0040 + //X_Y_MAX_h + 04CB 0006 + //X_vs_dly_l + 04D8 00E0 + //X_vs_dly_m + 04D9 009E + //X_vs_dly_h + 04DA 0049 + //X_vs_high_l + 04DB 00B0 + //X_vs_high_m + 04DC 0022 + //X_vs_high_h + 04DD 0000 + //X_vs_low_l + 04DE 0070 + //X_vs_low_m + 04DF 001F + //X_vs_low_h + 04E0 0002 + //X_hs_dly_l + 04E1 0000 + //X_hs_dly_m + 04E2 0000 + //X_hs_dly_h + 04E3 0000 + //X_hs_high_l + 04E4 0020 + //X_hs_high_h + 04E5 0000 + //X_hs_low_l + 04E6 0070 + //X_hs_low_h + 04E7 000B + //X_hs_cnt_l + 04E8 0090 + //X_hs_cnt_h + 04E9 0006 + //X_hs_llow_l + 04EA 0000 + //X_hs_llow_m + 04EB 0000 + //X_hs_llow_h + 04EC 0000 + //X_de_dly_l + 04ED 0060 + //X_de_dly_m + 04EE 0001 + //X_de_dly_h + 04EF 0000 + //X_de_high_l + 04F0 0000 + //X_de_high_h + 04F1 000A + //X_de_low_l + 04F2 0090 + //X_de_low_h + 04F3 0001 + //X_de_cnt_l + 04F4 0040 + //X_de_cnt_h + 04F5 0006 + //X_de_llow_l + 04F6 00A0 + //X_de_llow_m + 04F7 009B + //X_de_llow_h + 04F8 0003 + //Y_M + 05C0 0000 + //Y_M_h + 05C1 00E1 + //Y_M_h + 05C2 004B + //Y_N_l + 05C3 00C8 + //Y_N_m + 05C4 0008 + //Y_N_h + 05C5 0007 + //Y_X_OFFSET_l + 05C6 0000 + //Y_X_OFFSET_h + 05C7 000A + //Y_X_MAX_l + 05C8 0000 + //Y_X_MAX_h + 05C9 0014 + //Y_Y_MAX_l + 05CA 0040 + //Y_Y_MAX_h + 05CB 0006 + //Y_vs_dly_l + 05D8 00E0 + //Y_vs_dly_m + 05D9 009E + //Y_vs_dly_h + 05DA 0049 + //Y_vs_high_l + 05DB 00B0 + //Y_vs_high_m + 05DC 0022 + //Y_vs_high_h + 05DD 0000 + //Y_vs_low_l + 05DE 0070 + //Y_vs_low_m + 05DF 001F + //Y_vs_low_h + 05E0 0002 + //Y_hs_dly_l + 05E1 0000 + //Y_hs_dly_m + 05E2 0000 + //Y_hs_dly_h + 05E3 0000 + //Y_hs_high_l + 05E4 0020 + //Y_hs_high_h + 05E5 0000 + //Y_hs_low_l + 05E6 0070 + //Y_hs_low_h + 05E7 000B + //Y_hs_cnt_l + 05E8 0090 + //Y_hs_cnt_h + 05E9 0006 + //Y_hs_llow_l + 05EA 0000 + //Y_hs_llow_m + 05EB 0000 + //Y_hs_llow_h + 05EC 0000 + //Y_de_dly_l + 05ED 0060 + //Y_de_dly_m + 05EE 0001 + //Y_de_dly_h + 05EF 0000 + //Y_de_high_l + 05F0 0000 + //Y_de_high_h + 05F1 000A + //Y_de_low_l + 05F2 0090 + //Y_de_low_h + 05F3 0001 + //Y_de_cnt_l + 05F4 0040 + //Y_de_cnt_h + 05F5 0006 + //Y_de_llow_l + 05F6 00A0 + //Y_de_llow_m + 05F7 009B + //Y_de_llow_h + 05F8 0003 + //X_LUT_TEMPLATE_SEL + 04CD 0014 + //Y_LUT_TEMPLATE_SEL + 05CD 0014 + + //Turn off video + 6420 0010 + //Disable MST mode + 7019 0000 + //7019 0001 //Set MST_FUNCTION_ENABLE to 1 + //7904 0001 // Set MST_PAYLOAD_ID_0 to 01 + //7908 0002 // Set MST_PAYLOAD_ID_1 to 01 + //Disable MST_VS0_DTG_ENABLE + 7A14 0000 + //Disable LINK_ENABLE + 7000 0000 + //Reset DPRX core (VIDEO_INPUT_RESET) + 7054 0001 + ffff f000 //delay 0xf000 us + //Set MAX_LINK_RATE to 2.7Gb/s + 7074 000A + //Set MAX_LINK_COUNT to 4 + 7070 0004 + //Set ASYM_CTRL_PROP_GAIN to 000A + 04D0 000A + 05D0 000A + //Set AEQ time to 16ms + 6064 0000 + 6065 0000 + 6164 0000 + 6165 0000 + 6264 0000 + 6265 0000 + 6364 0000 + 6365 0000 + //Enable LINK_ENABLE + 7000 0001 + //delay 1000 + //Disable MSA reset + 7A18 0005 + //Adjust VS0_DMA_HSYNC + 7A28 00FF + 7A2A 00FF + //Adjust VS0_DMA_VSYNC + 7A24 00FF + 7A27 000F + //Enable MST_VS0_DTG_ENABLE + 7A14 0001 + //set EDP Video Control + 6421 0001 + //Turn on video + 6420 0013 + //delay 100 + //Turn off video + 6420 0010 + //delay 100 + //Turn on video + 6420 0013 + 6421 0003 + ]; + + i2c5_max96749_pinctrl: i2c5-max96749-pinctrl { + compatible = "maxim,max96749-pinctrl"; + pinctrl-names = "init", "sleep"; + pinctrl-0 = <&i2c5_max96749_pinctrl_pins>; + pinctrl-1 = <&i2c5_max96749_pinctrl_pins>; + status = "okay"; + + i2c5_max96749_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96749_I2C"; + function = "MAX96749_I2C"; + }; + tp-int { + pins = "MAX96749_MFP1"; + function = "DES_RXID1_TO_SER_LINKA"; + }; + }; + + i2c5_max96749_gpio: i2c5-max96749-gpio { + compatible = "maxim,max96749-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c5_max96749_pinctrl 0 220 25>; + }; + }; + + i2c5_max96749_bridge: i2c5-max96749-bridge { + compatible = "maxim,max96749-bridge"; + status = "okay"; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + i2c5_max96749_from_dp: endpoint { + remote-endpoint = <&dp_out_i2c5_max96749>; + }; + }; + + port@1 { + reg = <1>; + + i2c5_max96749_out_i2c5_max96772: endpoint { + remote-endpoint = <&i2c5_max96772_from_i2c5_max96749>; + }; + }; + }; + }; + + i2c5_max96772: i2c5-max96772@48 { + compatible = "maxim,max96772"; + reg = <0x48>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + + ]; + + i2c5_max96772_pinctrl: i2c5-max96772-pinctrl { + compatible = "maxim,max96772-pinctrl"; + status = "okay"; + + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c5_max96772_panel_pins>; + pinctrl-1 = <&i2c5_max96772_panel_pins>; + + i2c5_max96772_panel_pins: panel-pins { + tp-int { + pins = "MAX96772_GPIO10"; + function = "DES_TXID1_TO_SER"; + }; + }; + + i2c5_max96772_gpio: i2c5-max96772-gpio { + compatible = "maxim,max96772-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c5_max96772_pinctrl 0 250 15>; + }; + }; + + i2c5_max96772_panel: i2c5-max96772-panel { + compatible = "maxim,max96772-panel"; + status = "okay"; + + backlight = <&dp2lvds_backlight0>; + panel-size= <324 202>; + rate-count-ssc= <10 4 0>; + + panel-timing { + clock-frequency = <298400000>; + hactive = <2560>; + vactive = <1600>; + hfront-porch = <48>; + hsync-len = <32>; + hback-porch = <320>; + vfront-porch = <30>; + vsync-len = <3>; + vback-porch = <47>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + port { + i2c5_max96772_from_i2c5_max96749: endpoint { + remote-endpoint = <&i2c5_max96749_out_i2c5_max96772>; + }; + }; + }; + }; + + i2c5_r7f701_pwm: i2c5-r7f701-pwm@77 { + compatible = "r7f701-pwm"; + #pwm-cells = <3>; + reg = <0x77>; + status = "okay"; + }; + + i2c5_cyttsp7: i2c5-cyttsp7@24 { + compatible = "cy,cyttsp7_i2c_adapter"; + reg = <0x24>; + + status = "okay"; + cy,core { + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio_dp>; + cy,irq_gpio = <&gpio4 RK_PA0 GPIO_ACTIVE_HIGH>; + cy,rst_gpio = <&i2c5_max96772_gpio 7 GPIO_ACTIVE_HIGH>; + + cy,max_xfer_len = <0x100>; + + /* CY_CORE_FLAG_WAKE_ON_GESTURE */ + /* cy,flags = <1>; */ + /* CY_CORE_EWG_TAP_TAP | CY_CORE_EWG_TWO_FINGER_SLIDE */ + /* cy,easy_wakeup_gesture = <3>; */ + cy,btn_keys = <172 /* KEY_HOMEPAGE */ + /* previously was KEY_HOME, new Android versions use KEY_HOMEPAGE */ + 139 /* KEY_MENU */ + 158 /* KEY_BACK */ + 217 /* KEY_SEARCH */ + 114 /* KEY_VOLUMEDOWN */ + 115 /* KEY_VOLUMEUP */ + 212 /* KEY_CAMERA */ + 116>; /* KEY_POWER */ + cy,btn_keys-tag = <0>; + + cy,mt { + cy,inp_dev_name = "cyttsp7-mt-dp"; + /* CY_MT_FLAG_FLIP | CY_MT_FLAG_INV_X | CY_MT_FLAG_INV_Y */ + cy,flags = <0x20>; + cy,abs = + /* ABS_MT_POSITION_X, CY_ABS_MIN_X, CY_ABS_MAX_X, 0, 0 */ + < + 0x35 0 2560 0 0 + /* ABS_MT_POSITION_Y, CY_ABS_MIN_Y, CY_ABS_MAX_Y, 0, 0 */ + 0x36 0 1600 0 0 + /* ABS_MT_PRESSURE, CY_ABS_MIN_P, CY_ABS_MAX_P, 0, 0 */ + 0x3a 0 255 0 0 + /* CY_IGNORE_VALUE, CY_ABS_MIN_W, CY_ABS_MAX_W, 0, 0 */ + 0xffff 0 255 0 0 + /* ABS_MT_TRACKING_ID, CY_ABS_MIN_T, CY_ABS_MAX_T, 0, 0 */ + 0x39 0 15 0 0 + /* ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0 */ + 0x30 0 255 0 0 + /* ABS_MT_TOUCH_MINOR, 0, 255, 0, 0 */ + 0x31 0 255 0 0 + /* ABS_MT_ORIENTATION, -127, 127, 0, 0 */ + 0x34 0xffffff81 127 0 0 + /* ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0 */ + 0x37 0 1 0 0 + /* ABS_DISTANCE, 0, 255, 0, 0 */ + 0x19 0 255 0 0 + /* SRI:ABS_MT_DISTANCE, 0,MAX, 0, 0 */ + 0x3b 0 255 0 0>; + + cy,vkeys_x = <2560>; + cy,vkeys_y = <1600>; + + cy,virtual_keys = /* KeyCode CenterX CenterY Width Height */ + /* KEY_BACK */ + <158 1360 90 160 180 + /* KEY_MENU */ + 139 1360 270 160 180 + /* KEY_HOMEPAGE */ + 172 1360 450 160 180 + /* KEY SEARCH */ + 217 1360 630 160 180>; + }; + + cy,btn { + cy,inp_dev_name = "cyttsp7-btn-dp"; + }; + + cy,proximity { + cy,inp_dev_name = "cyttsp7-proximity-dp"; + cy,abs = + /* ABS_DISTANCE, CY_PROXIMITY_MIN_VAL, CY_PROXIMITY_MAX_VAL, 0, 0 */ + <0x19 0 1 0 0>; + }; + }; + }; +}; + +&i2c3 { + pinctrl-0 = <&i2c3m0_xfer>; + clock-frequency = <400000>; + status = "okay"; + + i2c3_max96749: i2c3-max96749@42 { + compatible = "maxim,max96749"; + reg = <0x42>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_serdes_pins>; + lock-gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + id-serdes-bridge-split = <0x02>; + status = "disabled"; + + serdes-init-sequence = [ + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 008a + //Address Value of I2C SRC_B + 0044 008c + //Address Value of I2C DST_B + 0045 008c + //Set TX_STR_SEL_X to 0 + 00A3 0000 + //Set TX_STR_SEL_Y to 1 + 00A7 0001 + //Set TX_STR_SEL_Z to 2 + 00AB 0002 + //Set TX_STR_SEL_U to 3 + 00AF 0003 + + //INFOFR TX_SRC_ID0:1:2 + 00C2 0001 + //CC TX_SRC_ID0:1:2 + 00D2 0002 + //IIC X TX_SRC_ID0:1:2 + 00EA 0001 + //IIC Y TX_SRC_ID0:1:2 + 00F2 0002 + + 00B2 0003 + 00BA 0003 + 00CA 0003 + 00C2 0003 + 00D2 0003 + 00DA 0003 + 00E2 0003 + 00EA 0003 + 00F2 0003 + //Set X_VID_LINK_SEL to 0 + 0100 0061 + //Set Y_VID_LINK_SEL to 1 + 0110 0063 + //Set Z_VID_LINK_SEL to 0 + 0120 0061 + //Set U_VID_LINK_SEL to 1 + 0130 0063 + //ASYM_WR_B_MUX_Y of SER will be written 1 + 05CE 003F + //ASYM_WAIT_LINE_FOR_READ_X of SER will be written 1 + 04D1 00F8 + //ASYM_WAIT_LINE_FOR_READ_Y of SER will be written 1 + 05D1 00F8 + //ASYM_VID_EN_W_VS_X of SER will be written 1 + 04CF 00BF + //ASYM_VID_EN_W_VS_Y of SER will be written 1 + 05CF 00BF + //ASYM_FR2FR_CTRL_EN_X of SER will be written 1 + 04D1 00FC + //ASYM_FR2FR_CTRL_EN_Y of SER will be written 1 + 05D1 00FC + //ALT_VTG_EN_X + 04CE 002F + //AUTO_VTG_CFG_X + 04CE 000F + //ALT_VTG_EN_Y + 05CE 0027 + //AUTO_VTG_CFG_Y + 05CE 0007 + //X_M_l + 04C0 0020 + //X_M_m + 04C1 004A + //X_M_h + 04C2 001D + //X_N_l + 04C3 00C8 + //X_N_m + 04C4 0008 + //X_N_h + 04C5 0007 + //X_X_OFFSET_l + 04C6 0000 + //X_X_OFFSET_h + 04C7 0000 + //X_X_MAX_l + 04C8 0080 + //X_X_MAX_h + 04C9 0007 + //X_Y_MAX_l + 04CA 00D0 + //X_Y_MAX_h + 04CB 0002 + //Y_M + 05C0 0020 + //Y_M_h + 05C1 004A + //Y_M_h + 05C2 001D + //Y_N_l + 05C3 00C8 + //Y_N_m + 05C4 0008 + //Y_N_h + 05C5 0007 + //Y_X_OFFSET_l + 05C6 0080 + //Y_X_OFFSET_h + 05C7 0007 + //Y_X_MAX_l + 05C8 0000 + //Y_X_MAX_h + 05C9 000F + //Y_Y_MAX_l + 05CA 00D0 + //Y_Y_MAX_h + 05CB 0002 + //X_LUT_TEMPLATE_SEL + 04CD 0014 + //X_vs_dly_l + 04D8 0080 + //X_vs_dly_m + 04D9 00F9 + //X_vs_dly_h + 04DA 001C + //X_vs_high_l + 04DB 0080 + //X_vs_high_m + 04DC 0040 + //X_vs_high_h + 04DD 0000 + //X_vs_low_l + 04DE 0020 + //X_vs_low_m + 04DF 0010 + //X_vs_low_h + 04E0 0000 + //X_hs_dly_l + 04E1 0000 + //X_hs_dly_m + 04E2 0000 + //X_hs_dly_h + 04E3 0000 + //X_hs_high_l + 04E4 0038 + //X_hs_high_h + 04E5 0000 + //X_hs_low_l + 04E6 00D8 + //X_hs_low_h + 04E7 0007 + //X_hs_cnt_l + 04E8 00A2 + //X_hs_cnt_h + 04E9 0003 + //X_hs_llow_l + 04EA 0000 + //X_hs_llow_m + 04EB 0000 + //X_hs_llow_h + 04EC 0000 + //X_de_dly_l + 04ED 0058 + //X_de_dly_m + 04EE 0000 + //X_de_dly_h + 04EF 0000 + //X_de_high_l + 04F0 0080 + //X_de_high_h + 04F1 0007 + //X_de_low_l + 04F2 0090 + //X_de_low_h + 04F3 0000 + //X_de_cnt_l + 04F4 00D0 + //X_de_cnt_h + 04F5 0002 + //X_de_llow_l + 04F6 00C8 + //X_de_llow_m + 04F7 009C + //X_de_llow_h + 04F8 0006 + //Y_vs_dly_l + 05D8 0080 + //Y_vs_dly_m + 05D9 00F9 + //Y_vs_dly_h + 05DA 001C + //Y_vs_high_l + 05DB 0080 + //Y_vs_high_m + 05DC 0040 + //Y_vs_high_h + 05DD 0000 + //Y_vs_low_l + 05DE 0020 + //Y_vs_low_m + 05DF 0010 + //Y_vs_low_h + 05E0 0000 + //Y_hs_dly_l + 05E1 0000 + //Y_hs_dly_m + 05E2 0000 + //Y_hs_dly_h + 05E3 0000 + //Y_hs_high_l + 05E4 0038 + //Y_hs_high_h + 05E5 0000 + //Y_hs_low_l + 05E6 00D8 + //Y_hs_low_h + 05E7 0007 + //Y_hs_cnt_l + 05E8 00A2 + //Y_hs_cnt_h + 05E9 0003 + //Y_hs_llow_l + 05EA 0000 + //Y_hs_llow_m + 05EB 0000 + //Y_hs_llow_h + 05EC 0000 + //Y_de_dly_l + 05ED 0058 + //Y_de_dly_m + 05EE 0000 + //Y_de_dly_h + 05EF 0000 + //Y_de_high_l + 05F0 0080 + //Y_de_high_h + 05F1 0007 + //Y_de_low_l + 05F2 0090 + //Y_de_low_h + 05F3 0000 + //Y_de_cnt_l + 05F4 00D0 + //Y_de_cnt_h + 05F5 0002 + //Y_de_llow_l + 05F6 00C8 + //Y_de_llow_m + 05F7 009C + //Y_de_llow_h + 05F8 0006 + //Y_LUT_TEMPLATE_SEL + 05CD 0014 + //Turn off video + 6420 0010 + //Disable MST mode + 7019 0000 + //7019 0001 //Set MST_FUNCTION_ENABLE to 1 + //7904 0001 // Set MST_PAYLOAD_ID_0 to 01 + //7908 0002 // Set MST_PAYLOAD_ID_1 to 01 + //Disable MST_VS0_DTG_ENABLE + 7A14 0000 + //Disable LINK_ENABLE + 7000 0000 + //Reset DPRX core (VIDEO_INPUT_RESET) + 7054 0001 + ffff f000 //delay 0xf000 us + //Set MAX_LINK_RATE to 2.7Gb/s + 7074 000A + //Set MAX_LINK_COUNT to 4 + 7070 0004 + //Set ASYM_CTRL_PROP_GAIN to 000A + 04D0 000A + 05D0 000A + //Set AEQ time to 16ms + 6064 0000 + 6065 0000 + 6164 0000 + 6165 0000 + 6264 0000 + 6265 0000 + 6364 0000 + 6365 0000 + //Enable LINK_ENABLE + 7000 0001 + //delay 1000 + //Disable MSA reset + 7A18 0005 + //Adjust VS0_DMA_HSYNC + 7A28 00FF + 7A2A 00FF + //Adjust VS0_DMA_VSYNC + 7A24 00FF + 7A27 000F + //Enable MST_VS0_DTG_ENABLE + 7A14 0001 + //set EDP Video Control + 6421 0001 + //Turn on video + 6420 0013 + //delay 100 + //Turn off video + 6420 0010 + //delay 100 + //Turn on video + 6420 0013 + 6421 0003 + ]; + + i2c3_max96749_pinctrl: i2c3-max96749-pinctrl { + compatible = "maxim,max96749-pinctrl"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c45_max96749_pinctrl_pins>; + status = "disabled"; + + i2c45_max96749_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96749_I2C"; + function = "MAX96749_I2C"; + }; + lcd-bl-pwm { + pins = "MAX96749_MFP0"; + function = "SER_TXID4_TO_DES_LINKA"; + }; + tp-int { + pins = "MAX96749_MFP1"; + function = "DES_RXID1_TO_SER_LINKA"; + }; + lcd-bl-pwm-split { + pins = "MAX96749_MFP4"; + function = "SER_TXID4_TO_DES_LINKB"; + }; + tp-int-split { + pins = "MAX96749_MFP5"; + function = "DES_RXID5_TO_SER_LINKB"; + }; + }; + + i2c3_max96749_gpio: i2c3-max96749-gpio { + compatible = "maxim,max96749-gpio"; + status = "disabled"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c3_max96749_pinctrl 0 280 25>; + }; + }; + + i2c3_max96749_bridge: i2c3-max96749-bridge { + compatible = "maxim,max96749-bridge"; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + i2c3_max96749_from_edp: endpoint { + remote-endpoint = <&edp_out_i2c3_max96749>; + }; + }; + + port@1 { + reg = <1>; + + i2c3_max96749_out_i2c3_max96752: endpoint { + remote-endpoint = <&i2c3_max96752_from_i2c3_max96749>; + }; + }; + }; + }; + }; + + i2c3_max96752: i2c3-max96752@4a { + compatible = "maxim,max96752"; + reg = <0x4a>; + #address-cells = <1>; + #size-cells = <0>; + id-serdes-panel-split = <0x02>; + link = <0x01>; + status = "disabled"; + + serdes-init-sequence = [ + /*max96752 dual oLDI output*/ + 0002 0043 + 0073 0031 + 007b 0031 + 007d 0038 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 0090 + + 0050 0000 + 01ce 004e + 01ea 0004 + ]; + + i2c3_max96752_pinctrl: i2c3-max96752-pinctrl { + compatible = "maxim,max96752-pinctrl"; + status = "disabled"; + + pinctrl-names = "default","init","sleep"; + pinctrl-0 = <&i2c3_max96752_panel_pins>; + pinctrl-1 = <&i2c3_max96752_panel_pins>; + pinctrl-2 = <&i2c3_max96752_panel_sleep_pins>; + + i2c3_max96752_panel_pins: panel-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_HIGH"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_HIGH"; + }; + tp-int { + pins = "MAX96752_GPIO2"; + function = "DES_TXID1_TO_SER"; + }; + 40ms-delay { + pins = "MAX96752_GPIO15"; + function = "DELAY_40MS"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_HIGH"; + }; + lcd-bl-pwm { + pins = "MAX96752_GPIO4"; + function = "SER_TO_DES_RXID4"; + }; + lcd_bias_en { + pins = "MAX96752_GPIO7"; + function = "DES_TXID7_OUTPUT_HIGH"; + }; + lcd_vdd_en { + pins = "MAX96752_GPIO6"; + function = "DES_TXID6_OUTPUT_HIGH"; + }; + }; + + i2c3_max96752_panel_sleep_pins: panel-sleep-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_LOW"; + }; + + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_LOW"; + }; + + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_LOW"; + }; + }; + + i2c3_max96752_gpio: i2c3-max96752-gpio { + compatible = "maxim,max96752-gpio"; + status = "disabled"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c3_max96752_pinctrl 0 305 15>; + }; + }; + + i2c3_max96752_panel: i2c3-max96752-panel { + compatible = "maxim,max96752-panel"; + status = "disabled"; + + backlight = <&edp2lvds_backlight0>; + panel-size= <346 194>; + + panel-timing { + clock-frequency = <115000000>; + hactive = <1920>; + vactive = <720>; + hfront-porch = <56>; + hsync-len = <32>; + hback-porch = <56>; + vfront-porch = <200>; + vsync-len = <2>; + vback-porch = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + port { + i2c3_max96752_from_i2c3_max96749: endpoint { + remote-endpoint = <&i2c3_max96749_out_i2c3_max96752>; + }; + }; + }; + }; + + i2c3_himax: i2c3-himax@45 { + compatible = "himax,hxcommon"; + reg = <0x45>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&touch_gpio_edp>; + pinctrl-1 = <&touch_gpio_edp>; + himax,location = "himax-touch-edp"; + himax,irq-gpio = <&gpio3 RK_PD6 IRQ_TYPE_EDGE_FALLING>; + himax,rst-gpio = <&i2c3_max96752_gpio 5 GPIO_ACTIVE_LOW>; + himax,panel-coords = <0 1920 0 720>; + himax,display-coords = <0 1920 0 720>; + status = "disabled"; + }; +}; + +&mipidcphy0 { + status = "okay"; +}; + +&pinctrl { + serdes { + /*EDP*/ + i2c3_serdes_pins: i2c3-serdes-pins { + rockchip,pins = + <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>,/*lock*/ + <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>;/*err*/ + }; + /*DP*/ + i2c5_serdes_pins: i2c5-serdes-pins { + rockchip,pins = + <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*DSI*/ + i2c8_serdes_pins: i2c8-serdes-pins { + rockchip,pins = + <2 RK_PD7 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + }; +}; + +/* dsi->serdes->lvds_panel */ +&pwm1_6ch_1 { + status = "okay"; + pinctrl-0 = <&pwm1m2_ch1>; +}; + +/* dp->serdes->lvds_panel */ +&pwm2_8ch_7 { + pinctrl-0 = <&pwm2m3_ch7>; + status = "okay"; +}; + + +/* edp->serdes->lvds_panel */ +&pwm0_2ch_0 { + pinctrl-0 = <&pwm0m3_ch0>; + status = "disabled"; +}; + +&route_dp0 { + status = "disabled"; + connect = <&vp2_out_dp0>; + logo,uboot = "logo2.bmp"; + logo,kernel = "logo2.bmp"; +}; + +&route_dsi { + status = "okay"; + connect = <&vp1_out_dsi>; + logo,uboot = "logo1.bmp"; + logo,kernel = "logo1.bmp"; +}; + +&route_edp { + status = "disabled"; + connect = <&vp0_out_edp>; + logo,uboot = "logo2.bmp"; + logo,kernel = "logo2.bmp"; +}; + +&usbdp_phy { + rockchip,dp-lane-mux = <0 1 2 3>; + status = "okay"; +}; + +&usbdp_phy_dp { + status = "okay"; +}; + +&usbdp_phy_u3 { + maximum-speed = "high-speed"; + status = "okay"; +}; + +&vp0 { + assigned-clocks = <&cru DCLK_VP0>; + assigned-clock-parents = <&hdptxphy_hdmi>; +}; + +//dsi +&vp1 { + assigned-clocks = <&cru DCLK_VP1_SRC>; + assigned-clock-parents = <&cru PLL_VPLL>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dtsi index ff14855b8004..5fe4d1221e83 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v20.dtsi @@ -218,6 +218,11 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c0 { s35390a: s35390a@30 { compatible = "sii,s35390a"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-maxim-max96712-dcphy0-ox03j10.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-maxim-max96712-dcphy0-ox03j10.dtsi new file mode 100644 index 000000000000..cffb04ea4958 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-maxim-max96712-dcphy0-ox03j10.dtsi @@ -0,0 +1,729 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ +#include + +/ { + max96712_dcphy0_osc: max96712-dcphy0-oscillator { + compatible = "fixed-clock"; + #clock-cells = <1>; + clock-frequency = <25000000>; + clock-output-names = "max96712-dcphy0-osc"; + }; + + max96712_dcphy0_vcc1v2: max96712-dcphy0-vcc1v2 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v2"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + startup-delay-us = <850>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_vcc1v8: max96712-dcphy0-vcc1v8 { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_vcc1v8"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + startup-delay-us = <200>; + vin-supply = <&vcc_2v0_pldo_s3>; + }; + + max96712_dcphy0_pwdn_regulator: max96712-dcphy0-pwdn-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_pwdn"; + gpio = <&gpio2 RK_PA0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_pwdn>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + }; + + max96712_dcphy0_poc_regulator: max96712-dcphy0-poc-regulator { + compatible = "regulator-fixed"; + regulator-name = "max96712_dcphy0_poc"; + gpio = <&i2c7_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + enable-active-high; + startup-delay-us = <10000>; + off-on-delay-us = <5000>; + vin-supply = <&dcphy0_vcc12v_buck1>; + }; +}; + +&csi2_dcphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_dcphy0_in_max96712: endpoint@1 { + reg = <1>; + remote-endpoint = <&max96712_dcphy0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidcphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&i2c2 { + max96712_dcphy0: max96712@29 { + compatible = "maxim4c,max96712"; + status = "okay"; + reg = <0x29>; + clock-names = "xvclk"; + clocks = <&max96712_dcphy0_osc 0>; + pinctrl-names = "default"; + pinctrl-0 = <&max96712_dcphy0_errb>, <&max96712_dcphy0_lock>; + power-domains = <&power RK3576_PD_VI>; + rockchip,grf = <&sys_grf>; + vcc1v2-supply = <&max96712_dcphy0_vcc1v2>; + vcc1v8-supply = <&max96712_dcphy0_vcc1v8>; + pwdn-supply = <&max96712_dcphy0_pwdn_regulator>; + lock-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + port { + max96712_dcphy0_out: endpoint { + remote-endpoint = <&mipi_dcphy0_in_max96712>; + data-lanes = <1 2 3 4>; + }; + }; + + /* support mode config start */ + support-mode-config { + status = "okay"; + + bus-format = ; + sensor-width = <1920>; + sensor-height = <1280>; + max-fps-numerator = <10000>; + max-fps-denominator = <300000>; + bpp = <16>; + link-freq-idx = <20>; + }; + /* support mode config end */ + + /* serdes local device start */ + serdes-local-device { + status = "okay"; + + /* GMSL LINK config start */ + gmsl-links { + status = "okay"; + + link-vdd-ldo1-en = <1>; + link-vdd-ldo2-en = <1>; + + // Link A: link-id = 0 + gmsl-link-config-0 { + status = "okay"; + link-id = <0>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam0>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 14 D1 03 00 00 // VGAHiGain + 14 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link B: link-id = 1 + gmsl-link-config-1 { + status = "okay"; + link-id = <1>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam1>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 15 D1 03 00 00 // VGAHiGain + 15 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link C: link-id = 2 + gmsl-link-config-2 { + status = "okay"; + link-id = <2>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam2>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 16 D1 03 00 00 // VGAHiGain + 16 45 00 00 00 // Disable SSC + ]; + }; + }; + + // Link D: link-id = 3 + gmsl-link-config-3 { + status = "okay"; + link-id = <3>; // Link ID: 0/1/2/3 + + link-type = <1>; // 0: GMSL1, 1: GMSL2 + link-rx-rate = <1>; // 0: 3GBPS, 1: 6GBPS + link-tx-rate = <0>; // 0: default for 187.5MBPS + + link-remote-cam = <&max96712_dcphy0_cam3>; // remote camera + + link-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 17 D1 03 00 00 // VGAHiGain + 17 45 00 00 00 // Disable SSC + ]; + }; + }; + }; + /* GMSL LINK config end */ + + /* VIDEO PIPE config start */ + video-pipes { + status = "okay"; + + // Video Pipe 0 + video-pipe-config-0 { + status = "okay"; + pipe-id = <0>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <0>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 0 to Controller 1 + 09 0B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 2D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 0D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 0E 1e 00 00 // DST0 VC = 0, DT = YUV422 8bit + 09 0F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 10 00 00 00 // DST1 VC = 0, DT = Frame Start + 09 11 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 12 01 00 00 // DST2 VC = 0, DT = Frame End + ]; + }; + }; + + // Video Pipe 1 + video-pipe-config-1 { + status = "okay"; + pipe-id = <1>; // Video Pipe 1: pipe-id = 1 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <1>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 1 to Controller 1 + 09 4B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 6D 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 4D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 4E 5e 00 00 // DST0 VC = 1, DT = YUV422 8bit + 09 4F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 50 40 00 00 // DST1 VC = 1, DT = Frame Start + 09 51 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 52 41 00 00 // DST2 VC = 1, DT = Frame End + ]; + }; + }; + + // Video Pipe 2 + video-pipe-config-2 { + status = "okay"; + pipe-id = <2>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <2>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 2 to Controller 1 + 09 8B 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 AD 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 8D 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 8E 9e 00 00 // DST0 VC = 2, DT = YUV422 8bit + 09 8F 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 90 80 00 00 // DST1 VC = 2, DT = Frame Start + 09 91 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 92 81 00 00 // DST2 VC = 2, DT = Frame End + ]; + }; + }; + + // Video Pipe 3 + video-pipe-config-3 { + status = "okay"; + pipe-id = <3>; // Video Pipe ID: 0/1/2/3/4/5/6/7 + + pipe-idx = <2>; // Video Pipe X/Y/Z/U: 0/1/2/3 + link-idx = <3>; // Link A/B/C/D: 0/1/2/3 + + pipe-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // Send YUV422, FS, and FE from Video Pipe 3 to Controller 1 + 09 CB 07 00 00 // Enable 0/1/2 SRC/DST Mappings + 09 ED 15 00 00 // SRC/DST 0/1/2 -> CSI2 Controller 1; + // For the following MSB 2 bits = VC, LSB 6 bits = DT + 09 CD 1e 00 00 // SRC0 VC = 0, DT = YUV422 8bit + 09 CE de 00 00 // DST0 VC = 3, DT = YUV422 8bit + 09 CF 00 00 00 // SRC1 VC = 0, DT = Frame Start + 09 D0 c0 00 00 // DST1 VC = 3, DT = Frame Start + 09 D1 01 00 00 // SRC2 VC = 0, DT = Frame End + 09 D2 c1 00 00 // DST2 VC = 3, DT = Frame End + ]; + }; + }; + }; + /* VIDEO PIPE config end */ + + /* MIPI TXPHY config start */ + mipi-txphys { + status = "okay"; + + phy-mode = <0>; // 0: 4Lanes, 1: 2Lanes + phy-force-clock-out = <1>; // 1: default for force clock out + phy-force-clk0-en = <1>; // provide MIPI clock: 0 = PHY1, 1 = PHY0 + phy-force-clk3-en = <0>; // provide MIPI clock: 0 = PHY2, 1 = PHY3 + + // MIPI TXPHY A: phy-id = 0 + mipi-txphy-config-0 { + status = "okay"; + phy-id = <0>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0x4>; + vc-ext-en = <0>; + }; + + // MIPI TXPHY B: phy-id = 1 + mipi-txphy-config-1 { + status = "okay"; + phy-id = <1>; // MIPI TXPHY ID: 0/1/2/3 + + phy-type = <0>; // 0: DPHY, 1: CPHY + auto-deskew = <0x80>; + data-lane-num = <4>; + data-lane-map = <0xe>; + vc-ext-en = <0>; + }; + }; + /* MIPI TXPHY config end */ + + /* local device extra init sequence */ + extra-init-sequence { + status = "disabled"; + + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + // common init sequence such as fsync / gpio and so on + ]; + }; + }; + /* serdes local device end */ + + /* i2c-mux start */ + i2c-mux { + #address-cells = <1>; + #size-cells = <0>; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser0: max96717@51 { + compatible = "maxim,ser,max96717"; + reg = <0x51>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 01 // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dcphy0_cam0: ox03j10@31 { + compatible = "maxim,ovti,ox03j10"; + reg = <0x31>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dcphy0_ser0>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam0_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser1: max96717@52 { + compatible = "maxim,ser,max96717"; + reg = <0x52>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 01 // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dcphy0_cam1: ox03j10@32 { + compatible = "maxim,ovti,ox03j10"; + reg = <0x32>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dcphy0_ser1>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam1_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser2: max96717@53 { + compatible = "maxim,ser,max96717"; + reg = <0x53>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 01 // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dcphy0_cam2: ox03j10@33 { + compatible = "maxim,ovti,ox03j10"; + reg = <0x33>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dcphy0_ser2>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <2>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam2_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + // Note: Serializer node defined before camera node + max96712_dcphy0_ser3: max96717@54 { + compatible = "maxim,ser,max96717"; + reg = <0x54>; + + ser-i2c-addr-def = <0x40>; + + ser-init-sequence { + seq-item-size = <5>; // reg-addr-len + reg-val-len * 2 + 1 + reg-addr-len = <2>; // 1: 8bits, 2: 16bits + reg-val-len = <1>; // 1: 8bits, 2: 16bits, 3: 24bits + + // reg_addr reg_val val_mask delay + init-sequence = [ + 02 BE 00 00 01 // MFP0 GPIO_OUT = 0: MFP0 output is driven to 0 + 03 02 10 00 00 // Improve CMU voltage performance to improve link robustness + 14 17 00 00 00 // RLMS17 = 0x00: disable AGC/DFE adaptation + 14 32 7f 00 00 // RLMS32 = 0x7F: change OSN loop mode + 03 F0 59 00 00 // REFGEN_PREDEF_FREQ_ALT = 1: Alternative table, REFGEN_PREDEF_FREQ = 0x1: 24MHz + 00 03 03 00 00 // RCLKSEL = 0x3: Reference PLL output + 00 06 B1 00 01 // RCLKEN = 1: RCLK output is enabled + 02 BF 40 00 00 // MFP0 PULL_UPDN_SEL = 1: Pullup + 02 BE 10 00 01 // MFP0 GPIO_OUT = 1: MFP0 output is driven to 1 + ]; + }; + }; + + max96712_dcphy0_cam3: ox03j10@34 { + compatible = "maxim,ovti,ox03j10"; + reg = <0x34>; + + cam-i2c-addr-def = <0x36>; + + cam-remote-ser = <&max96712_dcphy0_ser3>; // remote serializer + + poc-supply = <&max96712_dcphy0_poc_regulator>; + + rockchip,camera-module-index = <3>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + + /* port config start */ + port { + max96712_dcphy0_cam3_out: endpoint { + data-lanes = <1 2 3 4>; + }; + }; + /* port config end */ + }; + }; + }; + /* i2c-mux end */ + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidcphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi0_in>; + }; + }; + }; +}; + +&rkcif_mipi_lvds { + status = "okay"; + /* parameters for do cif reset detecting: + * index0: monitor mode, + 0 for idle, + 1 for continue, + 2 for trigger, + 3 for hotplug (for nextchip) + * index1: the frame id to start timer, + min is 2 + * index2: frame num of monitoring cycle + * index3: err time for keep monitoring + after finding out err (ms) + * index4: csi2 err reference val for resetting + */ + rockchip,cif-monitor = <3 2 1 1000 5>; + + port { + cif_mipi0_in: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif { + status = "okay"; + rockchip,android-usb-camerahal-enable; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&pinctrl { + max96712-dcphy0 { + max96712_dcphy0_pwdn: max96712-dcphy0-pwdn { + rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_output_low>; + }; + + max96712_dcphy0_errb: max96712-dcphy0-errb { + rockchip,pins = <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + + max96712_dcphy0_lock: max96712-dcphy0-lock { + rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none_smt>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu-io-expander.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu-io-expander.dtsi new file mode 100644 index 000000000000..e4d45ec0440d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu-io-expander.dtsi @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2023 Rockchip Electronics Co., Ltd. + * + */ + +#define MCU_PERI_5V_EN 0x01 +#define MCU_CAM1_PWREN 0x02 +#define MCU_CAM2_PWREN 0x03 +#define DSP_CORE_PWR_EN 0x04 +#define MCU_DSP_RST 0x05 +#define FM_PWR_EN_MCU 0x06 +#define ADC_PWDN_MCU 0x07 +#define MCU_ADSP_VCC12V_EN 0x08 +#define MCU_CAM3_PWREN 0x08 +#define A2B_PWR_EN_MCU 0x09 +#define MCU_RSTB_ETH 0x0a +#define MCU_DISB_ETH 0x0b +#define MUTE_AMP_MCU 0x0c +#define MCU_LCD1_SER_EN 0x0a +#define MCU_LCD2_SER_EN 0x0b +#define MCU_LCD3_SER_EN 0x0c +#define STANDBY_AMP_MCU 0x0d +#define MCU_CTRL_CluPWR 0x0e +#define MCU_LCD1_12V_EN 0x0f +#define MCU_LCD2_12V_EN 0x10 +#define MCU_LCD3_12V_EN 0x11 +#define MCU_CAM1_OUT1_EN 0x12 +#define MCU_CAM1_OUT2_EN 0x13 +#define MCU_CAM1_OUT3_EN 0x14 +#define MCU_CAM1_OUT4_EN 0x15 +#define MCU_CAM2_OUT1_EN 0x16 +#define MCU_CAM2_OUT2_EN 0x17 +#define MCU_CAM2_OUT3_EN 0x18 +#define MCU_CAM2_OUT4_EN 0x19 +#define MCU_CAM3_OUT1_EN 0x1a +#define MCU_CAM3_OUT2_EN 0x1b +#define MCU_CAM3_OUT3_EN 0x1c +#define MCU_CAM3_OUT4_EN 0x1d +#define MCU_USB3HOST_PWREN 0x1e +#define USB_OTG0_PWREN_H 0x1f +#define MCU_CTRL_VSYS 0x20 +#define DSP_VCC1V8_PWR_EN 0x21 +#define DSP_VCC3V3_PWR_EN 0x22 + +#define PERI_5V_PG 0x92 +#define SYS4V_PG 0x93 +#define FAULT_AMP3_MCU 0x92 +#define FAULT_AMP4_MCU 0x93 +#define MCU_DSP_FAULTB 0x94 +#define ADC_INT_MCU 0x95 +#define A2B_IRQ_MCU 0x96 +#define ACC_DET 0x97 +#define BACK_DET 0x98 +#define MCU_CAM2_OUT1_DIAG 0x99 +#define MCU_CAM2_OUT2_DIAG 0x9a +#define MCU_CAM2_OUT3_DIAG 0x9b +#define MCU_CAM2_OUT4_DIAG 0x9c +#define MCU_LCD1_PWR_DIAG 0x9d +#define MCU_LCD2_PWR_DIAG 0x9e +#define MCU_LCD3_PWR_DIAG 0x9f + +/ { + gpio_mcu_rockchip: gpio-mcu-rockchip { + compatible = "rockchip,mcu-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <32>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + }; +}; + +&spi4 { + compatible = "rockchip,spi-slave"; + status = "okay"; + pinctrl-names = "default", "high_speed"; + pinctrl-0 = <&spi4m3_csn0 &spi4m3_pins>; + ready-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>; + slave@0 { + compatible = "rockchip,vehicle-spi"; + status = "okay"; + id = <0x0>; + reg = <0x0>; + spi-max-frequency = <1000000>; + spi-lsb-first; + pinctrl-names = "default"; + pinctrl-0 = <&spi_irq_mcu>; + irq-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_LOW>; + }; +}; + +&pinctrl { + slave-external-mcu { + spi_irq_mcu: spi-irq-mcu { + rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu.dts b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu.dts new file mode 100644 index 000000000000..44162ee09a4e --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21-mcu.dts @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include "rk3576.dtsi" +#include "rk3576-vehicle-evb-v20.dtsi" +#include "rk3576-vehicle-evb-v21-mcu-io-expander.dtsi" +#include "rk3576-vehicle-evb-v20-serdes-mfd-display-maxim.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy0-ox03j10.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi" +#include "rk3576-android.dtsi" + +/delete-node/ &vcc5v0_host_usb30; + +/ { + model = "Rockchip RK3576 VEHICLE EVB V21 Board"; + compatible = "rockchip,rk3576-vehicle-evb-v21", "rockchip,rk3576"; + + chosen: chosen { + bootargs = "earlycon=uart8250,mmio32,0x2ad40000 console=ttyFIQ0 rcupdate.rcu_expedited=1 rcu_nocbs=all spidev.bufsiz=131072"; + }; + + vehicle_dummy: vehicle-dummy { + status = "okay"; + compatible = "rockchip,vehicle-dummy-adc"; + io-channels = <&saradc 4>, <&saradc 5>, <&saradc 6>; + io-channel-names = "gear", "turn_left", "turn_right"; + }; + + vcc5v0_buck: vcc5v0-buck { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_buck_en>; + startup-delay-us = <2500>; + off-on-delay-us = <1500>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + cluster_power_buck: cluster_power-buck { + compatible = "regulator-fixed"; + regulator-name = "cluster_power_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + //enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + vin-supply = <&vcc_1v8_s0>; + pinctrl-names = "default"; + pinctrl-0 = <&cluster_buck_en>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + usb_otg_vcc5v_buck: usb_otg_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + //enable-active-high; + gpio = <&gpio_mcu_rockchip USB_OTG0_PWREN_H GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + usb_host_vcc5v_buck: usb_host_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "usb_host_vcc5v_buck"; + //regulator-boot-on; + //regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_USB3HOST_PWREN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + lcd1_vcc12v_buck: lcd1_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd1_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD1_12V_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd2_vcc12v_buck: lcd2_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd2_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD2_12V_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd1_ser_vcc5v_buck: lcd1_ser_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd1_ser_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD1_SER_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + lcd2_ser_vcc5v_buck: lcd2_ser_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd2_ser_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD2_SER_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + adsp_vcc12v_buck: adsp_vcc12v-buck { + compatible = "regulator-fixed"; + status = "disabled"; + regulator-name = "adsp_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_ADSP_VCC12V_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd3_vcc12v_buck: lcd3_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd3_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD3_12V_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd3_vcc5v_buck: lcd3_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd3_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_LCD3_SER_EN GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck1: dcphy0_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM1_OUT1_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck2: dcphy0_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM1_OUT2_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck3: dcphy0_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM1_OUT3_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck4: dcphy0_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM1_OUT4_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck1: dphy0_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM2_OUT1_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck2: dphy0_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM2_OUT2_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck3: dphy0_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM2_OUT3_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck4: dphy0_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM2_OUT4_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck1: dphy3_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM3_OUT1_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck2: dphy3_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM3_OUT2_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck3: dphy3_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM3_OUT3_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck4: dphy3_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&gpio_mcu_rockchip MCU_CAM3_OUT4_EN GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; +}; + +&dfi { + status = "disabled"; +}; + +&dmc { + status = "disabled"; +}; + +&gmac1 { + status = "disabled"; +}; + +&hym8563 { + status = "disabled"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2m0_xfer>; +}; + +/*edp*/ +&i2c3_max96752 { + use-reg-check-work; + vpower-supply = <&lcd1_vcc12v_buck>; +}; + +/*edp touch*/ +&i2c3_himax { + himax,irq-gpio = <&gpio0 RK_PB6 IRQ_TYPE_EDGE_FALLING>; +}; + +/*dp*/ +&i2c5_max96745 { + lock-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; +}; + +&i2c5_ilitek { + interrupt-parent = <&gpio4>; + interrupts = ; +}; + +/*dp*/ +&i2c5_max96752 { + use-reg-check-work; + vpower-supply = <&lcd2_vcc12v_buck>; +}; + +&i2c8_max96789 { + route-enable; +}; + +/*dsi*/ +&i2c8_max96752 { + use-reg-check-work; + vpower-supply = <&lcd3_vcc12v_buck>; +}; + +&dp2lvds_backlight0 { + pwms = <&pwm2_8ch_7 0 25000 0>; +}; + +&edp2lvds_backlight0 { + pwms = <&pwm0_2ch_0 0 25000 0>; +}; + +&max96712_dphy0_poc_regulator { + gpio = <&gpio_mcu_rockchip MCU_CAM2_PWREN GPIO_ACTIVE_HIGH>; +}; + +/* edp->serdes->lvds_panel */ +&pwm0_2ch_0 { + pinctrl-0 = <&pwm0m3_ch0>; +}; + +/* dp->serdes->lvds_panel */ +&pwm2_8ch_7 { + pinctrl-0 = <&pwm2m3_ch7>; +}; + +&pinctrl { + touch { + //dsi-i2c8 + touch_gpio_dsi: touch-gpio-dsi { + rockchip,pins = + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + //dp-i2c5 + touch_gpio_dp: touch-gpio-dp { + rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + //edp0-i2c3 + touch_gpio_edp: touch-gpio-edp { + rockchip,pins = + <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + vcc5v0-buck { + vcc5v0_buck_en: vcc5v0-buck-en { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + cluster-buck { + cluster_buck_en: cluster-buck-en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + +&rkvpss { + status = "okay"; +}; + +&rkvpss_mmu { + status = "okay"; +}; + +&rkvpss_vir0 { + status = "okay"; +}; + +&route_dsi { + status = "okay"; +}; + +&sdmmc { + status = "disabled"; +}; + +&ufs { + status = "disabled"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + //vbus-supply = <&usb_otg_vcc5v_buck>; + status = "okay"; +}; + +&u2phy1_otg { + phy-supply = <&usb_host_vcc5v_buck>; + status = "okay"; +}; + +&usbdp_phy { + maximum-speed = "high-speed"; + status = "okay"; +}; + +&usb_drd1_dwc3 { + snps,dis_u2_susphy_quirk; + snps,usb2-lpm-disable; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21.dts b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21.dts new file mode 100644 index 000000000000..9e119c0a1b16 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb-v21.dts @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include "rk3576.dtsi" +#include "rk3576-vehicle-evb-v20.dtsi" +#include "rk3576-vehicle-evb-v20-nca9539-io-expander.dtsi" +#include "rk3576-vehicle-evb-v20-serdes-mfd-display-maxim.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy0-ox03j10.dtsi" +#include "rk3576-vehicle-evb-v20-maxim-max96712-dphy3-sc233at.dtsi" +#include "rk3576-android.dtsi" + +/delete-node/ &vcc5v0_host_usb30; + +/ { + model = "Rockchip RK3576 VEHICLE EVB V21 Board"; + compatible = "rockchip,rk3576-vehicle-evb-v21", "rockchip,rk3576"; + + chosen: chosen { + bootargs = "earlycon=uart8250,mmio32,0x2ad40000 console=ttyFIQ0 rcupdate.rcu_expedited=1 rcu_nocbs=all spidev.bufsiz=131072"; + }; + + vehicle_dummy: vehicle-dummy { + status = "okay"; + compatible = "rockchip,vehicle-dummy-adc"; + io-channels = <&saradc 4>, <&saradc 5>, <&saradc 6>; + io-channel-names = "gear", "turn_left", "turn_right"; + }; + + vcc5v0_buck: vcc5v0-buck { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio0 RK_PD3 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_buck_en>; + startup-delay-us = <2500>; + off-on-delay-us = <1500>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + cluster_power_buck: cluster_power-buck { + compatible = "regulator-fixed"; + regulator-name = "cluster_power_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + //enable-active-high; + gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + vin-supply = <&vcc_1v8_s0>; + pinctrl-names = "default"; + pinctrl-0 = <&cluster_buck_en>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + usb_otg_vcc5v_buck: usb_otg_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "usb_otg_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + //enable-active-high; + gpio = <&i2c0_nca9539_gpio 0 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + usb_host_vcc5v_buck: usb_host_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "usb_host_vcc5v_buck"; + //regulator-boot-on; + //regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 1 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + lcd1_vcc12v_buck: lcd1_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd1_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 2 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd2_vcc12v_buck: lcd2_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd2_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 3 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd1_ser_vcc5v_buck: lcd1_ser_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd1_ser_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 4 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + lcd2_ser_vcc5v_buck: lcd2_ser_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd2_ser_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 5 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_buck>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <5000000>; + }; + }; + + adsp_vcc12v_buck: adsp_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "adsp_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c0_nca9539_gpio 6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd3_vcc12v_buck: lcd3_vcc12v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd3_vcc12v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 0 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + lcd3_vcc5v_buck: lcd3_vcc5v-buck { + compatible = "regulator-fixed"; + regulator-name = "lcd3_vcc5v_buck"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 1 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck1: dcphy0_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 3 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck2: dcphy0_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 4 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck3: dcphy0_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 5 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dcphy0_vcc12v_buck4: dcphy0_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dcphy0_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 6 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck1: dphy0_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 7 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck2: dphy0_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 8 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck3: dphy0_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 9 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy0_vcc12v_buck4: dphy0_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dphy0_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 10 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck1: dphy3_vcc12v-buck1 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck1"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 11 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck2: dphy3_vcc12v-buck2 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck2"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 12 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck3: dphy3_vcc12v-buck3 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck3"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 13 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; + + dphy3_vcc12v_buck4: dphy3_vcc12v-buck4 { + compatible = "regulator-fixed"; + regulator-name = "dphy3_vcc12v_buck4"; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + gpio = <&i2c7_nca9539_gpio 14 GPIO_ACTIVE_HIGH>; + startup-delay-us = <2000>; + off-on-delay-us = <16000>; + vin-supply = <&vcc12v_dcin>; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <12000000>; + }; + }; +}; + +&dfi { + status = "disabled"; +}; + +&dmc { + status = "disabled"; +}; + +&gmac1 { + status = "disabled"; +}; + +&hym8563 { + status = "disabled"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2m0_xfer>; +}; + +/*edp*/ +&i2c3_max96752 { + use-reg-check-work; + vpower-supply = <&lcd1_vcc12v_buck>; +}; + +/*edp touch*/ +&i2c3_himax { + himax,irq-gpio = <&gpio0 RK_PB6 IRQ_TYPE_EDGE_FALLING>; +}; + +/*dp*/ +&i2c5_max96745 { + lock-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; +}; + +&i2c5_ilitek { + interrupt-parent = <&gpio4>; + interrupts = ; +}; + +/*dp*/ +&i2c5_max96752 { + use-reg-check-work; + vpower-supply = <&lcd2_vcc12v_buck>; +}; + +&i2c8_max96789 { + route-enable; +}; + +/*dsi*/ +&i2c8_max96752 { + use-reg-check-work; + vpower-supply = <&lcd3_vcc12v_buck>; +}; + +&dp2lvds_backlight0 { + pwms = <&pwm2_8ch_7 0 25000 0>; +}; + +&edp2lvds_backlight0 { + pwms = <&pwm0_2ch_0 0 25000 0>; +}; + +/* edp->serdes->lvds_panel */ +&pwm0_2ch_0 { + pinctrl-0 = <&pwm0m3_ch0>; +}; + +/* dp->serdes->lvds_panel */ +&pwm2_8ch_7 { + pinctrl-0 = <&pwm2m3_ch7>; +}; + +&pinctrl { + touch { + //dsi-i2c8 + touch_gpio_dsi: touch-gpio-dsi { + rockchip,pins = + <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + //dp-i2c5 + touch_gpio_dp: touch-gpio-dp { + rockchip,pins = <4 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + //edp0-i2c3 + touch_gpio_edp: touch-gpio-edp { + rockchip,pins = + <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + vcc5v0-buck { + vcc5v0_buck_en: vcc5v0-buck-en { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + cluster-buck { + cluster_buck_en: cluster-buck-en { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; +}; + +&rkvpss { + status = "okay"; +}; + +&rkvpss_mmu { + status = "okay"; +}; + +&rkvpss_vir0 { + status = "okay"; +}; + +&route_dsi { + status = "okay"; +}; + +&sdmmc { + status = "disabled"; +}; + +&ufs { + status = "disabled"; +}; + +&u2phy0 { + status = "okay"; +}; + +&u2phy0_otg { + //vbus-supply = <&usb_otg_vcc5v_buck>; + status = "okay"; +}; + +&u2phy1_otg { + phy-supply = <&usb_host_vcc5v_buck>; + status = "okay"; +}; + +&usbdp_phy { + maximum-speed = "high-speed"; + status = "okay"; +}; + +&usb_drd1_dwc3 { + snps,dis_u2_susphy_quirk; + snps,usb2-lpm-disable; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb.dtsi index f65e3b0b5627..47b640443de5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle-evb.dtsi @@ -238,6 +238,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c0 { s35390a: s35390a@30 { compatible = "sii,s35390a"; diff --git a/arch/arm64/boot/dts/rockchip/rk3576-vehicle.dtsi b/arch/arm64/boot/dts/rockchip/rk3576-vehicle.dtsi index 5498c092419f..60d2ec797e11 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576-vehicle.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576-vehicle.dtsi @@ -251,6 +251,25 @@ goodix,rst-gpio = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio0 RK_PC5 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + status = "disabled"; + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c2 { @@ -305,6 +324,22 @@ <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; wireless-bluetooth { diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index 64dff112dc69..ec54470fd966 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -2487,6 +2487,28 @@ status = "disabled"; }; + cci: cci@27500000 { + compatible = "arm,cci-500"; + reg = <0x0 0x27500000 0x0 0x100000>; + ranges = <0x0 0x0 0x27500000 0x100000>; + #address-cells = <1>; + #size-cells = <1>; + + pmu@10000 { + compatible = "arm,cci-500-pmu,r0"; + reg = <0x10000 0x80000>; + interrupt-parent = <&gic>; + interrupts = , + , + , + , + , + , + , + ; + }; + }; + rknpu: npu@27700000 { compatible = "rockchip,rk3576-rknpu"; reg = <0x0 0x27700000 0x0 0x8000>, diff --git a/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi index 8a534f342a53..c180b06c0974 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576s-evb.dtsi @@ -611,6 +611,25 @@ goodix,rst-gpio = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio0 RK_PC5 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + status = "disabled"; + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c2 { @@ -667,6 +686,22 @@ <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD0 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; wireless-bluetooth { diff --git a/arch/arm64/boot/dts/rockchip/rk3576s-evb1.dtsi b/arch/arm64/boot/dts/rockchip/rk3576s-evb1.dtsi index ed4050845eb6..a9fe620f2bbf 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576s-evb1.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576s-evb1.dtsi @@ -247,6 +247,11 @@ status = "okay"; }; +&hynitron { + status = "okay"; + power-supply = <&vcc3v3_lcd_n>; +}; + &i2c2 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi index b36dd1f3c58f..a2d471821611 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi @@ -280,6 +280,11 @@ mem-supply = <&vdd_cpu_big1_mem_s0>; }; +&display_subsystem { + clocks = <&hdptxphy_hdmi0>, <&hdptxphy_hdmi1>; + clock-names = "hdmi0_phy_pll", "hdmi1_phy_pll"; +}; + &dsi0 { status = "disabled"; //rockchip,lane-rate = <1000>; @@ -291,6 +296,7 @@ reset-delay-ms = <10>; enable-delay-ms = <10>; prepare-delay-ms = <10>; + init-delay-ms = <10>; unprepare-delay-ms = <10>; disable-delay-ms = <60>; width-mm = <68>; @@ -625,6 +631,7 @@ reset-delay-ms = <10>; enable-delay-ms = <10>; prepare-delay-ms = <10>; + init-delay-ms = <10>; unprepare-delay-ms = <10>; disable-delay-ms = <10>; width-mm = <68>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts index 2dcef191fc6b..adbe1a4294a3 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4-v10-ipc-6x-linux.dts @@ -83,6 +83,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c6 { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi index 15c811563b67..b0a9c6b0d7e0 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi @@ -496,6 +496,25 @@ goodix,irq-gpio = <&gpio0 RK_PD3 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c7 { @@ -634,6 +653,22 @@ <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb10.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb10.dtsi index 29e7072860e9..9fa949c91b0d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb10.dtsi @@ -503,6 +503,25 @@ goodix,irq-gpio = <&gpio3 RK_PC0 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c5m3_xfer { @@ -795,6 +814,22 @@ <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>, <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4-v10-edp.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4-v10-edp.dts index 1c7b183a80de..28a72d000bb2 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4-v10-edp.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4-v10-edp.dts @@ -118,6 +118,10 @@ status = "okay"; }; +&hynitron { + status = "disabled"; +}; + &i2c6 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi index 85d82cf5266b..d38c731a436b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi @@ -328,6 +328,25 @@ goodix,irq-gpio = <&gpio0 RK_PD3 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c7 { @@ -436,6 +455,22 @@ <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp-linux.dts index 02509827cdf8..8c368cf57e67 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp-linux.dts @@ -87,6 +87,10 @@ status = "okay"; }; +&hynitron { + status = "disabled"; +}; + &i2c5 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp.dts index 654e4af17449..1f456e502a79 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5-v10-edp.dts @@ -87,6 +87,10 @@ status = "okay"; }; +&hynitron { + status = "disabled"; +}; + &i2c5 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi index 4e76a04eb431..6db765f1140e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi @@ -984,6 +984,25 @@ goodix,irq-gpio = <&gpio4 RK_PB1 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio4 RK_PB1 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c7 { @@ -1103,6 +1122,22 @@ <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <4 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi index ef5dd89975c4..d1177ce60787 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi @@ -268,6 +268,25 @@ goodix,irq-gpio = <&gpio0 RK_PC6 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c8 { @@ -383,6 +402,22 @@ <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi index 96b7406c9b3a..d60040f0807a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb6-lp4.dtsi @@ -341,6 +341,25 @@ goodix,irq-gpio = <&gpio0 RK_PD3 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD2 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2s5_8ch { @@ -418,6 +437,22 @@ <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dts b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dts index fc23e31ffc21..8cf01c534961 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dts @@ -87,6 +87,10 @@ status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c6 { status = "disabled"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi index 2d1ae9d38b2f..b8e5dd6e81d8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb7-lp4.dtsi @@ -549,6 +549,25 @@ goodix,irq-gpio = <&gpio3 RK_PC0 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c6 { @@ -707,6 +726,22 @@ <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>, <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dtsi index 7ffc43b6f367..e9c13de9883c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-evb7-v11.dtsi @@ -560,6 +560,24 @@ goodix,irq-gpio = <&gpio3 RK_PC0 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c6 { @@ -774,6 +792,22 @@ <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>, <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi index fe48e4414f0e..ea4cb13306ce 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-edp-x0.dtsi @@ -518,6 +518,24 @@ irq-gpios = <&gpio1 RK_PA6 IRQ_TYPE_LEVEL_LOW>; rst-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c7 { @@ -649,6 +667,22 @@ <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { @@ -767,4 +801,3 @@ &usbhost_dwc3_0 { status = "disabled"; }; - diff --git a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi index 818646826ce7..92ca3231a681 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-toybrick-x0.dtsi @@ -519,6 +519,25 @@ irq-gpios = <&gpio1 RK_PA6 IRQ_TYPE_LEVEL_LOW>; rst-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c7 { @@ -622,6 +641,22 @@ <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>, <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-serdes-mfd-display-maxim-2.5k.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-serdes-mfd-display-maxim-2.5k.dtsi new file mode 100644 index 000000000000..ba8b772fef2d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-serdes-mfd-display-maxim-2.5k.dtsi @@ -0,0 +1,2493 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +/ { + dsi2lvds_backlight1: dsi2lvds_backlight1 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + dp2lvds_backlight0: dp2lvds_backlight0 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + dp2lvds_backlight1: dp2lvds_backlight1 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + edp2lvds_backlight0: edp2lvds_backlight0 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; + + edp2lvds_backlight1: edp2lvds_backlight1 { + compatible = "pwm-backlight"; + brightness-levels = < + 0 20 20 21 21 22 22 23 + 23 24 24 25 25 26 26 27 + 27 28 28 29 29 30 30 31 + 31 32 32 33 33 34 34 35 + 35 36 36 37 37 38 38 39 + 40 41 42 43 44 45 46 47 + 48 49 50 51 52 53 54 55 + 56 57 58 59 60 61 62 63 + 64 65 66 67 68 69 70 71 + 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 + 88 89 90 91 92 93 94 95 + 96 97 98 99 100 101 102 103 + 104 105 106 107 108 109 110 111 + 112 113 114 115 116 117 118 119 + 120 121 122 123 124 125 126 127 + 128 129 130 131 132 133 134 135 + 136 137 138 139 140 141 142 143 + 144 145 146 147 148 149 150 151 + 152 153 154 155 156 157 158 159 + 160 161 162 163 164 165 166 167 + 168 169 170 171 172 173 174 175 + 176 177 178 179 180 181 182 183 + 184 185 186 187 188 189 190 191 + 192 193 194 195 196 197 198 199 + 200 201 202 203 204 205 206 207 + 208 209 210 211 212 213 214 215 + 216 217 218 219 220 221 222 223 + 224 225 226 227 228 229 230 231 + 232 233 234 235 236 237 238 239 + 240 241 242 243 244 245 246 247 + 248 249 250 251 252 253 254 255 + >; + default-brightness-level = <200>; + }; +}; + +&backlight { + pwms = <&pwm0 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl0_enable_pin>; + //enable-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&dsi2lvds_backlight1 { + pwms = <&pwm2 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl1_enable_pin>; + //enable-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&dp0 { + //rockchip,split-mode; + force-hpd; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + dp0_out_i2c4_max96749: endpoint { + link-frequencies = /bits/ 64 <2700000000>; + remote-endpoint = <&i2c4_max96749_from_dp0>; + }; + }; + }; +}; + +&dp0_in_vp0 { + status = "okay"; +}; + +&dp0_in_vp1 { + status = "disabled"; +}; + +&dp0_in_vp2 { + status = "disabled"; +}; + +&dp1 { + force-hpd; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + dp1_out_i2c8_max96749: endpoint { + link-frequencies = /bits/ 64 <2700000000>; + remote-endpoint = <&i2c8_max96749_from_dp1>; + }; + }; + }; + +}; + +&dp1_in_vp0 { + status = "disabled"; +}; + +&dp1_in_vp1 { + status = "disabled"; +}; + +&dp1_in_vp2 { + status = "okay"; +}; + +&dp2lvds_backlight0 { + pwms = <&i2c4_r7f701_pwm 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl2_enable_pin>; + //enable-gpios = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&dp2lvds_backlight1 { + pwms = <&i2c8_r7f701_pwm 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl3_enable_pin>; + //enable-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +/* + * mipi_dcphy0 needs to be enabled + * when dsi0 is enabled + */ +&dsi0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + dsi0_out_i2c2_max96789: endpoint { + remote-endpoint = <&i2c2_max96789_from_dsi0>; + }; + }; + }; +}; + +&dsi0_in_vp2 { + status = "disabled"; +}; + +&dsi0_in_vp3 { + status = "okay"; +}; + +/* + * mipi_dcphy1 needs to be enabled + * when dsi1 is enabled + */ +&dsi1 { + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; +#if 0 + port@1 { + reg = <1>; + + dsi1_out_i2c2_max96789: endpoint { + remote-endpoint = <&i2c2_max96789_from_dsi1>; + }; + }; +#endif + }; +}; + +&dsi1_in_vp2 { + status = "disabled"; +}; + +&dsi1_in_vp3 { + status = "disabled"; +}; + +&edp0 { + //rockchip,split-mode; + force-hpd; + status = "okay"; + + ports { + port@1 { + reg = <1>; + + edp0_out_i2c5_max96749: endpoint { + remote-endpoint = <&i2c5_max96749_from_edp0>; + }; + }; + }; + +}; + +&edp0_in_vp0 { + status = "disabled"; +}; + +&edp0_in_vp1 { + status = "okay"; +}; + +&edp0_in_vp2 { + status = "disabled"; +}; + +&edp1 { + force-hpd; + status = "disabled"; +}; + +&edp1_in_vp0 { + status = "disabled"; +}; + +&edp1_in_vp1 { + status = "okay"; +}; + +&edp1_in_vp2 { + status = "disabled"; +}; + +&edp2lvds_backlight0 { + pwms = <&pwm7 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl4_enable_pin>; + //enable-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&edp2lvds_backlight1 { + pwms = <&pwm11 0 25000 0>; + //pinctrl-names = "default"; + //pinctrl-0 = <&bl5_enable_pin>; + //enable-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&hdmi0 { + status = "disabled"; +}; + +&hdmi1 { + status = "disabled"; +}; + +&hdptxphy0 { + status = "okay"; +}; + +&hdptxphy1 { + status = "disabled"; +}; + +&hdptxphy_hdmi0 { + status = "disabled"; +}; + +&hdptxphy_hdmi1 { + status = "okay"; +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2m4_xfer>; + clock-frequency = <400000>; + + i2c2_max96789: i2c2-max96789@42 { + compatible = "maxim,max96789"; + reg = <0x42>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_serdes_pins>; + lock-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>; + sel-mipi; + id-serdes-bridge-split = <0x01>; + status = "okay"; + + serdes-init-sequence = [ + //Independent 11_07_17-56 Using MAX96789/91/F (GMSL-1/2) + //Disable Video pipe + 0002 0003 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 008a + //Address Value of I2C SRC_B + 0044 008c + //Address Value of I2C DST_B + 0045 008c + //Set Stream for DSI Port A && assign pipeX + 0053 0010 + //Set Stream for DSI Port B && assign pipeY + 0057 0021 + //Clock Select, X for portA, Y/Z for PortB + 0308 0076 + //Start DSI Port + 0311 0061 + //Set Port A Lane Mapping + 0332 004E + //Set Port B Lane Mapping + 0333 00E4 + //Set GMSL type + 0004 00F2 + //Number of Lanes + 0331 0033 + //Set phy_config + 0330 0006 + //Set soft_dtx_en + 031C 0098 + //Set soft_dtx + 0321 0024 + //Set soft_dty_en + 031D 0098 + //Set soft_dty_ + 0322 0024 + //Init Default + 0326 00E4 + //HSYNC_WIDTH_L HSYNC=32 + 0385 0020 + //VSYNC_WIDTH_L VSYNC=2 + 0386 0002 + //HSYNC_WIDTH_H/VSYNC_WIDTH_H + 0387 0000 + //VFP_L VFP=200 + 03A5 00C8 + //VBP_H + 03A7 0000 + //VFP_H/VBP_L VBP=8 + 03A6 0008 + //VRES_L VRES=0X02D0=720 + 03A8 00D0 + //VRES_H + 03A9 0002 + //HFP_L HFP=56 + 03AA 0038 + //HBP_H + 03AC 0003 + //HFP_H/HBP_L(4bit) HBP=56 + 03AB 0008 + //HRES_L HRES=0X0780=1920 + 03AD 0080 + //HRES_H + 03AE 0007 + //Disable FIFO/DESKEW_EN + 03A4 00C0 + //HSYNC_WIDTH_L HSYNC=40 + 0395 0028 + //VSYNC_WIDTH_L VSYNC=20 + 0396 0014 + //HSYNC_WIDTH_H/VSYNC_WIDTH_H + 0397 0000 + //VFP_L VFP=15 + 03B1 000F + //VBP_H + 03B3 0000 + //VFP_H/VBP_L VBP=10 + 03B2 000A + //VRES_L VRES=0X0438=1080 + 03B4 0038 + //VRES_H + 03B5 0004 + //HFP_L HFP=140 + 03B6 008C + //HBP_H + 03B8 0006 + //HFP_H/HBP_L HBP=100 + 03B7 0004 + //HRES_L HRES=0X0780=1920 + 03B9 0080 + //HRES_H + 03BA 0007 + //Disable FIFO/DESKEW_EN + 03B0 00C0 + //Turn on video pipe + 0002 0033 + //Enable splitter mode reset one shot + 0010 0021 + ffff f000 //0xf000 ms delay + ]; + + i2c2_max96789_pinctrl: i2c2-max96789-pinctrl { + compatible = "maxim,max96789-pinctrl"; + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c2_max96789_pinctrl_pins>; + pinctrl-1 = <&i2c2_max96789_pinctrl_pins>; + status = "okay"; + i2c2_max96789_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96789_I2C"; + function = "MAX96789_I2C"; + }; + lcd-bl-pwm { + pins = "MAX96789_MFP7"; + function = "SER_TXID4_TO_DES"; + }; + tp-int { + pins = "MAX96789_MFP8"; + function = "DES_RXID8_TO_SER"; + }; + }; + + i2c2_max96789_gpio: i2c2-max96789-gpio { + compatible = "maxim,max96789-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c2_max96789_pinctrl 0 160 20>; + }; + }; + + i2c2_max96789_bridge: i2c2-max96789-bridge { + compatible = "maxim,max96789-bridge"; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + i2c2_max96789_from_dsi0: endpoint { + remote-endpoint = <&dsi0_out_i2c2_max96789>; + }; + }; + + port@1 { + reg = <1>; + i2c2_max96789_out_i2c2_max96752: endpoint { + remote-endpoint = <&i2c2_max96752_from_i2c2_max96789>; + }; + }; + }; + }; + }; + + i2c2_max96752: i2c2-max96752@4a { + compatible = "maxim,max96752"; + reg = <0x4a>; + //reg-hw = <0x4a>; + id-serdes-panel-split = <0x01>; + link = <0x01>; + status = "okay"; + + serdes-init-sequence = [ + /*max96752 dual oLDI output*/ + 0002 0043 + 0073 0031 + 007b 0031 + 007d 0038 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 0090 + + 0050 0000 + 01ce 004e + 01ea 0004 + ]; + + i2c2_max96752_pinctrl: i2c2-max96752-pinctrl { + compatible = "maxim,max96752-pinctrl"; + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c2_max96752_panel_pins>; + pinctrl-1 = <&i2c2_max96752_panel_sleep_pins>; + status = "okay"; + + i2c2_max96752_panel_pins: panel-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_HIGH"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_HIGH"; + }; + lcd-bias-en { + pins = "MAX96752_GPIO7"; + function = "DES_TXID7_OUTPUT_HIGH"; + }; + lcd-vdd-en { + pins = "MAX96752_GPIO6"; + function = "DES_TXID6_OUTPUT_HIGH"; + }; + tp-int { + pins = "MAX96752_GPIO2"; + function = "DES_TXID8_TO_SER"; + }; + 40ms-delay { + pins = "MAX96752_GPIO15"; + function = "DELAY_40MS"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_HIGH"; + }; + lcd-bl-pwm { + pins = "MAX96752_GPIO4"; + function = "SER_TO_DES_RXID4"; + }; + }; + + i2c2_max96752_panel_sleep_pins: panel-sleep-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_LOW"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_LOW"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_LOW"; + }; + }; + + i2c2_max96752_gpio: i2c2-max96752-gpio { + compatible = "maxim,max96752-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c2_max96752_pinctrl 0 180 15>; + }; + }; + + i2c2_max96752_panel: i2c2-max96752-panel { + compatible = "maxim,max96752-panel"; + status = "okay"; + + backlight = <&backlight>; + panel-size= <346 194>; + + panel-timing { + clock-frequency = <115000000>; + hactive = <1920>; + vactive = <720>; + hfront-porch = <56>; + hsync-len = <32>; + hback-porch = <56>; + vfront-porch = <200>; + vsync-len = <2>; + vback-porch = <8>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + i2c2_max96752_from_i2c2_max96789: endpoint { + remote-endpoint = <&i2c2_max96789_out_i2c2_max96752>; + }; + }; + }; + }; + }; + + himax@45 { + compatible = "himax,hxcommon"; + reg = <0x45>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&touch_gpio_dsi0>; + pinctrl-1 = <&touch_gpio_dsi0>; + himax,location = "himax-touch-dsi0"; + himax,irq-gpio = <&gpio1 RK_PB0 IRQ_TYPE_EDGE_FALLING>; + himax,rst-gpio = <&i2c2_max96752_gpio 5 GPIO_ACTIVE_LOW>; + himax,panel-coords = <0 1920 0 720>; + himax,display-coords = <0 1920 0 720>; + status = "okay"; + }; +}; + +&i2c4 { + pinctrl-0 = <&i2c4m2_xfer>; + clock-frequency = <400000>; + status = "okay"; + + i2c4_max96749: i2c4-max96749@42 { + compatible = "maxim,max96749"; + reg = <0x42>; + dual-link; + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_serdes_pins>; + lock-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + //Set TX_STR_SEL_X to 0 + 00A3 0000 + //Set TX_STR_SEL_Y to 1 + 00A7 0001 + //Set TX_STR_SEL_Z to 2 + 00AB 0002 + //Set TX_STR_SEL_U to 3 + 00AF 0003 + + //INFOFR TX_SRC_ID0:1:2 + 00C2 0001 + //CC TX_SRC_ID0:1:2 + 00D2 0002 + //IIC X TX_SRC_ID0:1:2 + 00EA 0001 + //IIC Y TX_SRC_ID0:1:2 + 00F2 0002 + + 00B2 0003 + 00BA 0003 + 00CA 0003 + 00C2 0003 + 00D2 0003 + 00DA 0003 + 00E2 0003 + 00EA 0003 + 00F2 0003 + //Set X_VID_LINK_SEL to 0 + 0100 0061 + //Set Y_VID_LINK_SEL to 1 + 0110 0063 + //Set Z_VID_LINK_SEL to 0 + 0120 0061 + //Set U_VID_LINK_SEL to 1 + 0130 0063 + + //ASYM_WR_B_MUX_Y + 05CE 003F + //ASYM_WAIT_LINE_FOR_READ_X + 04D1 00F8 + //ASYM_WAIT_LINE_FOR_READ_Y + 05D1 00F8 + //ASYM_VID_EN_W_VS_X + 04CF 00BF + //ASYM_VID_EN_W_VS_Y + 05CF 00BF + //ASYM_FR2FR_CTRL_EN_X + 04D1 00FC + //ASYM_FR2FR_CTRL_EN_Y + 05D1 00FC + //ALT_VTG_EN_X + 04CE 002F + //AUTO_VTG_CFG_X + 04CE 000F + //ALT_VTG_EN_Y + 05CE 0027 + //AUTO_VTG_CFG_Y + 05CE 0007 + //X_M_l + 04C0 0000 + //X_M_m + 04C1 00E1 + //X_M_h + 04C2 004B + //X_N_l + 04C3 00C8 + //X_N_m + 04C4 0008 + //X_N_h + 04C5 0007 + //X_X_OFFSET_l + 04C6 0000 + //X_X_OFFSET_h + 04C7 0000 + //X_X_MAX_l + 04C8 0000 + //X_X_MAX_h + 04C9 000A + //X_Y_MAX_l + 04CA 0040 + //X_Y_MAX_h + 04CB 0006 + //X_vs_dly_l + 04D8 00E0 + //X_vs_dly_m + 04D9 009E + //X_vs_dly_h + 04DA 0049 + //X_vs_high_l + 04DB 00B0 + //X_vs_high_m + 04DC 0022 + //X_vs_high_h + 04DD 0000 + //X_vs_low_l + 04DE 0070 + //X_vs_low_m + 04DF 001F + //X_vs_low_h + 04E0 0002 + //X_hs_dly_l + 04E1 0000 + //X_hs_dly_m + 04E2 0000 + //X_hs_dly_h + 04E3 0000 + //X_hs_high_l + 04E4 0020 + //X_hs_high_h + 04E5 0000 + //X_hs_low_l + 04E6 0070 + //X_hs_low_h + 04E7 000B + //X_hs_cnt_l + 04E8 0090 + //X_hs_cnt_h + 04E9 0006 + //X_hs_llow_l + 04EA 0000 + //X_hs_llow_m + 04EB 0000 + //X_hs_llow_h + 04EC 0000 + //X_de_dly_l + 04ED 0060 + //X_de_dly_m + 04EE 0001 + //X_de_dly_h + 04EF 0000 + //X_de_high_l + 04F0 0000 + //X_de_high_h + 04F1 000A + //X_de_low_l + 04F2 0090 + //X_de_low_h + 04F3 0001 + //X_de_cnt_l + 04F4 0040 + //X_de_cnt_h + 04F5 0006 + //X_de_llow_l + 04F6 00A0 + //X_de_llow_m + 04F7 009B + //X_de_llow_h + 04F8 0003 + //Y_M + 05C0 0000 + //Y_M_h + 05C1 00E1 + //Y_M_h + 05C2 004B + //Y_N_l + 05C3 00C8 + //Y_N_m + 05C4 0008 + //Y_N_h + 05C5 0007 + //Y_X_OFFSET_l + 05C6 0000 + //Y_X_OFFSET_h + 05C7 000A + //Y_X_MAX_l + 05C8 0000 + //Y_X_MAX_h + 05C9 0014 + //Y_Y_MAX_l + 05CA 0040 + //Y_Y_MAX_h + 05CB 0006 + //Y_vs_dly_l + 05D8 00E0 + //Y_vs_dly_m + 05D9 009E + //Y_vs_dly_h + 05DA 0049 + //Y_vs_high_l + 05DB 00B0 + //Y_vs_high_m + 05DC 0022 + //Y_vs_high_h + 05DD 0000 + //Y_vs_low_l + 05DE 0070 + //Y_vs_low_m + 05DF 001F + //Y_vs_low_h + 05E0 0002 + //Y_hs_dly_l + 05E1 0000 + //Y_hs_dly_m + 05E2 0000 + //Y_hs_dly_h + 05E3 0000 + //Y_hs_high_l + 05E4 0020 + //Y_hs_high_h + 05E5 0000 + //Y_hs_low_l + 05E6 0070 + //Y_hs_low_h + 05E7 000B + //Y_hs_cnt_l + 05E8 0090 + //Y_hs_cnt_h + 05E9 0006 + //Y_hs_llow_l + 05EA 0000 + //Y_hs_llow_m + 05EB 0000 + //Y_hs_llow_h + 05EC 0000 + //Y_de_dly_l + 05ED 0060 + //Y_de_dly_m + 05EE 0001 + //Y_de_dly_h + 05EF 0000 + //Y_de_high_l + 05F0 0000 + //Y_de_high_h + 05F1 000A + //Y_de_low_l + 05F2 0090 + //Y_de_low_h + 05F3 0001 + //Y_de_cnt_l + 05F4 0040 + //Y_de_cnt_h + 05F5 0006 + //Y_de_llow_l + 05F6 00A0 + //Y_de_llow_m + 05F7 009B + //Y_de_llow_h + 05F8 0003 + //X_LUT_TEMPLATE_SEL + 04CD 0014 + //Y_LUT_TEMPLATE_SEL + 05CD 0014 + + //Turn off video + 6420 0010 + //Disable MST mode + 7019 0000 + //7019 0001 //Set MST_FUNCTION_ENABLE to 1 + //7904 0001 // Set MST_PAYLOAD_ID_0 to 01 + //7908 0002 // Set MST_PAYLOAD_ID_1 to 01 + //Disable MST_VS0_DTG_ENABLE + 7A14 0000 + //Disable LINK_ENABLE + 7000 0000 + //Reset DPRX core (VIDEO_INPUT_RESET) + 7054 0001 + ffff f000 //delay 0xf000 us + //Set MAX_LINK_RATE to 2.7Gb/s + 7074 000A + //Set MAX_LINK_COUNT to 4 + 7070 0004 + //Set ASYM_CTRL_PROP_GAIN to 000A + 04D0 000A + 05D0 000A + //Set AEQ time to 16ms + 6064 0000 + 6065 0000 + 6164 0000 + 6165 0000 + 6264 0000 + 6265 0000 + 6364 0000 + 6365 0000 + //Enable LINK_ENABLE + 7000 0001 + //delay 1000 + //Disable MSA reset + 7A18 0005 + //Adjust VS0_DMA_HSYNC + 7A28 00FF + 7A2A 00FF + //Adjust VS0_DMA_VSYNC + 7A24 00FF + 7A27 000F + //Enable MST_VS0_DTG_ENABLE + 7A14 0001 + //set EDP Video Control + 6421 0001 + //Turn on video + 6420 0013 + //delay 100 + //Turn off video + 6420 0010 + //delay 100 + //Turn on video + 6420 0013 + 6421 0003 + ]; + + i2c4_max96749_pinctrl: i2c4-max96749-pinctrl { + compatible = "maxim,max96749-pinctrl"; + pinctrl-names = "init", "sleep"; + pinctrl-0 = <&i2c4_max96749_pinctrl_pins>; + pinctrl-1 = <&i2c4_max96749_pinctrl_pins>; + status = "okay"; + + i2c4_max96749_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96749_I2C"; + function = "MAX96749_I2C"; + }; + tp-int { + pins = "MAX96749_MFP1"; + function = "DES_RXID1_TO_SER_LINKA"; + }; + }; + + i2c4_max96749_gpio: i2c4-max96749-gpio { + compatible = "maxim,max96749-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c4_max96749_pinctrl 0 200 25>; + }; + }; + + i2c4_max96749_bridge: i2c4-max96749-bridge { + compatible = "maxim,max96749-bridge"; + status = "okay"; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + i2c4_max96749_from_dp0: endpoint { + remote-endpoint = <&dp0_out_i2c4_max96749>; + }; + }; + port@1 { + reg = <1>; + i2c4_max96749_out_i2c4_max96772: endpoint { + remote-endpoint = <&i2c4_max96772_from_i2c4_max96749>; + }; + }; + }; + }; + + i2c4_max96772: i2c4-max96772@48 { + compatible = "maxim,max96772"; + reg = <0x48>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + + ]; + + i2c4_max96772_pinctrl: i2c4-max96772-pinctrl { + compatible = "maxim,max96772-pinctrl"; + status = "okay"; + + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c4_max96772_panel_pins>; + pinctrl-1 = <&i2c4_max96772_panel_pins>; + + i2c4_max96772_panel_pins: panel-pins { + tp-int { + pins = "MAX96772_GPIO10"; + function = "DES_TXID1_TO_SER"; + }; + }; + + i2c4_max96772_gpio: i2c4-max96772-gpio { + compatible = "maxim,max96772-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c4_max96772_pinctrl 0 230 15>; + }; + }; + + i2c4_max96772_panel: i2c4-max96772-panel { + compatible = "maxim,max96772-panel"; + status = "okay"; + + backlight = <&dp2lvds_backlight0>; + panel-size= <324 202>; + rate-count-ssc= <10 4 0>; + + panel-timing { + clock-frequency = <298400000>; + hactive = <2560>; + vactive = <1600>; + hfront-porch = <48>; + hsync-len = <32>; + hback-porch = <320>; + vfront-porch = <30>; + vsync-len = <3>; + vback-porch = <47>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + port { + i2c4_max96772_from_i2c4_max96749: endpoint { + remote-endpoint = <&i2c4_max96749_out_i2c4_max96772>; + }; + }; + }; + }; + + i2c4_r7f701_pwm: i2c4-r7f701-pwm@77 { + compatible = "r7f701-pwm"; + #pwm-cells = <3>; + reg = <0x77>; + status = "okay"; + }; + + i2c4_cyttsp7: i2c4-cyttsp7@24 { + compatible = "cy,cyttsp7_i2c_adapter"; + reg = <0x24>; + status = "okay"; + + cy,core { + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio_dp0>; + cy,irq_gpio = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>; + cy,rst_gpio = <&i2c4_max96772_gpio 7 GPIO_ACTIVE_HIGH>; + + cy,max_xfer_len = <0x100>; + + /* CY_CORE_FLAG_WAKE_ON_GESTURE */ + /* cy,flags = <1>; */ + /* CY_CORE_EWG_TAP_TAP | CY_CORE_EWG_TWO_FINGER_SLIDE */ + /* cy,easy_wakeup_gesture = <3>; */ + cy,btn_keys = <172 /* KEY_HOMEPAGE */ + /* previously was KEY_HOME, new Android versions use KEY_HOMEPAGE */ + 139 /* KEY_MENU */ + 158 /* KEY_BACK */ + 217 /* KEY_SEARCH */ + 114 /* KEY_VOLUMEDOWN */ + 115 /* KEY_VOLUMEUP */ + 212 /* KEY_CAMERA */ + 116>; /* KEY_POWER */ + cy,btn_keys-tag = <0>; + + cy,mt { + cy,inp_dev_name = "cyttsp7-mt-dp0"; + /* CY_MT_FLAG_FLIP | CY_MT_FLAG_INV_X | CY_MT_FLAG_INV_Y */ + cy,flags = <0x20>; + cy,abs = + /* ABS_MT_POSITION_X, CY_ABS_MIN_X, CY_ABS_MAX_X, 0, 0 */ + < + 0x35 0 2560 0 0 + /* ABS_MT_POSITION_Y, CY_ABS_MIN_Y, CY_ABS_MAX_Y, 0, 0 */ + 0x36 0 1600 0 0 + /* ABS_MT_PRESSURE, CY_ABS_MIN_P, CY_ABS_MAX_P, 0, 0 */ + 0x3a 0 255 0 0 + /* CY_IGNORE_VALUE, CY_ABS_MIN_W, CY_ABS_MAX_W, 0, 0 */ + 0xffff 0 255 0 0 + /* ABS_MT_TRACKING_ID, CY_ABS_MIN_T, CY_ABS_MAX_T, 0, 0 */ + 0x39 0 15 0 0 + /* ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0 */ + 0x30 0 255 0 0 + /* ABS_MT_TOUCH_MINOR, 0, 255, 0, 0 */ + 0x31 0 255 0 0 + /* ABS_MT_ORIENTATION, -127, 127, 0, 0 */ + 0x34 0xffffff81 127 0 0 + /* ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0 */ + 0x37 0 1 0 0 + /* ABS_DISTANCE, 0, 255, 0, 0 */ + 0x19 0 255 0 0 + /* SRI:ABS_MT_DISTANCE, 0,MAX, 0, 0 */ + 0x3b 0 255 0 0>; + + cy,vkeys_x = <2560>; + cy,vkeys_y = <1600>; + + cy,virtual_keys = /* KeyCode CenterX CenterY Width Height */ + /* KEY_BACK */ + <158 1360 90 160 180 + /* KEY_MENU */ + 139 1360 270 160 180 + /* KEY_HOMEPAGE */ + 172 1360 450 160 180 + /* KEY SEARCH */ + 217 1360 630 160 180>; + }; + + cy,btn { + cy,inp_dev_name = "cyttsp7-btn-dp0"; + }; + + cy,proximity { + cy,inp_dev_name = "cyttsp7-proximity-dp0"; + cy,abs = + /* ABS_DISTANCE, CY_PROXIMITY_MIN_VAL, CY_PROXIMITY_MAX_VAL, 0, 0 */ + <0x19 0 1 0 0>; + }; + }; + }; +}; + +&i2c5 { + clock-frequency = <400000>; + status = "okay"; + + i2c5_max96749: i2c5-max96749@42 { + compatible = "maxim,max96749"; + reg = <0x42>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_serdes_pins>; + lock-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + id-serdes-bridge-split = <0x02>; + status = "okay"; + + serdes-init-sequence = [ + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 008a + //Address Value of I2C SRC_B + 0044 008c + //Address Value of I2C DST_B + 0045 008c + //Set TX_STR_SEL_X to 0 + 00A3 0000 + //Set TX_STR_SEL_Y to 1 + 00A7 0001 + //Set TX_STR_SEL_Z to 2 + 00AB 0002 + //Set TX_STR_SEL_U to 3 + 00AF 0003 + + //INFOFR TX_SRC_ID0:1:2 + 00C2 0001 + //CC TX_SRC_ID0:1:2 + 00D2 0002 + //IIC X TX_SRC_ID0:1:2 + 00EA 0001 + //IIC Y TX_SRC_ID0:1:2 + 00F2 0002 + + 00B2 0003 + 00BA 0003 + 00CA 0003 + 00C2 0003 + 00D2 0003 + 00DA 0003 + 00E2 0003 + 00EA 0003 + 00F2 0003 + //Set X_VID_LINK_SEL to 0 + 0100 0061 + //Set Y_VID_LINK_SEL to 1 + 0110 0063 + //Set Z_VID_LINK_SEL to 0 + 0120 0061 + //Set U_VID_LINK_SEL to 1 + 0130 0063 + //ASYM_WR_B_MUX_Y + 05CE 0037 + //ASYM_WAIT_LINE_FOR_READ_X + 04D1 00F8 + //ASYM_WAIT_LINE_FOR_READ_Y + 05D1 00F8 + //ASYM_VID_EN_W_VS_X + 04CF 00BF + //ASYM_VID_EN_W_VS_Y + 05CF 00BF + //ASYM_FR2FR_CTRL_EN_X + 04D1 00FC + //ASYM_FR2FR_CTRL_EN_Y + 05D1 00FC + //ALT_VTG_EN_X + 04CE 002F + //AUTO_VTG_CFG_X + 04CE 000F + //ALT_VTG_EN_Y + 05CE 0027 + //AUTO_VTG_CFG_Y + 05CE 0007 + //X_M_l + 04C0 00F8 + //X_M_m + 04C1 00C3 + //X_M_h + 04C2 0025 + //X_N_l + 04C3 00C8 + //X_N_m + 04C4 0008 + //X_N_h + 04C5 0007 + //X_X_OFFSET_l + 04C6 0000 + //X_X_OFFSET_h + 04C7 0000 + //X_X_MAX_l + 04C8 0080 + //X_X_MAX_h + 04C9 0007 + //X_Y_MAX_l + 04CA 0038 + //X_Y_MAX_h + 04CB 0004 + //Y_M + 05C0 00F8 + //Y_M_h + 05C1 00C3 + //Y_M_h + 05C2 0025 + //Y_N_l + 05C3 00C8 + //Y_N_m + 05C4 0008 + //Y_N_h + 05C5 0007 + //Y_X_OFFSET_l + 05C6 0080 + //Y_X_OFFSET_h + 05C7 0007 + //Y_X_MAX_l + 05C8 0000 + //Y_X_MAX_h + 05C9 000F + //Y_Y_MAX_l + 05CA 0038 + //Y_Y_MAX_h + 05CB 0004 + //X_vs_dly_l + 04D8 0028 + //X_vs_dly_m + 04D9 00C2 + //X_vs_dly_h + 04DA 0024 + //X_vs_high_l + 04DB 00E0 + //X_vs_high_m + 04DC 00AB + //X_vs_high_h + 04DD 0000 + //X_vs_low_l + 04DE 00F0 + //X_vs_low_m + 04DF 0055 + //X_vs_low_h + 04E0 0000 + //X_hs_dly_l + 04E1 0000 + //X_hs_dly_m + 04E2 0000 + //X_hs_dly_h + 04E3 0000 + //X_hs_high_l + 04E4 0028 + //X_hs_high_h + 04E5 0000 + //X_hs_low_l + 04E6 0070 + //X_hs_low_h + 04E7 0008 + //X_hs_cnt_l + 04E8 0065 + //X_hs_cnt_h + 04E9 0004 + //X_hs_llow_l + 04EA 0000 + //X_hs_llow_m + 04EB 0000 + //X_hs_llow_h + 04EC 0000 + //X_de_dly_l + 04ED 008C + //X_de_dly_m + 04EE 0000 + //X_de_dly_h + 04EF 0000 + //X_de_high_l + 04F0 0080 + //X_de_high_h + 04F1 0007 + //X_de_low_l + 04F2 0018 + //X_de_low_h + 04F3 0001 + //X_de_cnt_l + 04F4 0038 + //X_de_cnt_h + 04F5 0004 + //X_de_llow_l + 04F6 002C + //X_de_llow_m + 04F7 0082 + //X_de_llow_h + 04F8 0001 + + //Y_vs_dly_l + 05D8 0028 + //Y_vs_dly_m + 05D9 00C2 + //Y_vs_dly_h + 05DA 0024 + //Y_vs_high_l + 05DB 00E0 + //Y_vs_high_m + 05DC 00AB + //Y_vs_high_h + 05DD 0000 + //Y_vs_low_l + 05DE 00F0 + //Y_vs_low_m + 05DF 0055 + //Y_vs_low_h + 05E0 0000 + //Y_hs_dly_l + 05E1 0000 + //Y_hs_dly_m + 05E2 0000 + //Y_hs_dly_h + 05E3 0000 + //Y_hs_high_l + 05E4 0028 + //Y_hs_high_h + 05E5 0000 + //Y_hs_low_l + 05E6 0070 + //Y_hs_low_h + 05E7 0008 + //Y_hs_cnt_l + 05E8 0065 + //Y_hs_cnt_h + 05E9 0004 + //Y_hs_llow_l + 05EA 0000 + //Y_hs_llow_m + 05EB 0000 + //Y_hs_llow_h + 05EC 0000 + //Y_de_dly_l + 05ED 008C + //Y_de_dly_m + 05EE 0000 + //Y_de_dly_h + 05EF 0000 + //Y_de_high_l + 05F0 0080 + //Y_de_high_h + 05F1 0007 + //Y_de_low_l + 05F2 0018 + //Y_de_low_h + 05F3 0001 + //Y_de_cnt_l + 05F4 0038 + //Y_de_cnt_h + 05F5 0004 + //Y_de_llow_l + 05F6 002C + //Y_de_llow_m + 05F7 0082 + //Y_de_llow_h + 05F8 0001 + //X_LUT_TEMPLATE_SEL + 04CD 0014 + //Y_LUT_TEMPLATE_SEL + 05CD 0014 + //Turn off video + 6420 0010 + //Disable MST mode + 7019 0000 + //7019 0001 //Set MST_FUNCTION_ENABLE to 1 + //7904 0001 // Set MST_PAYLOAD_ID_0 to 01 + //7908 0002 // Set MST_PAYLOAD_ID_1 to 01 + //Disable MST_VS0_DTG_ENABLE + 7A14 0000 + //Disable LINK_ENABLE + 7000 0000 + //Reset DPRX core (VIDEO_INPUT_RESET) + 7054 0001 + ffff f000 //delay 0xf000 us + //Set MAX_LINK_RATE to 2.7Gb/s + 7074 000A + //Set MAX_LINK_COUNT to 4 + 7070 0004 + //Set ASYM_CTRL_PROP_GAIN to 000A + 04D0 000A + 05D0 000A + //Set AEQ time to 16ms + 6064 0000 + 6065 0000 + 6164 0000 + 6165 0000 + 6264 0000 + 6265 0000 + 6364 0000 + 6365 0000 + //Enable LINK_ENABLE + 7000 0001 + //delay 1000 + //Disable MSA reset + 7A18 0005 + //Adjust VS0_DMA_HSYNC + 7A28 00FF + 7A2A 00FF + //Adjust VS0_DMA_VSYNC + 7A24 00FF + 7A27 000F + //Enable MST_VS0_DTG_ENABLE + 7A14 0001 + //set EDP Video Control + 6421 0001 + //Turn on video + 6420 0013 + //delay 100 + //Turn off video + 6420 0010 + //delay 100 + //Turn on video + 6420 0013 + 6421 0003 + ]; + + i2c5_max96749_pinctrl: i2c5-max96749-pinctrl { + compatible = "maxim,max96749-pinctrl"; + pinctrl-names = "init", "sleep"; + pinctrl-0 = <&i2c5_max96749_pinctrl_pins>; + pinctrl-1 = <&i2c5_max96749_pinctrl_pins>; + status = "okay"; + + i2c5_max96749_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96749_I2C"; + function = "MAX96749_I2C"; + }; + lcd-bl-pwm { + pins = "MAX96749_MFP0"; + function = "SER_TXID4_TO_DES_LINKA"; + }; + tp-int { + pins = "MAX96749_MFP1"; + function = "DES_RXID1_TO_SER_LINKA"; + }; + }; + + i2c5_max96749_gpio: i2c5-max96749-gpio { + compatible = "maxim,max96749-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c5_max96749_pinctrl 0 250 25>; + }; + }; + + i2c5_max96749_bridge: i2c5-max96749-bridge { + compatible = "maxim,max96749-bridge"; + status = "okay"; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + i2c5_max96749_from_edp0: endpoint { + remote-endpoint = <&edp0_out_i2c5_max96749>; + }; + }; + + port@1 { + reg = <1>; + + i2c5_max96749_out_i2c5_max96752: endpoint { + remote-endpoint = <&i2c5_max96752_from_i2c5_max96749>; + }; + }; + }; + }; + + i2c5_max96752: i2c5-max96752@4a { + compatible = "maxim,max96752"; + reg = <0x4a>; + #address-cells = <1>; + #size-cells = <0>; + id-serdes-panel-split = <0x02>; + link = <0x01>; + status = "okay"; + + serdes-init-sequence = [ + /*max96752 dual oLDI output*/ + 0002 0043 + 0073 0031 + 007b 0031 + 007d 0038 + //Address Value of I2C SRC_A + 0042 008a + //Address Value of I2C DST_A + 0043 0090 + + 0050 0000 + 01ce 004e + 01ea 0004 + ]; + + i2c5_max96752_pinctrl: i2c5-max96752-pinctrl { + compatible = "maxim,max96752-pinctrl"; + status = "okay"; + + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c5_max96752_panel_pins>; + pinctrl-1 = <&i2c5_max96752_panel_sleep_pins>; + + i2c5_max96752_panel_pins: panel-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_HIGH"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_HIGH"; + }; + tp-int { + pins = "MAX96752_GPIO2"; + function = "DES_TXID1_TO_SER"; + }; + 40ms-delay { + pins = "MAX96752_GPIO15"; + function = "DELAY_40MS"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_HIGH"; + }; + lcd-bl-pwm { + pins = "MAX96752_GPIO4"; + function = "SER_TO_DES_RXID4"; + }; + lcd_bias_en { + pins = "MAX96752_GPIO7"; + function = "DES_TXID7_OUTPUT_HIGH"; + }; + lcd_vdd_en { + pins = "MAX96752_GPIO6"; + function = "DES_TXID6_OUTPUT_HIGH"; + }; + }; + + i2c5_max96752_panel_sleep_pins: panel-sleep-pins { + lcd-rst-pin { + pins = "MAX96752_GPIO10"; + function = "DES_TXID10_OUTPUT_LOW"; + }; + tp-rst { + pins = "MAX96752_GPIO5"; + function = "DES_TXID5_OUTPUT_LOW"; + }; + lcd-pwr-on { + pins = "MAX96752_GPIO3"; + function = "DES_TXID3_OUTPUT_LOW"; + }; + }; + + i2c5_max96752_gpio: i2c5-max96752-gpio { + compatible = "maxim,max96752-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c5_max96752_pinctrl 0 280 15>; + }; + }; + + i2c5_max96752_panel: i2c5-max96752-panel { + compatible = "maxim,max96752-panel"; + status = "okay"; + + backlight = <&edp2lvds_backlight0>; + panel-size= <346 194>; + + panel-timing { + clock-frequency = <148500000>; + hactive = <1920>; + vactive = <1080>; + hfront-porch = <140>; + hsync-len = <40>; + hback-porch = <100>; + vfront-porch = <15>; + vsync-len = <20>; + vback-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + port { + i2c5_max96752_from_i2c5_max96749: endpoint { + remote-endpoint = <&i2c5_max96749_out_i2c5_max96752>; + }; + }; + }; + }; + + ilitek@41 { + compatible = "ilitek,ili251x"; + reg = <0x41>; + interrupt-parent = <&gpio1>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio_edp0>; + //reset-gpio = <&gpio0 RK_PD1 GPIO_ACTIVE_LOW>; + ilitek,name = "ilitek_i2c"; + status = "okay"; + }; +}; + +&i2c8 { + pinctrl-0 = <&i2c8m2_xfer>; + clock-frequency = <400000>; + status = "okay"; + + i2c8_max96749: i2c8-max96749@42 { + compatible = "maxim,max96749"; + reg = <0x42>; + dual-link; + pinctrl-names = "default"; + pinctrl-0 = <&i2c8_serdes_pins>; + lock-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + //Set TX_STR_SEL_X to 0 + 00A3 0000 + //Set TX_STR_SEL_Y to 1 + 00A7 0001 + //Set TX_STR_SEL_Z to 2 + 00AB 0002 + //Set TX_STR_SEL_U to 3 + 00AF 0003 + + //INFOFR TX_SRC_ID0:1:2 + 00C2 0001 + //CC TX_SRC_ID0:1:2 + 00D2 0002 + //IIC X TX_SRC_ID0:1:2 + 00EA 0001 + //IIC Y TX_SRC_ID0:1:2 + 00F2 0002 + + 00B2 0003 + 00BA 0003 + 00CA 0003 + 00C2 0003 + 00D2 0003 + 00DA 0003 + 00E2 0003 + 00EA 0003 + 00F2 0003 + //Set X_VID_LINK_SEL to 0 + 0100 0061 + //Set Y_VID_LINK_SEL to 1 + 0110 0063 + //Set Z_VID_LINK_SEL to 0 + 0120 0061 + //Set U_VID_LINK_SEL to 1 + 0130 0063 + + //ASYM_WR_B_MUX_Y + 05CE 0037 + //ASYM_WAIT_LINE_FOR_READ_X + 04D1 00F8 + //ASYM_WAIT_LINE_FOR_READ_Y + 05D1 00F8 + //ASYM_VID_EN_W_VS_X + 04CF 00BF + //ASYM_VID_EN_W_VS_Y + 05CF 00BF + //ASYM_FR2FR_CTRL_EN_X + 04D1 00FC + //ASYM_FR2FR_CTRL_EN_Y + 05D1 00FC + //ALT_VTG_EN_X + 04CE 002F + //AUTO_VTG_CFG_X + 04CE 000F + //ALT_VTG_EN_Y + 05CE 0027 + //AUTO_VTG_CFG_Y + 05CE 0007 + //X_M_l + 04C0 0000 + //X_M_m + 04C1 00E1 + //X_M_h + 04C2 004B + //X_N_l + 04C3 00C8 + //X_N_m + 04C4 0008 + //X_N_h + 04C5 0007 + //X_X_OFFSET_l + 04C6 0000 + //X_X_OFFSET_h + 04C7 0000 + //X_X_MAX_l + 04C8 0000 + //X_X_MAX_h + 04C9 000A + //X_Y_MAX_l + 04CA 0040 + //X_Y_MAX_h + 04CB 0006 + //X_vs_dly_l + 04D8 00E0 + //X_vs_dly_m + 04D9 009E + //X_vs_dly_h + 04DA 0049 + //X_vs_high_l + 04DB 00B0 + //X_vs_high_m + 04DC 0022 + //X_vs_high_h + 04DD 0000 + //X_vs_low_l + 04DE 0070 + //X_vs_low_m + 04DF 001F + //X_vs_low_h + 04E0 0002 + //X_hs_dly_l + 04E1 0000 + //X_hs_dly_m + 04E2 0000 + //X_hs_dly_h + 04E3 0000 + //X_hs_high_l + 04E4 0020 + //X_hs_high_h + 04E5 0000 + //X_hs_low_l + 04E6 0070 + //X_hs_low_h + 04E7 000B + //X_hs_cnt_l + 04E8 0090 + //X_hs_cnt_h + 04E9 0006 + //X_hs_llow_l + 04EA 0000 + //X_hs_llow_m + 04EB 0000 + //X_hs_llow_h + 04EC 0000 + //X_de_dly_l + 04ED 0060 + //X_de_dly_m + 04EE 0001 + //X_de_dly_h + 04EF 0000 + //X_de_high_l + 04F0 0000 + //X_de_high_h + 04F1 000A + //X_de_low_l + 04F2 0090 + //X_de_low_h + 04F3 0001 + //X_de_cnt_l + 04F4 0040 + //X_de_cnt_h + 04F5 0006 + //X_de_llow_l + 04F6 00A0 + //X_de_llow_m + 04F7 009B + //X_de_llow_h + 04F8 0003 + //Y_M + 05C0 0000 + //Y_M_h + 05C1 00E1 + //Y_M_h + 05C2 004B + //Y_N_l + 05C3 00C8 + //Y_N_m + 05C4 0008 + //Y_N_h + 05C5 0007 + //Y_X_OFFSET_l + 05C6 0000 + //Y_X_OFFSET_h + 05C7 000A + //Y_X_MAX_l + 05C8 0000 + //Y_X_MAX_h + 05C9 0014 + //Y_Y_MAX_l + 05CA 0040 + //Y_Y_MAX_h + 05CB 0006 + //Y_vs_dly_l + 05D8 00E0 + //Y_vs_dly_m + 05D9 009E + //Y_vs_dly_h + 05DA 0049 + //Y_vs_high_l + 05DB 00B0 + //Y_vs_high_m + 05DC 0022 + //Y_vs_high_h + 05DD 0000 + //Y_vs_low_l + 05DE 0070 + //Y_vs_low_m + 05DF 001F + //Y_vs_low_h + 05E0 0002 + //Y_hs_dly_l + 05E1 0000 + //Y_hs_dly_m + 05E2 0000 + //Y_hs_dly_h + 05E3 0000 + //Y_hs_high_l + 05E4 0020 + //Y_hs_high_h + 05E5 0000 + //Y_hs_low_l + 05E6 0070 + //Y_hs_low_h + 05E7 000B + //Y_hs_cnt_l + 05E8 0090 + //Y_hs_cnt_h + 05E9 0006 + //Y_hs_llow_l + 05EA 0000 + //Y_hs_llow_m + 05EB 0000 + //Y_hs_llow_h + 05EC 0000 + //Y_de_dly_l + 05ED 0060 + //Y_de_dly_m + 05EE 0001 + //Y_de_dly_h + 05EF 0000 + //Y_de_high_l + 05F0 0000 + //Y_de_high_h + 05F1 000A + //Y_de_low_l + 05F2 0090 + //Y_de_low_h + 05F3 0001 + //Y_de_cnt_l + 05F4 0040 + //Y_de_cnt_h + 05F5 0006 + //Y_de_llow_l + 05F6 00A0 + //Y_de_llow_m + 05F7 009B + //Y_de_llow_h + 05F8 0003 + //X_LUT_TEMPLATE_SEL + 04CD 0014 + //Y_LUT_TEMPLATE_SEL + 05CD 0014 + + //Turn off video + 6420 0010 + //Disable MST mode + 7019 0000 + //7019 0001 //Set MST_FUNCTION_ENABLE to 1 + //7904 0001 // Set MST_PAYLOAD_ID_0 to 01 + //7908 0002 // Set MST_PAYLOAD_ID_1 to 01 + //Disable MST_VS0_DTG_ENABLE + 7A14 0000 + //Disable LINK_ENABLE + 7000 0000 + //Reset DPRX core (VIDEO_INPUT_RESET) + 7054 0001 + ffff f000 //delay 0xf000 us + //Set MAX_LINK_RATE to 2.7Gb/s + 7074 000A + //Set MAX_LINK_COUNT to 4 + 7070 0004 + //Set ASYM_CTRL_PROP_GAIN to 000A + 04D0 000A + 05D0 000A + //Set AEQ time to 16ms + 6064 0000 + 6065 0000 + 6164 0000 + 6165 0000 + 6264 0000 + 6265 0000 + 6364 0000 + 6365 0000 + //Enable LINK_ENABLE + 7000 0001 + //delay 1000 + //Disable MSA reset + 7A18 0005 + //Adjust VS0_DMA_HSYNC + 7A28 00FF + 7A2A 00FF + //Adjust VS0_DMA_VSYNC + 7A24 00FF + 7A27 000F + //Enable MST_VS0_DTG_ENABLE + 7A14 0001 + //set EDP Video Control + 6421 0001 + //Turn on video + 6420 0013 + //delay 100 + //Turn off video + 6420 0010 + //delay 100 + //Turn on video + 6420 0013 + 6421 0003 + ]; + + i2c8_max96749_pinctrl: i2c8-max96749-pinctrl { + compatible = "maxim,max96749-pinctrl"; + pinctrl-names = "init", "sleep"; + pinctrl-0 = <&i2c8_max96749_pinctrl_pins>; + pinctrl-1 = <&i2c8_max96749_pinctrl_pins>; + status = "okay"; + + i2c8_max96749_pinctrl_pins: pinctrl-pins { + i2c { + groups = "MAX96749_I2C"; + function = "MAX96749_I2C"; + }; + tp-int { + pins = "MAX96749_MFP1"; + function = "DES_RXID1_TO_SER_LINKA"; + }; + }; + + i2c8_max96749_gpio: i2c8-max96749-gpio { + compatible = "maxim,max96749-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c8_max96749_pinctrl 0 300 25>; + }; + }; + + i2c8_max96749_bridge: i2c8-max96749-bridge { + compatible = "maxim,max96749-bridge"; + status = "okay"; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + i2c8_max96749_from_dp1: endpoint { + remote-endpoint = <&dp1_out_i2c8_max96749>; + }; + }; + + port@1 { + reg = <1>; + + i2c8_max96749_out_i2c8_max96772: endpoint { + remote-endpoint = <&i2c8_max96772_from_i2c8_max96749>; + }; + }; + }; + }; + + i2c8_max96772: i2c8-max96772@48 { + compatible = "maxim,max96772"; + reg = <0x48>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + serdes-init-sequence = [ + + ]; + + i2c8_max96772_pinctrl: i2c8-max96772-pinctrl { + compatible = "maxim,max96772-pinctrl"; + status = "okay"; + + pinctrl-names = "init","sleep"; + pinctrl-0 = <&i2c8_max96772_panel_pins>; + pinctrl-1 = <&i2c8_max96772_panel_pins>; + + i2c8_max96772_panel_pins: panel-pins { + tp-int { + pins = "MAX96772_GPIO10"; + function = "DES_TXID1_TO_SER"; + }; + }; + + i2c8_max96772_gpio: i2c8-max96772-gpio { + compatible = "maxim,max96772-gpio"; + status = "okay"; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&i2c8_max96772_pinctrl 0 330 15>; + }; + }; + + i2c8_max96772_panel: i2c8-max96772-panel { + compatible = "maxim,max96772-panel"; + status = "okay"; + + backlight = <&dp2lvds_backlight1>; + panel-size= <324 202>; + rate-count-ssc= <10 4 0>; + + panel-timing { + clock-frequency = <298400000>; + hactive = <2560>; + vactive = <1600>; + hfront-porch = <48>; + hsync-len = <32>; + hback-porch = <320>; + vfront-porch = <30>; + vsync-len = <3>; + vback-porch = <47>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <0>; + }; + + port { + i2c8_max96772_from_i2c8_max96749: endpoint { + remote-endpoint = <&i2c8_max96749_out_i2c8_max96772>; + }; + }; + }; + }; + + i2c8_r7f701_pwm: i2c8-r7f701-pwm@77 { + compatible = "r7f701-pwm"; + #pwm-cells = <3>; + reg = <0x77>; + status = "okay"; + }; + + i2c8_cyttsp7: i2c8-cyttsp7@24 { + compatible = "cy,cyttsp7_i2c_adapter"; + reg = <0x24>; + + status = "okay"; + cy,core { + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio_dp1>; + cy,irq_gpio = <&gpio1 RK_PB7 GPIO_ACTIVE_HIGH>; + cy,rst_gpio = <&i2c8_max96772_gpio 7 GPIO_ACTIVE_HIGH>; + + cy,max_xfer_len = <0x100>; + + /* CY_CORE_FLAG_WAKE_ON_GESTURE */ + /* cy,flags = <1>; */ + /* CY_CORE_EWG_TAP_TAP | CY_CORE_EWG_TWO_FINGER_SLIDE */ + /* cy,easy_wakeup_gesture = <3>; */ + cy,btn_keys = <172 /* KEY_HOMEPAGE */ + /* previously was KEY_HOME, new Android versions use KEY_HOMEPAGE */ + 139 /* KEY_MENU */ + 158 /* KEY_BACK */ + 217 /* KEY_SEARCH */ + 114 /* KEY_VOLUMEDOWN */ + 115 /* KEY_VOLUMEUP */ + 212 /* KEY_CAMERA */ + 116>; /* KEY_POWER */ + cy,btn_keys-tag = <0>; + + cy,mt { + cy,inp_dev_name = "cyttsp7-mt-dp1"; + /* CY_MT_FLAG_FLIP | CY_MT_FLAG_INV_X | CY_MT_FLAG_INV_Y */ + cy,flags = <0x20>; + cy,abs = + /* ABS_MT_POSITION_X, CY_ABS_MIN_X, CY_ABS_MAX_X, 0, 0 */ + < + 0x35 0 2560 0 0 + /* ABS_MT_POSITION_Y, CY_ABS_MIN_Y, CY_ABS_MAX_Y, 0, 0 */ + 0x36 0 1600 0 0 + /* ABS_MT_PRESSURE, CY_ABS_MIN_P, CY_ABS_MAX_P, 0, 0 */ + 0x3a 0 255 0 0 + /* CY_IGNORE_VALUE, CY_ABS_MIN_W, CY_ABS_MAX_W, 0, 0 */ + 0xffff 0 255 0 0 + /* ABS_MT_TRACKING_ID, CY_ABS_MIN_T, CY_ABS_MAX_T, 0, 0 */ + 0x39 0 15 0 0 + /* ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0 */ + 0x30 0 255 0 0 + /* ABS_MT_TOUCH_MINOR, 0, 255, 0, 0 */ + 0x31 0 255 0 0 + /* ABS_MT_ORIENTATION, -127, 127, 0, 0 */ + 0x34 0xffffff81 127 0 0 + /* ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0 */ + 0x37 0 1 0 0 + /* ABS_DISTANCE, 0, 255, 0, 0 */ + 0x19 0 255 0 0 + /* SRI:ABS_MT_DISTANCE, 0,MAX, 0, 0 */ + 0x3b 0 255 0 0>; + + cy,vkeys_x = <2560>; + cy,vkeys_y = <1600>; + + cy,virtual_keys = /* KeyCode CenterX CenterY Width Height */ + /* KEY_BACK */ + <158 1360 90 160 180 + /* KEY_MENU */ + 139 1360 270 160 180 + /* KEY_HOMEPAGE */ + 172 1360 450 160 180 + /* KEY SEARCH */ + 217 1360 630 160 180>; + }; + + cy,btn { + cy,inp_dev_name = "cyttsp7-btn-dp1"; + }; + + cy,proximity { + cy,inp_dev_name = "cyttsp7-proximity-dp1"; + cy,abs = + /* ABS_DISTANCE, CY_PROXIMITY_MIN_VAL, CY_PROXIMITY_MAX_VAL, 0, 0 */ + <0x19 0 1 0 0>; + }; + }; + }; +}; + +&mipi_dcphy0 { + status = "okay"; +}; + +&mipi_dcphy1 { + status = "okay"; +}; + +&pinctrl { + serdes { + /*dsi0*/ + i2c2_serdes_pins: i2c2-serdes-pins { + rockchip,pins = + <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*dp0*/ + i2c4_serdes_pins: i2c4-serdes-pins { + rockchip,pins = + <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*edp0*/ + i2c5_serdes_pins: i2c5-serdes-pins { + rockchip,pins = + <0 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <0 RK_PD5 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*dsi1*/ + i2c6_serdes_pins: i2c6-serdes-pins { + rockchip,pins = + <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*edp1*/ + i2c7_serdes_pins: i2c7-serdes-pins { + rockchip,pins = + <4 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <4 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + /*dp1*/ + i2c8_serdes_pins: i2c8-serdes-pins { + rockchip,pins = + <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,/*err*/ + <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;/*lock*/ + }; + }; +}; + +/* dsi0->serdes->lvds_panel */ +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0m2_pins>; +}; + +/* dp0->serdes->lvds_panel */ +&pwm10 { + pinctrl-0 = <&pwm10m2_pins>; + status = "okay"; +}; + +/* edp1->serdes->lvds_panel */ +&pwm11 { + pinctrl-0 = <&pwm11m3_pins>; + status = "okay"; +}; + +/* edp0->serdes->lvds_panel */ +&pwm7 { + pinctrl-0 = <&pwm7m0_pins>; + status = "okay"; +}; + +/* dsi1->serdes->lvds_panel */ +&pwm2 { + status = "okay"; + pinctrl-0 = <&pwm2m1_pins>; //v23 hw change to PWM2_M1(GPIO3_B1) +}; + +/* dp1->serdes->lvds_panel */ +&pwm1 { + pinctrl-0 = <&pwm1m2_pins>; + status = "okay"; +}; + +&route_dp0 { + status = "disabled"; + connect = <&vp0_out_dp0>; + logo,uboot = "logo34.bmp"; + logo,kernel = "logo34.bmp"; +}; + +&route_dp1 { + status = "disabled"; + connect = <&vp2_out_dp1>; + logo,uboot = "logo34.bmp"; + logo,kernel = "logo34.bmp"; +}; + +&route_dsi0 { + status = "disabled"; + connect = <&vp3_out_dsi0>; + logo,uboot = "logo1.bmp"; + logo,kernel = "logo1.bmp"; +}; + +&route_dsi1 { + status = "disabled"; + connect = <&vp3_out_dsi1>; + logo,uboot = "logo2.bmp"; + logo,kernel = "logo2.bmp"; +}; + +&route_edp0 { + status = "disabled"; + connect = <&vp1_out_edp0>; + logo,uboot = "logo56.bmp"; + logo,kernel = "logo56.bmp"; +}; + +&route_edp1 { + status = "disabled"; + connect = <&vp1_out_edp1>; + logo,uboot = "logo56.bmp"; + logo,kernel = "logo56.bmp"; +}; + +&usbdp_phy0 { + rockchip,dp-lane-mux = <0 1 2 3>; + status = "okay"; +}; + +&usbdp_phy1 { + rockchip,dp-lane-mux = <0 1 2 3>; + status = "okay"; +}; + +//dp0 +&vp0 { + assigned-clocks = <&cru DCLK_VOP0>; + assigned-clock-parents = <&hdptxphy_hdmi1>; +}; + +//edp +&vp1 { + assigned-clocks = <&cru DCLK_VOP1_SRC>; + assigned-clock-parents = <&cru PLL_GPLL>; +}; + +//dp1 +&vp2 { + assigned-clocks = <&cru DCLK_VOP2>; + assigned-clock-parents = <&hdptxphy_hdmi1>; +}; + +//dsi0 +&vp3 { + assigned-clocks = <&cru DCLK_VOP3>; + assigned-clock-parents = <&cru PLL_V0PLL>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi index 5c07f761dcd9..1e19254cc005 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi @@ -813,6 +813,25 @@ goodix,irq-gpio = <&gpio4 RK_PB4 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c3 { @@ -892,6 +911,22 @@ <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>, <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x-v10-sii9022-bt1120-to-hdmi.dts b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x-v10-sii9022-bt1120-to-hdmi.dts index 4a03bc67aeb1..008940c5ba75 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x-v10-sii9022-bt1120-to-hdmi.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x-v10-sii9022-bt1120-to-hdmi.dts @@ -20,12 +20,16 @@ }; /* - * The pins of gt1x and sii9022 are multiplexed + * The pins of gt1x/hynitron and sii9022 are multiplexed */ >1x { status = "disabled"; }; +&hynitron { + status = "disabled"; +}; + &i2c4 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi index cfdbcae8cbe8..c88013addb27 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb3-lp4x.dtsi @@ -152,6 +152,25 @@ goodix,irq-gpio = <&gpio1 RK_PB5 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c8 { @@ -253,6 +272,22 @@ <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb-typec { diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi index 0465778bbb0d..6f715ade1dde 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi @@ -494,6 +494,25 @@ goodix,irq-gpio = <&gpio1 RK_PB5 IRQ_TYPE_LEVEL_LOW>; power-supply = <&vcc3v3_lcd_n>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc3v3_lcd_n>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &i2c5 { @@ -688,6 +707,22 @@ <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>, <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-amp.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-amp.dtsi new file mode 100644 index 000000000000..b77f4ade74e8 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-amp.dtsi @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include + +/ { + rockchip_amp: rockchip-amp { + compatible = "rockchip,amp"; + clocks = <&cru TCLK_WDT_HPMCU>, <&cru PCLK_WDT_HPMCU>, + <&cru HCLK_CACHE>, <&cru CLK_HPMCU>, + <&cru CLK_HPMCU_RTC>, <&cru PCLK_HPMCU_INTMUX>, + <&cru SCLK_UART4>, <&cru PCLK_UART4>, <&cru PCLK_HPMCU_MAILBOX>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart4m2_xfer_pins>; + + status = "okay"; + }; + + reserved-memory { + /* hpmcu address */ + hpmcu_reserved: hpmcu@48c02000 { + reg = <0x48c02000 0x3a000>; + no-map; + }; + + rpmsg_reserved: rpmsg@48c3c000 { + reg = <0x48c3c000 0x10000>; + no-map; + }; + + rpmsg_dma_reserved: rpmsg-dma@48c4c000 { + compatible = "shared-dma-pool"; + reg = <0x48c4c000 0x10000>; + no-map; + }; + }; + + rpmsg: rpmsg@48c3c000 { + compatible = "rockchip,rpmsg"; + mbox-names = "rpmsg-rx", "rpmsg-tx"; + mboxes = <&hpmcu_mbox0 0 &hpmcu_mbox3 0>; + rockchip,vdev-nums = <1>; + /* hpmcu: link-id 0x03; */ + rockchip,link-id = <0x03>; + reg = <0x48c3c000 0x10000>; + memory-region = <&rpmsg_dma_reserved>; + + status = "okay"; + }; +}; + +&hpmcu_mbox0 { + rockchip,txpoll-period-ms = <1>; + status = "okay"; +}; + +&hpmcu_mbox3 { + rockchip,txpoll-period-ms = <1>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-4k.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-4k.dtsi index 34e33d61fceb..4a73b4f86bf6 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-4k.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-4k.dtsi @@ -25,6 +25,12 @@ remote-endpoint = <&imx415_out0>; data-lanes = <1 2 3 4>; }; + + csi_dphy_input1: endpoint@2 { + reg = <2>; + remote-endpoint = <&sc850sl_out0>; + data-lanes = <1 2 3 4>; + }; }; port@1 { reg = <1>; @@ -55,6 +61,13 @@ remote-endpoint = <&imx415_out1>; data-lanes = <1 2 3 4>; }; + + csi_dphy3_input1: endpoint@2 { + reg = <2>; + remote-endpoint = <&sc850sl_out1>; + data-lanes = <1 2 3 4>; + }; + }; port@1 { reg = <1>; @@ -112,6 +125,55 @@ }; }; }; + + sc850sl_0: sc850sl_0@30 { + compatible = "smartsens,sc850sl"; + status = "okay"; + reg = <0x30>; + clocks = <&cru CLK_MIPI0_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0_pins>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + sc850sl_out0: endpoint { + remote-endpoint = <&csi_dphy_input1>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-0 = <&i2c4m3_pins>; + + sc850sl_1: sc850sl_1@30 { + compatible = "smartsens,sc850sl"; + status = "okay"; + reg = <0x30>; + clocks = <&cru CLK_MIPI2_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio5 RK_PB0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk2_pins>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + sc850sl_out1: endpoint { + remote-endpoint = <&csi_dphy3_input1>; + data-lanes = <1 2 3 4>; + }; + }; + }; }; &mipi0_csi2 { diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-csi0.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-csi0.dtsi index 05b2481e7b83..6b726e14c01a 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-csi0.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb-dual-cam-csi0.dtsi @@ -92,6 +92,7 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "default"; rockchip,camera-module-lens-name = "default"; + rockchip,camera-module-sync-mode = "internal_master"; port { sc450ai_1_out: endpoint { remote-endpoint = <&csi_dphy2_input0>; @@ -114,6 +115,7 @@ rockchip,camera-module-facing = "back"; rockchip,camera-module-name = "default"; rockchip,camera-module-lens-name = "default"; + rockchip,camera-module-sync-mode = "external_master"; port { sc450ai_2_out: endpoint { remote-endpoint = <&csi_dphy1_input0>; @@ -258,7 +260,7 @@ &rkisp_vir0_sditf { status = "okay"; -} +}; &rkisp_vir1 { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-amp.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-amp.dts new file mode 100644 index 000000000000..38cf820cfd55 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-amp.dts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b.dtsi" +#include "rv1126b-evb.dtsi" +#include "rv1126b-evb-cam-csi0.dtsi" +#include "rv1126b-evb1-v10.dtsi" +#include "rv1126b-amp.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 AMP Board with HPMCU"; + compatible = "rockchip,rv1126b-evb1-v10", "rockchip,rv1126b"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts new file mode 100644 index 000000000000..9ee73d5f6811 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-emmc.dts @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-evb1-v10.dts" +#include "rv1126b-fastboot-emmc.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 Arm64 Fastboot Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts new file mode 100644 index 000000000000..a9d1046d7ff1 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nand.dts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b-evb1-v10.dts" +#include "rv1126b-fastboot-spi-nand.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 Arm64 Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot-spi-nand", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts new file mode 100644 index 000000000000..3f14ea6c77be --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10-fastboot-spi-nor.dts @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b-evb1-v10.dts" +#include "rv1126b-fastboot-spi-nor.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V10 Arm64 Board"; + compatible = "rockchip,rv1126b-evb1-v10-fastboot-spi-nor", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <75000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (20 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4a040000 (10 * 0x00100000)>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts index 9ab0043261cb..6ab9eb32912f 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dts @@ -17,6 +17,8 @@ &rockchip_suspend { status = "okay"; + rockchip,sleep-debug-en = <1>; + rockchip,sleep-mode-config = < (0 | RKPM_SLP_ARMOFF_LOGOFF diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi index 8c3cb43766d3..74004d783759 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v10.dtsi @@ -201,8 +201,9 @@ interrupts = ; pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; + pinctrl-names = "default", "pmic-reset"; pinctrl-0 = <&pmic_int>; + pinctrl-1 = <&soc_pwrctrl_reset>; rockchip,system-power-controller; wakeup-source; @@ -318,6 +319,25 @@ goodix,rst-gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio7 RK_PA6 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc_mipi>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio7 RK_PA6 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &mdio { @@ -342,6 +362,10 @@ pmic_int: pmic-int { rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + soc_pwrctrl_reset: soc-pwrctrl-reset { + rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_output_high>; + }; }; sdio-pwrseq { @@ -363,6 +387,22 @@ <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>, <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <7 RK_PA6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <7 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts new file mode 100644 index 000000000000..7594524c8867 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11-dual-4k.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-evb1-v10-dual-4k.dts" +#include "rv1126b-evb1-v11.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V11 DUAL 4K Board"; + compatible = "rockchip,rv1126b-evb1-v11-dual-4k", "rockchip,rv1126b"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dts new file mode 100644 index 000000000000..2ceb738121d4 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-evb1-v10.dts" +#include "rv1126b-evb1-v11.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V11 Board"; + compatible = "rockchip,rv1126b-evb1-v11", "rockchip,rv1126b"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dtsi new file mode 100644 index 000000000000..90dc4348c5ef --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v11.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-evb1-v10.dtsi" + +/ { + model = "Rockchip RV1126B EVB1 V11 Board"; + compatible = "rockchip,rv1126b-evb1-v11", "rockchip,rv1126b"; +}; + +&typec5v_pwren { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_none>; +}; + +&vbus5v0_typec { + gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v12.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v12.dtsi new file mode 100644 index 000000000000..a6d009dc40bb --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb1-v12.dtsi @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +#include "rv1126b-evb1-v11.dtsi" + +/delete-node/ &vccio_sd; +/delete-node/ &vdd_npu; +/delete-node/ &rk801; + +/ { + model = "Rockchip RV1126B EVB1 V12 Board"; + compatible = "rockchip,rv1126b-evb1-v12", "rockchip,rv1126b"; + + vdd_cpu: vdd-cpu { + compatible = "pwm-regulator"; + pwms = <&pwm0_8ch_0 0 25000 1>; + regulator-name = "vdd_cpu"; + regulator-init-microvolt = <950000>; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + pwm-supply = <&vcc5v0_sys>; + }; +}; + +&i2c0 { + status = "okay"; + + rk801: rk801@27 { + compatible = "rockchip,rk801"; + status = "okay"; + reg = <0x27>; + interrupt-parent = <&gpio0>; + interrupts = ; + pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + + pinctrl-names = "default", "pmic-reset"; + pinctrl-0 = <&pmic_int>; + pinctrl-1 = <&soc_pwrctrl_reset>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc12v_dcin>; + vcc2-supply = <&vcc12v_dcin>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc3v3_sys>; + vcc6-supply = <&vcc3v3_sys>; + vcc7-supply = <&vcc3v3_sys>; + + regulators { + vdd_npu: DCDC_REG1 { + regulator-name = "vdd_npu"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-off-in-suspend; + regulator-suspend-microvolt = <950000>; + }; + }; + + vcc3v3_sys: DCDC_REG2 { + regulator-name = "vcc3v3_sys"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-on-in-suspend; + }; + }; + + vdd_logic: DCDC_REG4 { + regulator-name = "vdd_logic"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <1500000>; + regulator-initial-mode = <0x1>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-mode = <0x2>; + regulator-off-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + vccio_sd: LDO_REG1 { + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + + vcc_1v8: LDO_REG2 { + regulator-name = "vcc_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_3v3: SWITCH_REG { + regulator-name = "vcc_3v3"; + regulator-boot-on; + regulator-always-on; + regulator-state-mem { + regulator-off-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-aov-dual-cam.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-aov-dual-cam.dts new file mode 100644 index 000000000000..6cec649318d1 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-aov-dual-cam.dts @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b.dtsi" +#include "rv1126b-evb.dtsi" +#include "rv1126b-evb2-v10.dtsi" +#include "rv1126b-evb-dual-cam-4k.dtsi" + +/ { + model = "Rockchip RV1126B EVB2 V10 Board"; + compatible = "rockchip,rv1126b-evb2-v10", "rockchip,rv1126b"; +}; + +&rockchip_suspend { + status = "okay"; + + rockchip,sleep-pin-config = < + (0 + | RKPM_SLEEP_PIN0_EN + ) + (0 + | RKPM_SLEEP_PIN0_ACT_LOW + ) + >; + + rockchip,sleep-io-config = < + /* pmic_sleep */ + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(0) + ) + /* reset */ + #if 0 + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_NONE + | RKPM_IO_CFG_ID(1) + ) + #endif + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(2) + ) + (0 + | RKPM_IO_CFG_PULL_NONE + | RKPM_IO_CFG_ID(3) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_UP + | RKPM_IO_CFG_ID(4) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(5) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(6) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_UP + | RKPM_IO_CFG_ID(7) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(8) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(9) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(10) + ) + /* uart0 tx */ + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(11) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(12) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(16) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(17) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_NONE + | RKPM_IO_CFG_ID(18) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_NONE + | RKPM_IO_CFG_ID(19) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(20) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(21) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(22) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(23) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(24) + ) + (0 + | RKPM_IO_CFG_IOMUX_GPIO + | RKPM_IO_CFG_GPIO_DIR_INPUT + | RKPM_IO_CFG_PULL_DOWN + | RKPM_IO_CFG_ID(25) + ) + >; +}; + +&sc850sl_0 { + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-stb = <1>; +}; + +&sc850sl_1 { + reset-gpios = <&gpio4 RK_PA6 GPIO_ACTIVE_HIGH>; + rockchip,camera-module-stb = <1>; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-mcu-k350c4516t.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-mcu-k350c4516t.dts index baa7b7a71285..9414553a06f3 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-mcu-k350c4516t.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-mcu-k350c4516t.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "rv1126b-evb2-v10.dts" / { @@ -15,6 +16,7 @@ &rgb { status = "okay"; + rockchip,data-map-mode = ; rockchip,data-sync-bypass; pinctrl-names = "default"; /* diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dts index 7ffacffa6ab3..d05397b88aab 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-sii9022-bt1120-to-hdmi.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include #include "rv1126b-evb2-v10.dts" / { @@ -60,6 +61,11 @@ &rgb { status = "okay"; + /* + * BT1120: ROCKCHIP_BT1120_DATA_MAP_DATA_WITH_DUMMY_0 + * BT656: ROCKCHIP_BT656_DATA_MAP_DATA_WITH_DUMMY_0 + */ + rockchip,data-map-mode = ; pinctrl-names = "default"; /* * bt1120_pins for bt1120 diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts new file mode 100644 index 000000000000..ca8d8a5e66a1 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10-tb-400w.dts @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; +#include "rv1126b.dtsi" +#include "rv1126b-evb.dtsi" +#include "rv1126b-evb2-v10.dtsi" +#include "rv1126b-thunder-boot-cam.dtsi" +#include "rv1126b-thunder-boot-spi-nor.dtsi" + +/ { + model = "Rockchip RV1126B EVB2 V10 ARM64 TB 400W Board"; + compatible = "rockchip,rv1126b-evb2-v10-tb-400w", "rockchip,rv1126b"; + + chosen { + bootargs = "loglevel=0 initcall_nr_threads=-1 initcall_debug=0 earlycon=uart8250,mmio32,0x20810000 console=ttyFIQ0 root=/dev/rd0 rootfstype=erofs rootflags=dax snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=32K"; + }; +}; + +&i2c3 { + clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c3m1_pins>; + rockchip,amp-shared; + status = "okay"; + + sc450ai: sc450ai@30 { + compatible = "smartsens,sc450ai"; + status = "okay"; + reg = <0x30>; + clocks = <&cru CLK_MIPI0_OUT2IO>; + clock-names = "xvclk"; + reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; + pwdn-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_clk0_pins>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "default"; + rockchip,camera-module-lens-name = "default"; + port { + cam0_out: endpoint { + remote-endpoint = <&csi_dphy_input0>; + data-lanes = <1 2 3 4>; + }; + }; + }; +}; + +&ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; +}; + +&ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; +}; + +&rkisp_thunderboot { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 2688x1520: 0x14c8000 + */ + reg = <0x41320000 0x14c8000>; +}; + +&usb2phy { + status = "okay"; +}; + +&usb2phy_otg { + status = "okay"; +}; + +&usb3phy { + status = "okay"; +}; + +&usb_drd_dwc3 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts index f79d92f045f7..96dd2a1089d5 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dts @@ -6,405 +6,18 @@ /dts-v1/; #include "rv1126b.dtsi" #include "rv1126b-evb.dtsi" +#include "rv1126b-evb2-v10.dtsi" #include "rv1126b-evb-cam-csi0.dtsi" / { model = "Rockchip RV1126B EVB2 V10 Board"; compatible = "rockchip,rv1126b-evb2-v10", "rockchip,rv1126b"; - - gpio-keys { - compatible = "gpio-keys"; - autorepeat; - pinctrl-names = "default"; - pinctrl-0 = <&pwr_key>; - power-key { - gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; - linux,code = ; - label ="GPIO Key Power"; - debounce-interval = <100>; - wakeup-source; - /* gpio-key,wakeup; */ - }; - }; - - vcc5v0_dcin: vcc5v0-dcin { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_dcin"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; - }; - - vcc5v0_host: vcc5v0-host { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_host"; - regulator-boot-on; - regulator-always-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - gpio = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; - vin-supply = <&vcc5v0_dcin>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_host_en>; - }; - - vccsys_stb: vccsys-stb { - compatible = "regulator-fixed"; - regulator-name = "vccsys_stb"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc5v0_dcin>; - }; - - vcc3v3_stb: vcc3v3-stb { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_stb"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vccsys_stb>; - }; - - vcc1v8_pmu: vdd1_1v8_ddr: vcc1v8_pmu { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_stb"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - vin-supply = <&vccsys_stb>; - }; - - vdd2_1v1_ddr: vdd2_1v1_ddr { - compatible = "regulator-fixed"; - regulator-name = "vdd2_1v1_ddr"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; - vin-supply = <&vccsys_stb>; - }; - - vddq_0v6_lp4x: vddq-0v6-lp4x { - compatible = "regulator-fixed"; - regulator-name = "vddq_0v6_lp4x"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <600000>; - regulator-max-microvolt = <600000>; - vin-supply = <&vccsys_stb>; - }; - - vcc3v3_pmu: vcc3v3-pmu { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_pmu"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vccsys_stb>; - }; - - vcc0v9_pmu: vcc0v9-pmu { - compatible = "regulator-fixed"; - regulator-name = "vcc0v9_pmu"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <900000>; - regulator-max-microvolt = <900000>; - vin-supply = <&vcc1v8_pmu>; - }; - - vcc_mipi: vcc-mipi{ - compatible = "regulator-fixed"; - regulator-name = "vcc_mipi"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc1v8_pmu>; - }; - - vcc_1v8: vcc-1v8 { - compatible = "regulator-fixed"; - regulator-name = "vcc_1v8"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - vin-supply = <&vccsys_stb>; - }; - - vcc_3v3: vcc3v3_dev: vcc-3v3 { - compatible = "regulator-fixed"; - regulator-name = "vcc_3v3"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vccsys_stb>; - }; - - vcc_lcd: vcc-lcd { - compatible = "regulator-fixed"; - gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; - regulator-name = "vcc_lcd"; - enable-active-high; - }; - - vcc_sd: vcc-sd { - compatible = "regulator-fixed"; - gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; - regulator-name = "vcc_sd"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - enable-active-low; - vin-supply = <&vcc_3v3>; - }; - - vccio_sd: vccio-sd { - compatible = "regulator-gpio"; - regulator-boot-on; - regulator-name = "vccio_sd"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_volt>; - gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; - vin-supply = <&vccsys_stb>; - states = <1800000 0x0 - 3300000 0x1>; - }; - - vdd_log: vdd-log { - compatible = "pwm-regulator"; - pwms = <&pwm0_8ch_2 0 25000 1>; - regulator-name = "vdd_log"; - regulator-init-microvolt = <905000>; - regulator-min-microvolt = <810000>; - regulator-max-microvolt = <1006000>; - regulator-always-on; - regulator-boot-on; - pwm-supply = <&vccsys_stb>; - status = "okay"; - }; - - vdd_cpu: vdd-cpu { - compatible = "pwm-regulator"; - pwms = <&pwm0_8ch_0 0 25000 1>; - regulator-name = "vdd_cpu"; - regulator-init-microvolt = <950000>; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1100000>; - regulator-always-on; - regulator-boot-on; - pwm-supply = <&vccsys_stb>; - status = "okay"; - }; - - vdd_npu: vdd-npu { - compatible = "pwm-regulator"; - pwms = <&pwm0_8ch_1 0 25000 1>; - regulator-name = "vdd_npu"; - regulator-init-microvolt = <950000>; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1100000>; - regulator-always-on; - regulator-boot-on; - pwm-supply = <&vccsys_stb>; - status = "okay"; - }; - - wireless-bluetooth { - compatible = "bluetooth-platdata"; - uart_rts-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; - pinctrl-names = "default", "rts_gpio"; - pinctrl-0 = <&uart2m0_rtsn_pins>; - pinctrl-1 = <&uart2_gpios>; - BT,power-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; - - wireless-wlan { - compatible = "wlan-platdata"; - rockchip,grf = <&grf>; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_wake_host>; - wifi_chip_type = "rk96x"; - WIFI,host_wake-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; -}; - -&acdcdig_dsm { - pa-ctl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - status = "okay"; -}; - -&acodec_sound { - status = "okay"; -}; - -&audio_codec { - status = "okay"; -}; - -&backlight { - pwms = <&pwm2_8ch_7 0 25000 0>; -}; - -&cpu0 { - cpu-supply = <&vdd_cpu>; -}; - -&display_subsystem { - status = "okay"; -}; - -&dsi { - status = "okay"; -}; - -&dsi_in_vop { - status = "okay"; -}; - -&dsi_panel { - power-supply = <&vcc_lcd>; -}; - -&fspi0 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <100000000>; - spi-rx-bus-width = <4>; - spi-tx-bus-width = <1>; - }; -}; - -&gmac { - phy-mode = "rmii"; - clock_in_out = "input"; - phy-handle = <&rmii_phy>; - status = "okay"; }; &imx415 { reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; }; -&i2c2 { - pinctrl-0 = <&i2c2m1_pins>; - status = "okay"; - - gt1x: gt1x@14 { - compatible = "goodix,gt1x"; - reg = <0x14>; - pinctrl-names = "default"; - pinctrl-0 = <&touch_gpio>; - vdd_ana-supply = <&vcc_lcd>; - goodix,rst-gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; - goodix,irq-gpio = <&gpio3 RK_PB7 IRQ_TYPE_LEVEL_LOW>; - }; -}; - -&mdio { - rmii_phy: ethernet-phy@2 { - compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; - reg = <2>; - clocks = <&cru CLK_MACPHY>; - clock-frequency = <24000000>; - resets = <&cru SRST_RESETN_MACPHY>; - pinctrl-names = "default"; - pinctrl-0 = <&fephym2_pins>; - phy-is-integrated; - }; -}; - -&mipi_dphy { - status = "okay"; -}; - -&pinctrl { - buttons { - pwr_key: pwr-key { - rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - sdmmc { - /omit-if-no-ref/ - sdmmc_volt: sdmmc-volt { - rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - touch { - touch_gpio: touch-gpio { - rockchip,pins = - <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, - <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - usb { - vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - wireless-bluetooth { - uart2_gpios: uart2-gpios { - rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - wireless-wlan { - wifi_wake_host: wifi-wake-host { - rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; -}; - -&pwm0_8ch_0 { - status = "okay"; -}; - -&pwm0_8ch_1 { - status = "okay"; -}; - -&pwm0_8ch_2 { - status = "okay"; -}; - -&pwm2_8ch_7 { - status = "okay"; -}; - -&rkaiisp { - status = "okay"; -}; - -&rkaiisp_mmu { - status = "okay"; -}; - -&rkaiisp_vir0 { - status = "okay"; -}; - -&rknpu { - rknpu-supply = <&vdd_npu>; -}; - &rockchip_suspend { status = "okay"; @@ -562,83 +175,11 @@ >; }; -&route_dsi { - status = "okay"; -}; - -&rtc { - rockchip,rtc-suspend-bypass; - status = "okay"; -}; - -&sai2 { - rockchip,sai-rx-route = <1 0 2 3>; - status = "okay"; - /delete-property/ pinctrl-names; - /delete-property/ pinctrl-0; -}; - -&saradc0 { - vref-supply = <&vcc_1v8>; -}; - &sc450ai { reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_LOW>; }; &sc850sl { reset-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>; -}; - -&sdmmc0 { - max-frequency = <200000000>; - no-sdio; - no-mmc; - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - disable-wp; - sd-uhs-sdr104; - vmmc-supply = <&vcc_sd>; - vqmmc-supply = <&vccio_sd>; - status = "okay"; -}; - -&sdmmc1 { - bus-width = <1>; - cap-sd-highspeed; - no-sd; - no-mmc; - max-frequency = <200000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; - keep-power-in-suspend; - non-removable; - //mmc-pwrseq = <&sdio_pwrseq>; - //sd-uhs-sdr104; - status = "okay"; -}; - -&uart2 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; -}; - -&usb2phy_host { - phy-supply = <&vcc5v0_host>; -}; - -&usb3phy { - status = "disabled"; -}; - -&usb_drd_dwc3 { - dr_mode = "otg"; - extcon = <&usb2phy>; - maximum-speed = "high-speed"; - phys = <&usb2phy_otg>; - phy-names = "usb2-phy"; - snps,dis_u2_susphy_quirk; - snps,usb2-lpm-disable; + rockchip,camera-module-stb = <1>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dtsi new file mode 100644 index 000000000000..39cb108c6065 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb2-v10.dtsi @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/ { + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-names = "default"; + pinctrl-0 = <&pwr_key>; + power-key { + gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; + linux,code = ; + label ="GPIO Key Power"; + debounce-interval = <100>; + wakeup-source; + /* gpio-key,wakeup; */ + }; + }; + + vcc5v0_dcin: vcc5v0-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_host: vcc5v0-host { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_host"; + regulator-boot-on; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpio = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>; + vin-supply = <&vcc5v0_dcin>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; + + vccsys_stb: vccsys-stb { + compatible = "regulator-fixed"; + regulator-name = "vccsys_stb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc5v0_dcin>; + }; + + vcc3v3_stb: vcc3v3-stb { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_stb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vccsys_stb>; + }; + + vcc1v8_pmu: vdd1_1v8_ddr: vcc1v8_pmu { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_stb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vccsys_stb>; + }; + + vdd2_1v1_ddr: vdd2_1v1_ddr { + compatible = "regulator-fixed"; + regulator-name = "vdd2_1v1_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + vin-supply = <&vccsys_stb>; + }; + + vddq_0v6_lp4x: vddq-0v6-lp4x { + compatible = "regulator-fixed"; + regulator-name = "vddq_0v6_lp4x"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <600000>; + vin-supply = <&vccsys_stb>; + }; + + vcc3v3_pmu: vcc3v3-pmu { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vccsys_stb>; + }; + + vcc0v9_pmu: vcc0v9-pmu { + compatible = "regulator-fixed"; + regulator-name = "vcc0v9_pmu"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc1v8_pmu>; + }; + + vcc_mipi: vcc-mipi{ + compatible = "regulator-fixed"; + regulator-name = "vcc_mipi"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc1v8_pmu>; + }; + + vcc_1v8: vcc-1v8 { + compatible = "regulator-fixed"; + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vccsys_stb>; + }; + + vcc_3v3: vcc3v3_dev: vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vccsys_stb>; + }; + + vcc_lcd: vcc-lcd { + compatible = "regulator-fixed"; + gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>; + regulator-name = "vcc_lcd"; + enable-active-high; + }; + + vcc_sd: vcc-sd { + compatible = "regulator-fixed"; + gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; + regulator-name = "vcc_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-low; + vin-supply = <&vcc_3v3>; + }; + + vccio_sd: vccio-sd { + compatible = "regulator-gpio"; + regulator-boot-on; + regulator-name = "vccio_sd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_volt>; + gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; + vin-supply = <&vccsys_stb>; + states = <1800000 0x0 + 3300000 0x1>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm0_8ch_2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-init-microvolt = <905000>; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1006000>; + regulator-always-on; + regulator-boot-on; + pwm-supply = <&vccsys_stb>; + status = "okay"; + }; + + vdd_cpu: vdd-cpu { + compatible = "pwm-regulator"; + pwms = <&pwm0_8ch_0 0 25000 1>; + regulator-name = "vdd_cpu"; + regulator-init-microvolt = <950000>; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + pwm-supply = <&vccsys_stb>; + status = "okay"; + }; + + vdd_npu: vdd-npu { + compatible = "pwm-regulator"; + pwms = <&pwm0_8ch_1 0 25000 1>; + regulator-name = "vdd_npu"; + regulator-init-microvolt = <950000>; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + pwm-supply = <&vccsys_stb>; + status = "okay"; + }; + + wireless-bluetooth { + compatible = "bluetooth-platdata"; + uart_rts-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "rts_gpio"; + pinctrl-0 = <&uart2m0_rtsn_pins>; + pinctrl-1 = <&uart2_gpios>; + BT,power-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; + + wireless-wlan { + compatible = "wlan-platdata"; + rockchip,grf = <&grf>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_wake_host>; + wifi_chip_type = "rk96x"; + WIFI,host_wake-gpios = <&gpio0 RK_PC0 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&acdcdig_dsm { + pa-ctl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; + status = "okay"; +}; + +&acodec_sound { + status = "okay"; +}; + +&audio_codec { + status = "okay"; +}; + +&backlight { + pwms = <&pwm2_8ch_7 0 25000 0>; +}; + +&cpu0 { + cpu-supply = <&vdd_cpu>; +}; + +&display_subsystem { + status = "okay"; +}; + +&dsi { + status = "okay"; +}; + +&dsi_in_vop { + status = "okay"; +}; + +&dsi_panel { + power-supply = <&vcc_lcd>; +}; + +&fspi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <100000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <1>; + }; +}; + +&gmac { + phy-mode = "rmii"; + clock_in_out = "input"; + phy-handle = <&rmii_phy>; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2m1_pins>; + status = "okay"; + + gt1x: gt1x@14 { + compatible = "goodix,gt1x"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <&touch_gpio>; + vdd_ana-supply = <&vcc_lcd>; + goodix,rst-gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; + goodix,irq-gpio = <&gpio3 RK_PB7 IRQ_TYPE_LEVEL_LOW>; + }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc_lcd>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; +}; + +&mdio { + rmii_phy: ethernet-phy@2 { + compatible = "ethernet-phy-id0680.8101", "ethernet-phy-ieee802.3-c22"; + reg = <2>; + clocks = <&cru CLK_MACPHY>; + clock-frequency = <24000000>; + resets = <&cru SRST_RESETN_MACPHY>; + pinctrl-names = "default"; + pinctrl-0 = <&fephym2_pins>; + phy-is-integrated; + }; +}; + +&mipi_dphy { + status = "okay"; +}; + +&pinctrl { + buttons { + pwr_key: pwr-key { + rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + sdmmc { + /omit-if-no-ref/ + sdmmc_volt: sdmmc-volt { + rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + touch { + touch_gpio: touch-gpio { + rockchip,pins = + <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, + <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + ts_int_active: ts_int_active { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-bluetooth { + uart2_gpios: uart2-gpios { + rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + wireless-wlan { + wifi_wake_host: wifi-wake-host { + rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; +}; + +&pwm0_8ch_0 { + status = "okay"; +}; + +&pwm0_8ch_1 { + status = "okay"; +}; + +&pwm0_8ch_2 { + status = "okay"; +}; + +&pwm2_8ch_7 { + status = "okay"; +}; + +&rkaiisp { + status = "okay"; +}; + +&rkaiisp_mmu { + status = "okay"; +}; + +&rkaiisp_vir0 { + status = "okay"; +}; + +&rknpu { + rknpu-supply = <&vdd_npu>; +}; + +&route_dsi { + status = "okay"; +}; + +&rtc { + rockchip,rtc-suspend-bypass; + status = "okay"; +}; + +&sai2 { + rockchip,sai-rx-route = <1 0 2 3>; + status = "okay"; + /delete-property/ pinctrl-names; + /delete-property/ pinctrl-0; +}; + +&saradc0 { + vref-supply = <&vcc_1v8>; +}; + +&sdmmc0 { + max-frequency = <200000000>; + no-sdio; + no-mmc; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + disable-wp; + sd-uhs-sdr104; + vmmc-supply = <&vcc_sd>; + vqmmc-supply = <&vccio_sd>; + status = "okay"; +}; + +&sdmmc1 { + bus-width = <1>; + cap-sd-highspeed; + no-sd; + no-mmc; + max-frequency = <200000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_clk_pins &sdmmc1_cmd_pins &sdmmc1_bus4_pins>; + keep-power-in-suspend; + non-removable; + //mmc-pwrseq = <&sdio_pwrseq>; + //sd-uhs-sdr104; + status = "okay"; +}; + +&uart2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2m0_xfer_pins &uart2m0_ctsn_pins>; +}; + +&usb2phy_host { + phy-supply = <&vcc5v0_host>; +}; + +&usb3phy { + status = "disabled"; +}; + +&usb_drd_dwc3 { + dr_mode = "otg"; + extcon = <&usb2phy>; + maximum-speed = "high-speed"; + phys = <&usb2phy_otg>; + phy-names = "usb2-phy"; + snps,dis_u2_susphy_quirk; + snps,usb2-lpm-disable; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts index d0dacbfed835..370e01ec9df6 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb3-v10.dts @@ -324,6 +324,25 @@ goodix,rst-gpio = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio3 RK_PB7 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc_mipi>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio5 RK_PD6 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &mipi2_csi2 { @@ -451,6 +470,8 @@ &rockchip_suspend { status = "okay"; + rockchip,sleep-debug-en = <1>; + rockchip,sleep-pin-config = < (0 ) @@ -483,6 +504,22 @@ <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>, <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; }; + + ts_int_active: ts_int_active { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_down>; + }; }; usb { diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts index 71d28c743afc..0c5a8bb6eedf 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126b-evb4-v10.dts @@ -247,8 +247,9 @@ interrupts = ; pwrctrl-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; + pinctrl-names = "default", "pmic-reset"; pinctrl-0 = <&pmic_int>; + pinctrl-1 = <&soc_pwrctrl_reset>; rockchip,system-power-controller; wakeup-source; @@ -361,6 +362,25 @@ goodix,rst-gpio = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio0 RK_PA7 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc_mipi>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio0 RK_PC5 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &mdio { @@ -385,6 +405,10 @@ pmic_int: pmic-int { rockchip,pins = <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up>; }; + + soc_pwrctrl_reset: soc-pwrctrl-reset { + rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_output_high>; + }; }; sdio-pwrseq { @@ -400,6 +424,24 @@ }; }; + touch { + ts_int_active: ts_int_active { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + usb { typec5v_pwren: typec5v-pwren { rockchip,pins = <5 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>; @@ -438,6 +480,8 @@ &rockchip_suspend { status = "okay"; + rockchip,sleep-debug-en = <1>; + rockchip,sleep-mode-config = < (0 | RKPM_SLP_ARMOFF_LOGOFF diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi new file mode 100644 index 000000000000..698e5b2148a4 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-emmc.dtsi @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/ { + ramdisk: ramdisk { + compatible = "rockchip,ramdisk"; + memory-region = <&ramdisk_r>; + }; + + thunder_boot_mmc: thunder-boot-mmc { + compatible = "rockchip,thunder-boot-mmc"; + reg = <0x21470000 0x4000>; + clocks = <&cru HCLK_EMMC>, <&cru CCLK_EMMC>; + clock-names = "biu", "ciu"; + memory-region-src = <&ramdisk_c>; + memory-region-dst = <&ramdisk_r>; + memory-region-idmac = <&mmc_idmac>; + }; +}; + +&emmc { + memory-region-ecsd = <&mmc_ecsd>; + post-power-on-delay-ms = <0>; +}; + +&reserved_memory { + /* Should enable this node if the security feature is enabled, like TA. */ + tee: tee@48400000 { + reg = <0x48400000 0x00800000>; + status = "disabled"; + }; + + mmc_idmac: mmc@48000000 { + reg = <0x48000000 0x00400000>; + }; + + mmc_ecsd: mmc@47FFFE00{ + reg = <0x47FFFE00 0x00001000>; + }; + + ramdisk_r: ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; + }; + + ramdisk_c: ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; + }; +}; + +&hw_decompress { + memory-region = <&ramdisk_c>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nand.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nand.dtsi new file mode 100644 index 000000000000..d31fb7748499 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nand.dtsi @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/ { + ramdisk: ramdisk { + compatible = "rockchip,ramdisk"; + memory-region = <&ramdisk_r>; + }; +}; + +&reserved_memory { + /* Should enable this node if the security feature is enabled, like TA. */ + tee: tee@48400000 { + reg = <0x48400000 0x00800000>; + status = "disabled"; + }; + + ramdisk_r: ramdisk_r { + reg = <0x48c40000 (40 * 0x00100000)>; + }; + + ramdisk_c: ramdisk_c { + reg = <0x4b440000 (20 * 0x00100000)>; + }; +}; + +&hw_decompress { + memory-region = <&ramdisk_c>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nor.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nor.dtsi new file mode 100644 index 000000000000..354484f5b66d --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-fastboot-spi-nor.dtsi @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/ { + ramdisk: ramdisk { + compatible = "rockchip,ramdisk"; + memory-region = <&ramdisk_r>; + }; + + thunder_boot_spi_nor: thunder-boot-spi-nor { + compatible = "rockchip,thunder-boot-sfc"; + reg = <0x21460000 0x4000>; + memory-region-src = <&ramdisk_c>; + memory-region-dst = <&ramdisk_r>; + }; +}; + +&reserved_memory { + /* Should enable this node if the security feature is enabled, like TA. */ + tee: tee@48400000 { + reg = <0x48400000 0x00800000>; + status = "disabled"; + }; + + ramdisk_r: ramdisk_r { + reg = <0x48c40000 (20 * 0x00100000)>; + }; + + ramdisk_c: ramdisk_c { + reg = <0x4a040000 (10 * 0x00100000)>; + }; +}; + +&hw_decompress { + memory-region = <&ramdisk_c>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi index d2aa7ff395b9..0d5fa19bd673 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b-pinctrl.dtsi @@ -249,9 +249,9 @@ ethm0_miim_pins: ethm0-miim-pins { rockchip,pins = /* eth_mdc_m0 */ - <6 RK_PC0 2 &pcfg_pull_none>, + <6 RK_PC0 2 &pcfg_pull_none_drv_level_3_75>, /* eth_mdio_m0 */ - <6 RK_PB7 2 &pcfg_pull_none>; + <6 RK_PB7 2 &pcfg_pull_none_drv_level_3_75>; }; /omit-if-no-ref/ @@ -278,9 +278,9 @@ /* eth_txctl_m0 */ <6 RK_PB1 2 &pcfg_pull_none>, /* eth_txd0_m0 */ - <6 RK_PA7 2 &pcfg_pull_none>, + <6 RK_PA7 2 &pcfg_pull_none_drv_level_3_75>, /* eth_txd1_m0 */ - <6 RK_PB0 2 &pcfg_pull_none>; + <6 RK_PB0 2 &pcfg_pull_none_drv_level_3_75>; }; /omit-if-no-ref/ @@ -289,7 +289,7 @@ /* eth_rxclk_m0 */ <6 RK_PC3 2 &pcfg_pull_none>, /* eth_txclk_m0 */ - <6 RK_PC2 2 &pcfg_pull_none>; + <6 RK_PC2 2 &pcfg_pull_none_drv_level_3_75>; }; /omit-if-no-ref/ @@ -300,9 +300,9 @@ /* eth_rxd3_m0 */ <6 RK_PA4 2 &pcfg_pull_none>, /* eth_txd2_m0 */ - <6 RK_PA5 2 &pcfg_pull_none>, + <6 RK_PA5 2 &pcfg_pull_none_drv_level_3_75>, /* eth_txd3_m0 */ - <6 RK_PA6 2 &pcfg_pull_none>; + <6 RK_PA6 2 &pcfg_pull_none_drv_level_3_75>; }; /omit-if-no-ref/ @@ -323,9 +323,9 @@ ethm1_miim_pins: ethm1-miim-pins { rockchip,pins = /* eth_mdc_m1 */ - <5 RK_PB6 2 &pcfg_pull_none>, + <5 RK_PB6 2 &pcfg_pull_none_drv_level_5_00>, /* eth_mdio_m1 */ - <5 RK_PB5 2 &pcfg_pull_none>; + <5 RK_PB5 2 &pcfg_pull_none_drv_level_5_00>; }; /omit-if-no-ref/ @@ -352,9 +352,9 @@ /* eth_txctl_m1 */ <5 RK_PC2 2 &pcfg_pull_none>, /* eth_txd0_m1 */ - <5 RK_PB7 2 &pcfg_pull_none>, + <5 RK_PB7 2 &pcfg_pull_none_drv_level_5_00>, /* eth_txd1_m1 */ - <5 RK_PC0 2 &pcfg_pull_none>; + <5 RK_PC0 2 &pcfg_pull_none_drv_level_5_00>; }; /omit-if-no-ref/ @@ -363,7 +363,7 @@ /* eth_rxclk_m1 */ <5 RK_PC7 2 &pcfg_pull_none>, /* eth_txclk_m1 */ - <5 RK_PC6 2 &pcfg_pull_none>; + <5 RK_PC6 2 &pcfg_pull_none_drv_level_5_00>; }; /omit-if-no-ref/ @@ -374,9 +374,9 @@ /* eth_rxd3_m1 */ <5 RK_PC4 2 &pcfg_pull_none>, /* eth_txd2_m1 */ - <5 RK_PC5 2 &pcfg_pull_none>, + <5 RK_PC5 2 &pcfg_pull_none_drv_level_5_00>, /* eth_txd3_m1 */ - <5 RK_PA0 2 &pcfg_pull_none>; + <5 RK_PA0 2 &pcfg_pull_none_drv_level_5_00>; }; /omit-if-no-ref/ @@ -399,14 +399,14 @@ eth_clk_25mm0_out_pins: eth-clk-25mm0-out-pins { rockchip,pins = /* eth_clk_25m_out_m0 */ - <6 RK_PC1 2 &pcfg_pull_none>; + <6 RK_PC1 2 &pcfg_pull_none_drv_level_3_75>; }; /omit-if-no-ref/ eth_clk_25mm1_out_pins: eth-clk-25mm1-out-pins { rockchip,pins = /* eth_clk_25m_out_m1 */ - <5 RK_PC1 2 &pcfg_pull_none>; + <5 RK_PC1 2 &pcfg_pull_none_drv_level_5_00>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-cam.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-cam.dtsi new file mode 100644 index 000000000000..1a4eb65902e2 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-cam.dtsi @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + */ + +&csi2_dphy0 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + csi_dphy_input0: endpoint@1 { + reg = <1>; + remote-endpoint = <&cam0_out>; + data-lanes = <1 2 3 4>; + }; + }; + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + csidphy0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi0_csi2_input>; + }; + }; + }; +}; + +&mipi0_csi2 { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_input: endpoint@1 { + reg = <1>; + remote-endpoint = <&csidphy0_out>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + mipi0_csi2_output: endpoint@0 { + reg = <0>; + remote-endpoint = <&cif_mipi_in0>; + }; + }; + }; +}; + +&rkcif { + status = "okay"; +}; + +&rkcif_mipi_lvds { + status = "okay"; + memory-region-thunderboot = <&rkisp_thunderboot>; + + port { + cif_mipi_in0: endpoint { + remote-endpoint = <&mipi0_csi2_output>; + }; + }; +}; + +&rkcif_mipi_lvds_sditf { + status = "okay"; + + port { + mipi_lvds_sditf: endpoint { + remote-endpoint = <&isp_vir0>; + }; + }; +}; + +&rkcif_mmu { + status = "okay"; +}; + +&rkisp { + status = "okay"; +}; + +&rkisp_mmu { + status = "okay"; +}; + +&rkisp_vir0 { + status = "okay"; + memory-region-thunderboot = <&rkisp_thunderboot>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + isp_vir0: endpoint@0 { + reg = <0>; + remote-endpoint = <&mipi_lvds_sditf>; + }; + }; +}; + +&rkisp_vir0_sditf { + status = "okay"; +}; + +&rkvpss { + status = "okay"; + dvbm = <&rkdvbm>; +}; + +&rkvpss_mmu { + status = "okay"; +}; + +&rkvpss_vir0 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-emmc.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-emmc.dtsi new file mode 100644 index 000000000000..1d5b33308f53 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-emmc.dtsi @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-thunder-boot.dtsi" + +/ { + thunder_boot_mmc: thunder-boot-mmc { + compatible = "rockchip,thunder-boot-mmc"; + reg = <0x21470000 0x4000>; + clocks = <&cru HCLK_EMMC>, <&cru CCLK_EMMC>; + clock-names = "biu", "ciu"; + memory-region-src = <&ramdisk_c>; + memory-region-dst = <&ramdisk_r>; + memory-region-idmac = <&mmc_idmac>; + }; +}; + +&emmc { + memory-region-ecsd = <&mmc_ecsd>; + post-power-on-delay-ms = <0>; +}; + +&reserved_memory { + mmc_ecsd: mmc@47fffe00 { + reg = <0x47fffe00 0x00001000>; + }; + + mmc_idmac: mmc@48000000 { + reg = <0x48000000 0x00400000>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-spi-nor.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-spi-nor.dtsi new file mode 100644 index 000000000000..92dfbebff64f --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot-spi-nor.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b-thunder-boot.dtsi" + +/ { + thunder_boot_spi_nor: thunder-boot-spi-nor { + compatible = "rockchip,thunder-boot-sfc"; + reg = <0x21460000 0x4000>; + memory-region-src = <&ramdisk_c>; + memory-region-dst = <&ramdisk_r>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi new file mode 100644 index 000000000000..3c7d15df6207 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126b-thunder-boot.dtsi @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +/ { + ramdisk: ramdisk { + compatible = "rockchip,ramdisk"; + memory-region = <&ramdisk_r>; + }; + + thunder_boot_rkisp: thunder-boot-rkisp { + compatible = "rockchip,thunder-boot-rkisp"; + clocks = <&cru CLK_HPMCU>, + <&cru PCLK_HPMCU_INTMUX>, <&cru PCLK_HPMCU_MAILBOX>, + <&cru PCLK_WDT_HPMCU>, <&cru HCLK_CACHE>, + <&cru PCLK_TIMER>, + <&cru ACLK_ISP>, <&cru HCLK_ISP>, + <&cru CLK_CORE_ISP>, <&cru ISP0CLK_VICAP>, + <&cru ACLK_VICAP>, <&cru HCLK_VICAP>, + <&cru DCLK_VICAP>, <&cru ISP0CLK_VICAP>, + <&cru PCLK_CSI2HOST0>, <&cru PCLK_CSI2HOST1>, + <&cru CLK_I2C4>, <&cru PCLK_I2C4>; + clock-names = "clk_hpmcu", + "pclk_hpmcu_intmux", "pclk_hpmcu_mailbox", + "pclk_wdt_hpmcu", "hclk_cache", + "pclk_timer", + "aclk_isp", "hclk_isp", + "clk_isp_core", "clk_isp_core_vicap", + "aclk_cif","hclk_cif", + "dclk_cif", "isp0clk_cif", + "pclk_csi2host0", "pclk_csi2host1", + "clk_i2c4", "pclk_i2c4"; + }; + + thunder_boot_service: thunder-boot-service { + compatible = "rockchip,thunder-boot-service"; + mbox-names = "amp-rx"; + mboxes = <&hpmcu_mbox0 0>; + resets = <&cru SRST_RESETN_HPMCU_FULL_CLUSTER>; + reset-names = "hpmcu_full_cluster"; + memory-region = <&rtos>; + status = "okay"; + }; +}; + +&hpmcu_mbox0 { + status = "okay"; +}; + +&hw_decompress { + memory-region = <&ramdisk_c>; + status = "okay"; +}; + +&reserved_memory { + /* + * reserved memory layout + * + * H _______________________ + * | | + * | ramdisk_c | + * |_______________________| + * | | + * | ramdisk_r | + * 0x48c40000 |_______________________| + * | | + * | mcu_log | + * 0x48c3c000 |_______________________| + * | | + * | mcu | + * 0x48c00000 |_______________________| + * | | + * | [TEEOS+TA+SHM] | + * 0x48400000 |_______________________| + * | | + * | isp[0..1]_tb_rmem | + * |_______________________| + * | | + * | meta | + * 0x41240000 |_______________________| + * | | + * | fdt | + * 0x41200000 |_______________________| + * | | + * | kernel_r | + * 0x40208000 |_______________________| + * | | + * | bl31 | + * L |_______________________| + * + */ + + meta: meta@41240000 { + /* reg's offset MUST match with RTOS */ + reg = <0x41240000 0x000e0000>; + }; + + rkisp_thunderboot: rkisp@41320000 { + /* reg's offset MUST match with RTOS */ + /* + * vicap, capture raw10, ceil(w*10/8/256)*256*h *4(buf num) + * e.g. 1920x1080: 0xa8c000 + */ + reg = <0x41320000 0xa8c000>; + }; + + rkisp1_thunderboot: rkisp1_thunderboot { + /* vicap capture for a second camera */ + }; + + /* Should enable this node if the security feature is enabled, like TA. */ + tee: tee@48400000 { + reg = <0x48400000 0x00800000>; + status = "disabled"; + }; + + rtos: rtos@48c00000 { + reg = <0x48c00000 0x0003a000>; + }; + + mcu_log: mcu_log@48c3c000 { + reg = <0x48c3c000 0x4000>; + }; + + ramdisk_r: ramdisk_r { + reg = <0x48c40000 (10 * 0x00100000)>; + }; + + ramdisk_c: ramdisk_c { + reg = <0x49640000 (5 * 0x00100000)>; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi index d3c0d1dfb338..b6b931ef72af 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126b.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126b.dtsi @@ -879,7 +879,7 @@ rockchip_suspend: rockchip-suspend { compatible = "rockchip,pm-config"; status = "disabled"; - + rockchip,sleep-debug-en = <0>; rockchip,sleep-mode-config = < (0 | RKPM_SLP_ARMOFF_PMUOFF @@ -903,7 +903,7 @@ thermal_zones: thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <20>; /* milliseconds */ - polling-delay = <1000>; /* milliseconds */ + polling-delay = <100>; /* milliseconds */ thermal-sensors = <&tsadc 0>; trips { soc_crit: soc-crit { @@ -940,7 +940,8 @@ <&cru CLK_UART_FRAC0>, <&cru CLK_UART_FRAC1>, <&cru CLK_CM_FRAC0>, <&cru CLK_CM_FRAC1>, <&cru CLK_CM_FRAC2>, <&cru CLK_AUDIO_FRAC0>, - <&cru CLK_AUDIO_FRAC1>; + <&cru CLK_AUDIO_FRAC1>, <&cru CLK_AISP_PLL_SRC>, + <&cru CLK_CPLL_DIV10>; assigned-clock-rates = <1188000000>, <1000000000>, <786432000>, <786432000>, @@ -950,7 +951,8 @@ <96000000>, <128000000>, <18432000>, <500000000>, <32768000>, <45158400>, - <49152000>; + <49152000>, <786432000>, + <98304000>; }; grf: syscon@20100000 { @@ -1873,6 +1875,10 @@ cpu_code: cpu-code@2 { reg = <0x02 0x2>; }; + specification_serial_number: specification-serial-number@7 { + reg = <0x08 0x1>; + bits = <0 5>; + }; cpu_version: cpu-version@21 { reg = <0x21 0x1>; bits = <3 3>; @@ -1898,9 +1904,6 @@ clocks = <&cru CLK_TSADC>, <&cru PCLK_TSADC>, <&cru CLK_TSADC_PHYCTRL>; clock-names = "tsadc", "apb_pclk", "tsadc_phyctrl"; - resets = <&cru SRST_RESETN_TSADC>, <&cru SRST_PRESETN_TSADC>, - <&cru SRST_RESETN_TSADC_PHYCTRL>; - reset-names = "tsadc", "tsadc-apb", "tsadc-phy"; #thermal-sensor-cells = <1>; rockchip,grf = <&grf>; rockchip,hw-tshut-temp = <120000>; @@ -3013,7 +3016,7 @@ rkcif: rkcif@21d10000 { compatible = "rockchip,rv1126b-cif"; - reg = <0x21d10000 0x1000>; + reg = <0x21d10000 0xf00>; reg-names = "cif_regs"; interrupts = ; interrupt-names = "cif-intr"; @@ -3283,10 +3286,11 @@ npu_opp_table: npu-opp-table { compatible = "operating-points-v2"; - nvmem-cells = <&npu_leakage>; - nvmem-cell-names = "leakage"; + nvmem-cells = <&npu_leakage>, <&specification_serial_number>; + nvmem-cell-names = "leakage", "specification_serial_number"; rockchip,init-freq = <800000>; + rockchip,supported-hw; rockchip,pvtm-voltage-sel = < 0 969 0 970 1009 1 @@ -3305,45 +3309,52 @@ rockchip,pvtm-volt = <1000000>; rockchip,pvtm-ref-temp = <40>; rockchip,pvtm-temp-prop = <0 0>; - rockchip,pvtm-thermal-zone = "npu-thermal"; + rockchip,pvtm-thermal-zone = "cpu-thermal"; rockchip,grf = <&pvtpll_npu>; rockchip,temp-hysteresis = <5000>; rockchip,low-temp = <10000>; rockchip,low-temp-min-volt = <950000>; opp-396000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <396000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-510000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <510000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-600000000 { + opp-supported-hw = <0xff 0xffff>; opp-hz = /bits/ 64 <600000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-700000000 { + opp-supported-hw = <0xf7 0xffff>; opp-hz = /bits/ 64 <700000000>; opp-microvolt = <850000 850000 1050000>; opp-microvolt-L0 = <900000 900000 1050000>; opp-microvolt-L1 = <875000 875000 1050000>; }; opp-800000000 { + opp-supported-hw = <0xf7 0xffff>; opp-hz = /bits/ 64 <800000000>; opp-microvolt = <925000 925000 1050000>; }; opp-900000000 { + opp-supported-hw = <0xf7 0xffff>; opp-hz = /bits/ 64 <900000000>; opp-microvolt = <975000 975000 1050000>; }; opp-950000000 { + opp-supported-hw = <0xf7 0xffff>; opp-hz = /bits/ 64 <950000000>; opp-microvolt = <975000 975000 1050000>; opp-microvolt-L0 = <1000000 1000000 1050000>; diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14-dual-cam.dts b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14-dual-cam.dts index 0f06f0ea6252..4a69dd9b6c7f 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14-dual-cam.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14-dual-cam.dts @@ -4,7 +4,7 @@ */ /dts-v1/; -#include "rv1126b.dtsi" +#include "rv1126bp.dtsi" #include "rv1126bp-evb.dtsi" #include "rv1126bp-evb-v14.dtsi" #include "rv1126bp-evb-v14-dual-cam.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts index 89c248f9eb05..1c97ab42c895 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dts @@ -4,7 +4,7 @@ */ /dts-v1/; -#include "rv1126b.dtsi" +#include "rv1126bp.dtsi" #include "rv1126bp-evb.dtsi" #include "rv1126bp-evb-v14.dtsi" #include "rv1126bp-evb-cam-csi0.dtsi" diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi index 2b85c32c5247..20f67c2a4c78 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb-v14.dtsi @@ -236,7 +236,6 @@ regulator-name = "vdd_arm"; regulator-state-mem { regulator-off-in-suspend; - regulator-suspend-microvolt = <800000>; }; }; @@ -263,15 +262,15 @@ }; }; - vcc_0v8: LDO_REG1 { + vcc_0v9: LDO_REG1 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <800000>; - regulator-name = "vcc_0v8"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vcc_0v9"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <900000>; }; }; @@ -287,15 +286,15 @@ }; }; - vdd0v8_pmu: LDO_REG3 { + vdd0v9_pmu: LDO_REG3 { regulator-always-on; regulator-boot-on; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <800000>; - regulator-name = "vcc0v8_pmu"; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vcc0v9_pmu"; regulator-state-mem { regulator-on-in-suspend; - regulator-suspend-microvolt = <800000>; + regulator-suspend-microvolt = <900000>; }; }; @@ -424,6 +423,25 @@ goodix,rst-gpio = <&gpio5 RK_PA4 GPIO_ACTIVE_HIGH>; goodix,irq-gpio = <&gpio5 RK_PA6 IRQ_TYPE_LEVEL_LOW>; }; + + hynitron: hynitron@5a { + compatible = "hyn,3240"; + reg = <0x5a>; + power-supply = <&vcc_mipi>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + reset-gpios = <&gpio5 RK_PA4 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpio5 RK_PA6 GPIO_ACTIVE_LOW>; + + max-touch-number = <5>; + display-coords = <0 0 1080 1920>; + pos-swap = <0>; + posx-reverse = <0>; + posy-reverse = <0>; + }; }; &mdio { @@ -457,6 +475,24 @@ }; }; + touch { + ts_int_active: ts_int_active { + rockchip,pins = <5 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_reset_active: ts_reset_active { + rockchip,pins = <5 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + ts_int_suspend: ts_int_suspend { + rockchip,pins = <5 RK_PA6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + ts_reset_suspend: ts_reset_suspend { + rockchip,pins = <5 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + wireless-bluetooth { uart2_gpios: uart2-gpios { rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>; @@ -486,6 +522,22 @@ status = "okay"; }; +&rkavsp { + status = "okay"; +}; + +&rkavsp_mmu { + status = "okay"; +}; + +&rkfec { + status = "okay"; +}; + +&rkfec_mmu { + status = "okay"; +}; + &rknpu { rknpu-supply = <&vdd_npu>; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp-evb.dtsi b/arch/arm64/boot/dts/rockchip/rv1126bp-evb.dtsi index 81acd65cf9cf..ec31468906b5 100644 --- a/arch/arm64/boot/dts/rockchip/rv1126bp-evb.dtsi +++ b/arch/arm64/boot/dts/rockchip/rv1126bp-evb.dtsi @@ -383,6 +383,17 @@ status = "okay"; }; +&rgb { + /* + * RV1126 compatible pin output mode 0. + * + * MCU: ROCKCHIP_MCU_DATA_MAP_DATA_1x24 + * BT1120: ROCKCHIP_BT1120_DATA_MAP_DATA_PADLO + * BT656: ROCKCHIP_BT656_DATA_MAP_PADLO + */ + rockchip,data-map-mode = <0>; +}; + &rkdvbm { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rv1126bp.dtsi b/arch/arm64/boot/dts/rockchip/rv1126bp.dtsi new file mode 100644 index 000000000000..627df949fcf3 --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rv1126bp.dtsi @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + */ + +#include "rv1126b.dtsi" + +/ { +}; + +&rgb { + /* + * RV1126 compatible pin output mode 0. + * + * MCU: ROCKCHIP_MCU_DATA_MAP_DATA_1x24 + * BT1120: ROCKCHIP_BT1120_DATA_MAP_DATA_PADLO + * BT656: ROCKCHIP_BT656_DATA_MAP_PADLO + */ + rockchip,data-map-mode = <0>; +}; + +&usb_drd_dwc3 { + phys = <&usb2phy_otg>; + phy-names = "usb2-phy"; + maximum-speed = "high-speed"; + snps,dis_u2_susphy_quirk; + snps,usb2-lpm-disable; + snps,usb2-gadget-lpm-disable; +}; diff --git a/arch/arm64/configs/rk3576_vehicle.config b/arch/arm64/configs/rk3576_vehicle.config index 0df4caf1b138..e49df7c51019 100644 --- a/arch/arm64/configs/rk3576_vehicle.config +++ b/arch/arm64/configs/rk3576_vehicle.config @@ -39,6 +39,7 @@ CONFIG_HZ_1000=y # CONFIG_LIGHT_DEVICE is not set CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MALI400 is not set +CONFIG_MALI_BIFROST=y # CONFIG_MALI_MIDGARD is not set # CONFIG_MFD_MAX96745 is not set # CONFIG_MFD_MAX96755F is not set @@ -47,6 +48,7 @@ CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MFD_RKX110_X120 is not set CONFIG_MFD_SERDES_DISPLAY=y # CONFIG_PROXIMITY_DEVICE is not set +CONFIG_PWM_R7F701=y # CONFIG_R8168 is not set CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_ACT8865 is not set @@ -57,8 +59,6 @@ CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_WL2868C is not set # CONFIG_REGULATOR_XZ3216 is not set # CONFIG_ROCKCHIP_CHARGER_MANAGER is not set -# CONFIG_ROCKCHIP_CLK_INV is not set -# CONFIG_ROCKCHIP_CLK_PVTM is not set CONFIG_ROCKCHIP_DRM_DIRECT_SHOW=y CONFIG_RTC_DRV_S35390A=y # CONFIG_SLUB_SYSFS is not set @@ -73,6 +73,7 @@ CONFIG_RTC_DRV_S35390A=y # CONFIG_SND_SOC_RK817 is not set # CONFIG_SND_SOC_RK_CODEC_DIGITAL is not set # CONFIG_SND_SOC_RT5640 is not set +CONFIG_SPI_SLAVE=y # CONFIG_TOUCHSCREEN_ELAN5515 is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set # CONFIG_TOUCHSCREEN_GSLX680_PAD is not set @@ -93,6 +94,8 @@ CONFIG_TOUCHSCREEN_ILI210X=m # CONFIG_USB_NET_SMSC95XX is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD_PLATFORM=m +CONFIG_VEHICLE_CORE=y +CONFIG_VEHICLE_GPIO_MCU_EXPANDER=y # CONFIG_VIDEO_AW36518 is not set # CONFIG_VIDEO_AW8601 is not set # CONFIG_VIDEO_CN3927V is not set @@ -117,9 +120,36 @@ CONFIG_VIDEO_MAXIM_SERDES=y # CONFIG_VIDEO_S5KJN1 is not set # CONFIG_VIDEO_SGM3784 is not set # CONFIG_VL6180 is not set +CONFIG_LARGE_PAGE_SUPPORT=y +# CONFIG_MALI_ARBITER_SUPPORT is not set +# CONFIG_MALI_ARBITRATION is not set +CONFIG_MALI_BIFROST_DEBUG=y +CONFIG_MALI_BIFROST_DEVFREQ=y +CONFIG_MALI_BIFROST_ENABLE_TRACE=y +CONFIG_MALI_BIFROST_EXPERT=y +CONFIG_MALI_BIFROST_FENCE_DEBUG=y +CONFIG_MALI_BIFROST_GATOR_SUPPORT=y +# CONFIG_MALI_BIFROST_NO_MALI is not set +# CONFIG_MALI_BIFROST_PRFCNT_SET_SECONDARY is not set +CONFIG_MALI_BIFROST_SYSTEM_TRACE=y +# CONFIG_MALI_CSF_SUPPORT is not set +# CONFIG_MALI_DMA_BUF_LEGACY_COMPAT is not set +# CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND is not set +# CONFIG_MALI_HW_ERRATA_1485982_NOT_AFFECTED is not set +# CONFIG_MALI_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE is not set +# CONFIG_MALI_IS_FPGA is not set +# CONFIG_MALI_JOB_DUMP is not set +CONFIG_MALI_PLATFORM_NAME="rk" +CONFIG_MALI_PRFCNT_SET_PRIMARY=y +# CONFIG_MALI_PRFCNT_SET_SELECT_VIA_DEBUG_FS is not set +# CONFIG_MALI_PRFCNT_SET_TERTIARY is not set +CONFIG_MALI_REAL_HW=y +CONFIG_MALI_TRACE_POWER_GPU_WORK_PERIOD=y +CONFIG_PAGE_MIGRATION_SUPPORT=y # CONFIG_ROCKCHIP_DRM_SELF_TEST is not set CONFIG_SERDES_DISPLAY_CHIP_MAXIM=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96749=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772=y @@ -132,10 +162,20 @@ CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121=y CONFIG_SERDES_DISPLAY_CHIP_ROHM=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82=y +CONFIG_SPI_DYNAMIC=y +# CONFIG_SPI_SLAVE_ROCKCHIP_OBJ is not set +# CONFIG_SPI_SLAVE_SYSTEM_CONTROL is not set +# CONFIG_SPI_SLAVE_TIME is not set +CONFIG_VEHICLE_ADC=y +CONFIG_VEHICLE_DUMMY=y +CONFIG_VEHICLE_GPIO=y +CONFIG_VEHICLE_SPI=y +CONFIG_VEHICLE_SPI_PROTOCOL=y CONFIG_VIDEO_MAXIM_CAM_DUMMY=y # CONFIG_VIDEO_MAXIM_CAM_OS04A10 is not set CONFIG_VIDEO_MAXIM_CAM_OV231X=y CONFIG_VIDEO_MAXIM_CAM_OX01F10=y +CONFIG_VIDEO_MAXIM_CAM_OX03C10=y CONFIG_VIDEO_MAXIM_CAM_OX03J10=y CONFIG_VIDEO_MAXIM_CAM_SC320AT=y # CONFIG_VIDEO_MAXIM_DES_MAXIM2C is not set @@ -144,7 +184,3 @@ CONFIG_VIDEO_MAXIM_SER_MAX9295=y CONFIG_VIDEO_MAXIM_SER_MAX96715=y CONFIG_VIDEO_MAXIM_SER_MAX96717=y # CONFIG_VIDEO_REVERSE_IMAGE is not set -CONFIG_MALI_BIFROST=y -CONFIG_MALI_PLATFORM_NAME="rk" -CONFIG_MALI_BIFROST_EXPERT=y -CONFIG_MALI_BIFROST_DEBUG=y diff --git a/arch/arm64/configs/rk3588_vehicle.config b/arch/arm64/configs/rk3588_vehicle.config index 722de0be5abf..59b8c7b085aa 100644 --- a/arch/arm64/configs/rk3588_vehicle.config +++ b/arch/arm64/configs/rk3588_vehicle.config @@ -40,6 +40,7 @@ CONFIG_HZ_1000=y CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MALI400 is not set # CONFIG_MALI_MIDGARD is not set +CONFIG_MALI_VALHALL=y # CONFIG_MFD_MAX96745 is not set # CONFIG_MFD_MAX96755F is not set # CONFIG_MFD_RK618 is not set @@ -47,6 +48,7 @@ CONFIG_LOG_BUF_SHIFT=20 # CONFIG_MFD_RKX110_X120 is not set CONFIG_MFD_SERDES_DISPLAY=y # CONFIG_PROXIMITY_DEVICE is not set +CONFIG_PWM_R7F701=y # CONFIG_R8168 is not set CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_ACT8865 is not set @@ -57,8 +59,6 @@ CONFIG_REALTEK_PHY=y # CONFIG_REGULATOR_WL2868C is not set # CONFIG_REGULATOR_XZ3216 is not set # CONFIG_ROCKCHIP_CHARGER_MANAGER is not set -# CONFIG_ROCKCHIP_CLK_INV is not set -# CONFIG_ROCKCHIP_CLK_PVTM is not set CONFIG_ROCKCHIP_DRM_DIRECT_SHOW=y CONFIG_RTC_DRV_S35390A=y # CONFIG_SLUB_SYSFS is not set @@ -73,6 +73,7 @@ CONFIG_RTC_DRV_S35390A=y # CONFIG_SND_SOC_RK817 is not set # CONFIG_SND_SOC_RK_CODEC_DIGITAL is not set # CONFIG_SND_SOC_RT5640 is not set +CONFIG_SPI_SLAVE=y # CONFIG_TOUCHSCREEN_ELAN5515 is not set # CONFIG_TOUCHSCREEN_GSL3673 is not set # CONFIG_TOUCHSCREEN_GSLX680_PAD is not set @@ -93,6 +94,8 @@ CONFIG_TOUCHSCREEN_ILI210X=m # CONFIG_USB_NET_SMSC95XX is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD_PLATFORM=m +CONFIG_VEHICLE_CORE=y +CONFIG_VEHICLE_GPIO_MCU_EXPANDER=y # CONFIG_VIDEO_AW36518 is not set # CONFIG_VIDEO_AW8601 is not set # CONFIG_VIDEO_CN3927V is not set @@ -117,9 +120,33 @@ CONFIG_VIDEO_MAXIM_SERDES=y # CONFIG_VIDEO_S5KJN1 is not set # CONFIG_VIDEO_SGM3784 is not set # CONFIG_VL6180 is not set +CONFIG_MALI_CSF_INCLUDE_FW=y +# CONFIG_MALI_VALHALL_CORESIGHT is not set +# CONFIG_MALI_VALHALL_CORESTACK is not set +CONFIG_MALI_VALHALL_CSF_SUPPORT=y +CONFIG_MALI_VALHALL_DEBUG=y +CONFIG_MALI_VALHALL_DEVFREQ=y +# CONFIG_MALI_VALHALL_DMA_BUF_LEGACY_COMPAT is not set +# CONFIG_MALI_VALHALL_DMA_BUF_MAP_ON_DEMAND is not set +CONFIG_MALI_VALHALL_ENABLE_TRACE=y +CONFIG_MALI_VALHALL_EXPERT=y +CONFIG_MALI_VALHALL_FENCE_DEBUG=y +CONFIG_MALI_VALHALL_GATOR_SUPPORT=y +# CONFIG_MALI_VALHALL_HW_ERRATA_1485982_NOT_AFFECTED is not set +# CONFIG_MALI_VALHALL_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE is not set +# CONFIG_MALI_VALHALL_JOB_DUMP is not set +# CONFIG_MALI_VALHALL_NO_MALI is not set +CONFIG_MALI_VALHALL_PLATFORM_NAME="rk" +CONFIG_MALI_VALHALL_PRFCNT_SET_PRIMARY=y +# CONFIG_MALI_VALHALL_PRFCNT_SET_SECONDARY is not set +# CONFIG_MALI_VALHALL_PRFCNT_SET_TERTIARY is not set +CONFIG_MALI_VALHALL_REAL_HW=y +CONFIG_MALI_VALHALL_SYSTEM_TRACE=y +CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD=y # CONFIG_ROCKCHIP_DRM_SELF_TEST is not set CONFIG_SERDES_DISPLAY_CHIP_MAXIM=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96749=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755=y CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772=y @@ -132,6 +159,16 @@ CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121=y CONFIG_SERDES_DISPLAY_CHIP_ROHM=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82=y CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82=y +CONFIG_SPI_DYNAMIC=y +# CONFIG_SPI_SLAVE_ROCKCHIP_OBJ is not set +# CONFIG_SPI_SLAVE_SYSTEM_CONTROL is not set +# CONFIG_SPI_SLAVE_TIME is not set +CONFIG_VALHALL_LARGE_PAGE_SUPPORT=y +CONFIG_VEHICLE_ADC=y +CONFIG_VEHICLE_DUMMY=y +CONFIG_VEHICLE_GPIO=y +CONFIG_VEHICLE_SPI=y +CONFIG_VEHICLE_SPI_PROTOCOL=y CONFIG_VIDEO_MAXIM_CAM_DUMMY=y CONFIG_VIDEO_MAXIM_CAM_OS04A10=y CONFIG_VIDEO_MAXIM_CAM_OV231X=y @@ -144,7 +181,3 @@ CONFIG_VIDEO_MAXIM_SER_MAX9295=y CONFIG_VIDEO_MAXIM_SER_MAX96715=y CONFIG_VIDEO_MAXIM_SER_MAX96717=y # CONFIG_VIDEO_REVERSE_IMAGE is not set -CONFIG_MALI_VALHALL=y -CONFIG_MALI_VALHALL_PLATFORM_NAME="rk" -CONFIG_MALI_VALHALL_EXPERT=y -CONFIG_MALI_VALHALL_DEBUG=y diff --git a/arch/arm64/configs/rockchip_amp.config b/arch/arm64/configs/rockchip_amp.config new file mode 100644 index 000000000000..4924a3c6ec87 --- /dev/null +++ b/arch/arm64/configs/rockchip_amp.config @@ -0,0 +1,31 @@ +CONFIG_MAILBOX=y +CONFIG_ROCKCHIP_AMP=y +CONFIG_RPMSG_VIRTIO=y +# CONFIG_ALTERA_MBOX is not set +# CONFIG_ARM_MHU is not set +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set +CONFIG_BLK_MQ_VIRTIO=y +# CONFIG_BT_VIRTIO is not set +# CONFIG_CRYPTO_DEV_VIRTIO is not set +# CONFIG_GPIO_VIRTIO is not set +# CONFIG_HW_RANDOM_VIRTIO is not set +CONFIG_MAILBOX_POLL_PERIOD_US=y +# CONFIG_MAILBOX_TEST is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_PLATFORM_MHU is not set +CONFIG_ROCKCHIP_MBOX=y +# CONFIG_ROCKCHIP_MBOX_DEMO is not set +CONFIG_RPMSG=y +# CONFIG_RPMSG_CHAR is not set +# CONFIG_RPMSG_CTRL is not set +CONFIG_RPMSG_NS=y +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +CONFIG_RPMSG_ROCKCHIP_MBOX=y +# CONFIG_RPMSG_ROCKCHIP_TEST is not set +CONFIG_RPMSG_TTY=y +# CONFIG_SND_SOC_FSL_RPMSG is not set +# CONFIG_SND_VIRTIO is not set +CONFIG_VIRTIO=y +CONFIG_VIRTIO_ANCHOR=y +# CONFIG_VIRTIO_BLK is not set diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index c9910480cf21..3d7f9f3efb03 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -237,6 +237,7 @@ CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_GSL3673=y CONFIG_TOUCHSCREEN_GT1X=y +CONFIG_TOUCHSCREEN_HYN=y CONFIG_TOUCHSCREEN_ELAN=y CONFIG_TOUCHSCREEN_USB_COMPOSITE=y CONFIG_ROCKCHIP_REMOTECTL=y diff --git a/arch/arm64/configs/rv1126b.config b/arch/arm64/configs/rv1126b.config new file mode 100644 index 000000000000..2f8102b20737 --- /dev/null +++ b/arch/arm64/configs/rv1126b.config @@ -0,0 +1,2 @@ +CONFIG_ROCKCHIP_RKNPU_PROC_FS=y +CONFIG_ROCKCHIP_RKNPU_DMA_HEAP=y diff --git a/arch/arm64/configs/rv1126b_defconfig b/arch/arm64/configs/rv1126b_defconfig index 2b537e3ff6cb..8d8a02210559 100644 --- a/arch/arm64/configs/rv1126b_defconfig +++ b/arch/arm64/configs/rv1126b_defconfig @@ -276,6 +276,7 @@ CONFIG_MMC_CQHCI=y CONFIG_MMC_HSQ=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_RK808=y +CONFIG_RTC_DRV_ROCKCHIP=y CONFIG_DMADEVICES=y CONFIG_ROCKCHIP_DMA=y CONFIG_DMABUF_PARTIAL=y diff --git a/drivers/base/arm/memory_group_manager/memory_group_manager.c b/drivers/base/arm/memory_group_manager/memory_group_manager.c index 6789fe87075a..2c5780d42a62 100644 --- a/drivers/base/arm/memory_group_manager/memory_group_manager.c +++ b/drivers/base/arm/memory_group_manager/memory_group_manager.c @@ -310,6 +310,18 @@ static u64 example_mgm_update_gpu_pte(struct memory_group_manager_device *const if (WARN_ON(group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) return pte; + /* If a page is mapped uncached on the CPU but cached on the GPU, it will be considered to + * have Mismatched Memory Attributes (MMA), and the MMA_VIOLATION bit will be set in the + * pte_flags argument. + * + * If the system requires consistent memory attributes external to the GPU, system + * integrators must allocate one of the PBHA values (range 1-15) for this feature, and + * specify the value either via the mma-wa-id devicetree property or via the mma_wa_id + * module parameter, which is then passed into this function via the pbha_id parameter. The + * GPU will continue to use cached transactions internally, but use non-cacheable + * transactions externally. Note that system integrators may choose not to set the PBHA + * value here if their system does not require it. + */ if (pte_flags & BIT(MMA_VIOLATION)) { pr_warn_once("MMA violation! Applying PBHA override workaround to PTE\n"); pte |= ((u64)pbha_id << PTE_PBHA_SHIFT) & PTE_PBHA_MASK; diff --git a/drivers/clk/rockchip/clk-rv1126b.c b/drivers/clk/rockchip/clk-rv1126b.c index e5c324f4d923..ed7cac4c2953 100644 --- a/drivers/clk/rockchip/clk-rv1126b.c +++ b/drivers/clk/rockchip/clk-rv1126b.c @@ -14,6 +14,7 @@ #include #include #include "clk.h" +#include #define RV1126B_GRF_SOC_STATUS0 0x10 @@ -143,6 +144,7 @@ PNAME(clk_timer3_parents_p) = { "clk_timer_root", "mclk_asrc0", "mclk_asrc1" }; PNAME(clk_timer4_parents_p) = { "clk_timer_root", "mclk_asrc2", "mclk_asrc3" }; PNAME(clk_macphy_p) = { "xin24m", "clk_cpll_div20" }; PNAME(mux_ddrphy_p) = { "dpll", "aclk_sysmem" }; +PNAME(clk_cpll_div10_p) = { "gpll", "clk_aisp_pll_src" }; static struct rockchip_pll_clock rv1126b_pll_clks[] __initdata = { [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p, @@ -178,9 +180,6 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE_NOMUX(CLK_CPLL_DIV20, "clk_cpll_div20", "cpll", 0, RV1126B_CLKSEL_CON(1), 0, 5, DFLAGS, RV1126B_CLKGATE_CON(0), 0, GFLAGS), - COMPOSITE(CLK_CPLL_DIV10, "clk_cpll_div10", mux_gpll_cpll_p, 0, - RV1126B_CLKSEL_CON(1), 15, 1, MFLAGS, 5, 5, DFLAGS, - RV1126B_CLKGATE_CON(0), 1, GFLAGS), COMPOSITE_NOMUX(CLK_CPLL_DIV8, "clk_cpll_div8", "cpll", 0, RV1126B_CLKSEL_CON(1), 10, 5, DFLAGS, RV1126B_CLKGATE_CON(0), 2, GFLAGS), @@ -323,9 +322,6 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { COMPOSITE(CLK_ISP_PLL, "clk_isp_pll", mux_gpll_aupll_cpll_p, 0, RV1126B_CLKSEL_CON(61), 10, 2, MFLAGS, 6, 4, DFLAGS, RV1126B_CLKGATE_CON(5), 3, GFLAGS), - COMPOSITE(CLK_AISP_PLL, "clk_aisp_pll", mux_gpll_aupll_cpll_p, 0, - RV1126B_CLKSEL_CON(62), 4, 2, MFLAGS, 0, 3, DFLAGS, - RV1126B_CLKGATE_CON(5), 4, GFLAGS), COMPOSITE(CLK_SARADC0_SRC, "clk_saradc0_src", mux_200m_24m_p, 0, RV1126B_CLKSEL_CON(63), 12, 1, MFLAGS, 0, 3, DFLAGS, RV1126B_CLKGATE_CON(5), 6, GFLAGS), @@ -870,7 +866,7 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { RV1126B_BUSCLKGATE_CON(2), 14, GFLAGS), GATE(HCLK_RKRNG_NS, "hclk_rkrng_ns", "hclk_rkrng_s_ns", 0, RV1126B_BUSCLKGATE_CON(2), 15, GFLAGS), - GATE(CLK_TIMER5, "clk_timer5", "clk_timer_root", 0, + GATE(CLK_TIMER5, "clk_timer5", "clk_timer_root", CLK_IS_CRITICAL, RV1126B_BUSCLKGATE_CON(2), 11, GFLAGS), GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus_root", 0, RV1126B_BUSCLKGATE_CON(3), 0, GFLAGS), @@ -928,9 +924,9 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { RV1126B_BUSCLKGATE_CON(4), 14, GFLAGS), GATE(PCLK_UART7, "pclk_uart7", "pclk_bus_root", 0, RV1126B_BUSCLKGATE_CON(4), 15, GFLAGS), - GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_root", 0, + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_root", CLK_IS_CRITICAL, RV1126B_BUSCLKGATE_CON(5), 0, GFLAGS), - GATE(CLK_TSADC, "clk_tsadc", "xin24m", 0, + GATE(CLK_TSADC, "clk_tsadc", "xin24m", CLK_IS_CRITICAL, RV1126B_BUSCLKGATE_CON(5), 1, GFLAGS), GATE(HCLK_SAI0, "hclk_sai0", "hclk_bus_root", 0, RV1126B_BUSCLKGATE_CON(5), 2, GFLAGS), @@ -966,7 +962,7 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { RV1126B_BUSCLKGATE_CON(6), 4, GFLAGS), GATE(PCLK_OTP_MASK, "pclk_otp_mask", "pclk_bus_root", 0, RV1126B_BUSCLKGATE_CON(6), 6, GFLAGS), - GATE(CLK_TSADC_PHYCTRL, "clk_tsadc_phyctrl", "xin24m", 0, + GATE(CLK_TSADC_PHYCTRL, "clk_tsadc_phyctrl", "xin24m", CLK_IS_CRITICAL, RV1126B_BUSCLKGATE_CON(6), 8, GFLAGS), MUX(LRCK_SRC_ASRC0, "lrck_src_asrc0", lrck_src_asrc_p, 0, RV1126B_BUSCLKSEL_CON(3), 0, 3, MFLAGS), @@ -1019,6 +1015,30 @@ static struct rockchip_clk_branch rv1126b_clk_branches[] __initdata = { RV1126B_PERICLKSEL_CON(1), 12, 1, MFLAGS), }; +static struct rockchip_clk_branch rv1126b_clk_cpll_div10_v0[] __initdata = { + COMPOSITE_NODIV(CLK_AISP_PLL_SRC, "clk_aisp_pll_src", mux_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(62), 4, 2, MFLAGS, + RV1126B_CLKGATE_CON(5), 4, GFLAGS), + DIV(CLK_AISP_PLL, "clk_aisp_pll", "clk_aisp_pll_src", 0, + RV1126B_CLKSEL_CON(62), 0, 3, DFLAGS), + + COMPOSITE(CLK_CPLL_DIV10, "clk_cpll_div10", mux_gpll_cpll_p, 0, + RV1126B_CLKSEL_CON(1), 15, 1, MFLAGS, 5, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 1, GFLAGS), +}; + +static struct rockchip_clk_branch rv1126b_clk_cpll_div10[] __initdata = { + COMPOSITE_NODIV(CLK_AISP_PLL_SRC, "clk_aisp_pll_src", mux_gpll_aupll_cpll_p, 0, + RV1126B_CLKSEL_CON(62), 4, 2, MFLAGS, + RV1126B_CLKGATE_CON(5), 4, GFLAGS), + DIV(CLK_AISP_PLL, "clk_aisp_pll", "clk_aisp_pll_src", 0, + RV1126B_CLKSEL_CON(62), 0, 3, DFLAGS), + + COMPOSITE(CLK_CPLL_DIV10, "clk_cpll_div10", clk_cpll_div10_p, 0, + RV1126B_CLKSEL_CON(1), 15, 1, MFLAGS, 5, 5, DFLAGS, + RV1126B_CLKGATE_CON(0), 1, GFLAGS), +}; + static struct rockchip_clk_branch rv1126b_armclk __initdata = MUX(ARMCLK, "armclk", mux_armclk_p, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, RV1126B_CORECLKSEL_CON(0), 1, 1, MFLAGS); @@ -1061,6 +1081,14 @@ static void __init rv1126b_clk_init(struct device_node *np) ARRAY_SIZE(rv1126b_pll_clks), RV1126B_GRF_SOC_STATUS0); + rockchip_soc_id_init(); + if (rockchip_get_cpu_version()) + rockchip_clk_register_branches(ctx, rv1126b_clk_cpll_div10, + ARRAY_SIZE(rv1126b_clk_cpll_div10)); + else + rockchip_clk_register_branches(ctx, rv1126b_clk_cpll_div10_v0, + ARRAY_SIZE(rv1126b_clk_cpll_div10_v0)); + rockchip_clk_register_branches(ctx, rv1126b_clk_branches, ARRAY_SIZE(rv1126b_clk_branches)); diff --git a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c index 2c7417bd6506..8547a6863e48 100644 --- a/drivers/gpu/arm/bifrost/context/mali_kbase_context.c +++ b/drivers/gpu/arm/bifrost/context/mali_kbase_context.c @@ -72,6 +72,74 @@ static struct kbase_process *find_process_node(struct rb_node *node, pid_t tgid) return kprcs; } +static ssize_t kbase_kctx_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct kobj_attribute *kattr = container_of(attr, struct kobj_attribute, attr); + + if (kattr->show) + return kattr->show(kobj, kattr, buf); + + return -EIO; +} + +static ssize_t kbase_total_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kprcs->total_gpu_pages << PAGE_SHIFT); +} + +static ssize_t kbase_private_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + struct kbase_context *tmp_kctx; + size_t total_pages = 0; + + /* Sum up used_pages from all contexts in the process */ + list_for_each_entry(tmp_kctx, &kprcs->kctx_list, kprcs_link) { + total_pages += atomic_read(&tmp_kctx->used_pages); + } + + return scnprintf(buf, PAGE_SIZE, "%zu\n", total_pages << PAGE_SHIFT); +} + +static struct kobj_attribute kbase_total_gpu_mem_attr = { + .attr = { + .name = "total_gpu_mem", + .mode = 0444, + }, + .show = kbase_total_gpu_mem_show, + .store = NULL, +}; + +static struct kobj_attribute kbase_private_gpu_mem_attr = { + .attr = { + .name = "private_gpu_mem", + .mode = 0444, + }, + .show = kbase_private_gpu_mem_show, + .store = NULL, +}; + +static struct attribute *kbase_kctx_attrs[] = { + &kbase_total_gpu_mem_attr.attr, + &kbase_private_gpu_mem_attr.attr, + NULL, +}; + +static const struct attribute_group kbase_kctx_attr_group = { + .attrs = kbase_kctx_attrs, +}; + +static const struct sysfs_ops kbase_kctx_sysfs_ops = { + .show = kbase_kctx_attr_show, +}; + +static const struct kobj_type kbase_kctx_ktype = { + .sysfs_ops = &kbase_kctx_sysfs_ops, + .default_groups = (const struct attribute_group *[]) { &kbase_kctx_attr_group, NULL }, +}; + /** * kbase_insert_kctx_to_process - Initialise kbase process context. * @@ -100,6 +168,8 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) */ if (!kprcs) { struct rb_node **new = &prcs_root->rb_node, *parent = NULL; + char kctx_name[64]; + int ret = 0; kprcs = kzalloc(sizeof(*kprcs), GFP_KERNEL); if (kprcs == NULL) @@ -109,6 +179,15 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) kprcs->dma_buf_root = RB_ROOT; kprcs->total_gpu_pages = 0; + if (unlikely(!scnprintf(kctx_name, 64, "%d", tgid))) + return -ENOMEM; + + ret = kobject_init_and_add(&kprcs->kobj, &kbase_kctx_ktype, kctx->kbdev->kprcs_kobj, kctx_name); + if (ret) { + dev_err(kctx->kbdev->dev, "Failed to create kctx kobject"); + kobject_put(&kprcs->kobj); + } + while (*new) { struct kbase_process *prcs_node; @@ -260,6 +339,7 @@ static void kbase_remove_kctx_from_process(struct kbase_context *kctx) * we can remove it from the process rb_tree. */ if (list_empty(&kprcs->kctx_list)) { + kobject_put(&kprcs->kobj); rb_erase(&kprcs->kprcs_node, &kctx->kbdev->process_root); /* Add checks, so that the terminating process Should not * hold any gpu_memory. diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 9cd02fec4a10..46c91c6fcb6c 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -3182,6 +3182,56 @@ static ssize_t gpuinfo_show(struct device *dev, struct device_attribute *attr, c } static DEVICE_ATTR_RO(gpuinfo); +/** + * gpumem_private_show - Show callback for the gpumem_private sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the current number of pages used by the GPU. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t private_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%llu\n", (u64)atomic_read(&(kbdev->memdev.used_pages)) << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(private_gpu_mem); + +/** + * total_gpu_mem_show - Show callback for the total_gpu_mem sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the total GPU memory including dmabuf memory. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t total_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kbdev->total_gpu_pages << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(total_gpu_mem); + /** * dvfs_period_store - Store callback for the dvfs_period sysfs file. * @dev: The device with sysfs file is for @@ -5556,6 +5606,8 @@ static struct attribute *kbase_attrs[] = { &dev_attr_soft_job_timeout.attr, #endif /* !MALI_USE_CSF */ &dev_attr_gpuinfo.attr, + &dev_attr_total_gpu_mem.attr, + &dev_attr_private_gpu_mem.attr, &dev_attr_dvfs_period.attr, &dev_attr_pm_poweroff.attr, &dev_attr_reset_timeout.attr, @@ -5631,6 +5683,14 @@ int kbase_sysfs_init(struct kbase_device *kbdev) sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); } + kbdev->kprcs_kobj = kobject_create_and_add("kprcs", &kbdev->dev->kobj); + if (!kbdev->kprcs_kobj) { + dev_err(kbdev->dev, "Creation of kprcs sysfs group failed"); + sysfs_remove_group(&kbdev->dev->kobj, &kbase_mempool_attr_group); + sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); + sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + } + return err; } @@ -5639,6 +5699,7 @@ void kbase_sysfs_term(struct kbase_device *kbdev) sysfs_remove_group(&kbdev->dev->kobj, &kbase_mempool_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + kobject_put(kbdev->kprcs_kobj); put_device(kbdev->dev); } diff --git a/drivers/gpu/arm/bifrost/mali_kbase_defs.h b/drivers/gpu/arm/bifrost/mali_kbase_defs.h index b97df15f7a17..a4c0dbc26567 100755 --- a/drivers/gpu/arm/bifrost/mali_kbase_defs.h +++ b/drivers/gpu/arm/bifrost/mali_kbase_defs.h @@ -688,6 +688,7 @@ struct kbase_devfreq_queue_info { /** * struct kbase_process - Representing an object of a kbase process instantiated * when the first kbase context is created under it. + * @kobj: Kernel object for sysfs representation of the process. * @tgid: Thread group ID. * @total_gpu_pages: Total gpu pages allocated across all the contexts * of this process, it accounts for both native allocations @@ -703,6 +704,7 @@ struct kbase_devfreq_queue_info { * imported multiple times for the process. */ struct kbase_process { + struct kobject kobj; pid_t tgid; size_t total_gpu_pages; struct list_head kctx_list; @@ -1109,6 +1111,7 @@ struct kbase_device { unsigned int nr_regulators; #endif /* CONFIG_REGULATOR */ char devname[DEVNAME_SIZE]; + struct kobject *kprcs_kobj; u32 id; #if !IS_ENABLED(CONFIG_MALI_REAL_HW) diff --git a/drivers/gpu/arm/valhall/Kbuild b/drivers/gpu/arm/valhall/Kbuild index e2a58ea59d20..41afecc01294 100644 --- a/drivers/gpu/arm/valhall/Kbuild +++ b/drivers/gpu/arm/valhall/Kbuild @@ -63,7 +63,7 @@ endif # # Driver version string which is returned to userspace via an ioctl -MALI_RELEASE_NAME ?= '"g28p0-00eac0"' +MALI_RELEASE_NAME ?= '"g29p0-00eac0"' # Set up defaults if not defined by build system ifeq ($(CONFIG_MALI_VALHALL_DEBUG), y) MALI_UNIT_TEST = 1 @@ -79,13 +79,10 @@ MALI_PLATFORM_DIR := $(shell echo $(CONFIG_MALI_VALHALL_PLATFORM_NAME)) ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) MALI_JIT_PRESSURE_LIMIT_BASE = 0 - MALI_USE_CSF = 1 else MALI_JIT_PRESSURE_LIMIT_BASE ?= 1 - MALI_USE_CSF ?= 0 endif - ifneq ($(CONFIG_MALI_VALHALL_KUTF), n) MALI_KERNEL_TEST_API ?= 1 else @@ -104,7 +101,6 @@ endif # ccflags-y = \ -DMALI_CUSTOMER_RELEASE=$(MALI_CUSTOMER_RELEASE) \ - -DMALI_USE_CSF=$(MALI_USE_CSF) \ -DMALI_KERNEL_TEST_API=$(MALI_KERNEL_TEST_API) \ -DMALI_UNIT_TEST=$(MALI_UNIT_TEST) \ -DMALI_COVERAGE=$(MALI_COVERAGE) \ @@ -112,7 +108,6 @@ ccflags-y = \ -DMALI_JIT_PRESSURE_LIMIT_BASE=$(MALI_JIT_PRESSURE_LIMIT_BASE) \ -DMALI_PLATFORM_DIR=$(MALI_PLATFORM_DIR) - ifeq ($(KBUILD_EXTMOD),) # in-tree ccflags-y +=-DMALI_KBASE_PLATFORM_PATH=../../$(src)/platform/$(CONFIG_MALI_VALHALL_PLATFORM_NAME) @@ -183,23 +178,6 @@ valhall_kbase-$(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) += \ mali_power_gpu_work_period_trace.o \ mali_kbase_gpu_metrics.o -ifneq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += \ - mali_kbase_jm.o \ - mali_kbase_dummy_job_wa.o \ - mali_kbase_debug_job_fault.o \ - mali_kbase_event.o \ - mali_kbase_jd.o \ - mali_kbase_jd_debugfs.o \ - mali_kbase_js.o \ - mali_kbase_js_ctx_attr.o \ - mali_kbase_kinstr_jm.o - - valhall_kbase-$(CONFIG_SYNC_FILE) += \ - mali_kbase_fence_ops.o \ - mali_kbase_fence.o -endif - INCLUDE_SUBDIR = \ $(src)/arbiter/Kbuild \ diff --git a/drivers/gpu/arm/valhall/Kconfig b/drivers/gpu/arm/valhall/Kconfig index d821acbdafe0..b54098a24b3d 100644 --- a/drivers/gpu/arm/valhall/Kconfig +++ b/drivers/gpu/arm/valhall/Kconfig @@ -324,15 +324,6 @@ config MALI_VALHALL_HW_ERRATA_1485982_USE_CLOCK_ALTERNATIVE endif -config MALI_VALHALL_ARBITRATION - tristate "Enable Virtualization reference code" - depends on MALI_VALHALL - default n - help - Enables the build of several reference modules used in the reference - virtualization setup for Mali - If unsure, say N. - config MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD bool "Enable per-application GPU metrics tracepoints" depends on MALI_VALHALL diff --git a/drivers/gpu/arm/valhall/Makefile b/drivers/gpu/arm/valhall/Makefile index f5871b01a3be..1bc641fb1119 100644 --- a/drivers/gpu/arm/valhall/Makefile +++ b/drivers/gpu/arm/valhall/Makefile @@ -39,7 +39,6 @@ ifeq ($(MALI_KCONFIG_EXT_PREFIX),) CONFIG_MALI_VALHALL_PLATFORM_NAME ?= "devicetree" CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD ?= y CONFIG_MALI_BIFROST_GATOR_SUPPORT ?= y - CONFIG_MALI_VALHALL_ARBITRATION ?= n CONFIG_MALI_KUTF_PTM_TESTS ?= n @@ -143,7 +142,6 @@ ifeq ($(MALI_KCONFIG_EXT_PREFIX),) endif else # Prevent misuse when CONFIG_MALI_BIFROST=n - CONFIG_MALI_VALHALL_ARBITRATION = n CONFIG_MALI_VALHALL_KUTF = n CONFIG_MALI_VALHALL_KUTF_IRQ_TEST = n CONFIG_MALI_VALHALL_KUTF_CLK_RATE_TRACE = n @@ -155,7 +153,6 @@ ifeq ($(MALI_KCONFIG_EXT_PREFIX),) CONFIG_MALI_BIFROST \ CONFIG_MALI_VALHALL_CSF_SUPPORT \ CONFIG_MALI_BIFROST_GATOR_SUPPORT \ - CONFIG_MALI_VALHALL_ARBITRATION \ CONFIG_MALI_KUTF_PTM_TESTS \ CONFIG_MALI_VALHALL_REAL_HW \ CONFIG_MALI_BIFROST_DEVFREQ \ diff --git a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.c b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.c index 49b42a6ec2c0..b69b315ccd3d 100644 --- a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.c +++ b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.c @@ -36,264 +36,6 @@ #error "Unsupported Mali Arbiter interface version." #endif -static void on_max_config(struct device *dev, uint32_t max_l2_slices, uint32_t max_core_mask) -{ - struct kbase_device *kbdev; - - if (!dev) { - pr_err("%s(): dev is NULL", __func__); - return; - } - - kbdev = dev_get_drvdata(dev); - if (!kbdev) { - dev_err(dev, "%s(): kbdev is NULL", __func__); - return; - } - - if (!max_l2_slices || !max_core_mask) { - dev_dbg(dev, "%s(): max_config ignored as one of the fields is zero", __func__); - return; - } - - /* set the max config info in the kbase device */ - kbase_arbiter_set_max_config(kbdev, max_l2_slices, max_core_mask); -} - -/** - * on_update_freq() - Updates GPU clock frequency - * @dev: arbiter interface device handle - * @freq: GPU clock frequency value reported from arbiter - * - * call back function to update GPU clock frequency with - * new value from arbiter - */ -static void on_update_freq(struct device *dev, uint32_t freq) -{ - struct kbase_device *kbdev; - - if (!dev) { - pr_err("%s(): dev is NULL", __func__); - return; - } - - kbdev = dev_get_drvdata(dev); - if (!kbdev) { - dev_err(dev, "%s(): kbdev is NULL", __func__); - return; - } - - kbase_arbiter_pm_update_gpu_freq(&kbdev->arb.arb_freq, freq); -} - -/** - * on_gpu_stop() - sends KBASE_VM_GPU_STOP_EVT event on VM stop - * @dev: arbiter interface device handle - * - * call back function to signal a GPU STOP event from arbiter interface - */ -static void on_gpu_stop(struct device *dev) -{ - struct kbase_device *kbdev; - - if (!dev) { - pr_err("%s(): dev is NULL", __func__); - return; - } - - kbdev = dev_get_drvdata(dev); - if (!kbdev) { - dev_err(dev, "%s(): kbdev is NULL", __func__); - return; - } - - KBASE_TLSTREAM_TL_ARBITER_STOP_REQUESTED(kbdev, kbdev); - KBASE_KTRACE_ADD(kbdev, ARB_GPU_STOP_REQUESTED, NULL, 0); - kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_STOP_EVT); -} - -/** - * on_gpu_granted() - sends KBASE_VM_GPU_GRANTED_EVT event on GPU granted - * @dev: arbiter interface device handle - * - * call back function to signal a GPU GRANT event from arbiter interface - */ -static void on_gpu_granted(struct device *dev) -{ - struct kbase_device *kbdev; - - if (!dev) { - pr_err("%s(): dev is NULL", __func__); - return; - } - - kbdev = dev_get_drvdata(dev); - if (!kbdev) { - dev_err(dev, "%s(): kbdev is NULL", __func__); - return; - } - - KBASE_TLSTREAM_TL_ARBITER_GRANTED(kbdev, kbdev); - KBASE_KTRACE_ADD(kbdev, ARB_GPU_GRANTED, NULL, 0); - kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_GRANTED_EVT); -} - -/** - * on_gpu_lost() - sends KBASE_VM_GPU_LOST_EVT event on GPU granted - * @dev: arbiter interface device handle - * - * call back function to signal a GPU LOST event from arbiter interface - */ -static void on_gpu_lost(struct device *dev) -{ - struct kbase_device *kbdev; - - if (!dev) { - pr_err("%s(): dev is NULL", __func__); - return; - } - - kbdev = dev_get_drvdata(dev); - if (!kbdev) { - dev_err(dev, "%s(): kbdev is NULL", __func__); - return; - } - KBASE_TLSTREAM_TL_ARBITER_LOST(kbdev, kbdev); - KBASE_KTRACE_ADD(kbdev, ARB_GPU_LOST, NULL, 0); - kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_LOST_EVT); -} - -static int kbase_arbif_of_init(struct kbase_device *kbdev) -{ - struct arbiter_if_dev *arb_if; - struct device_node *arbiter_if_node; - struct platform_device *pdev; - - if (!IS_ENABLED(CONFIG_OF)) { - /* - * Return -ENODEV in the event CONFIG_OF is not available and let the - * internal AW check for suitability for arbitration. - */ - return -ENODEV; - } - - arbiter_if_node = of_parse_phandle(kbdev->dev->of_node, "arbiter-if", 0); - if (!arbiter_if_node) - arbiter_if_node = of_parse_phandle(kbdev->dev->of_node, "arbiter_if", 0); - if (!arbiter_if_node) { - dev_dbg(kbdev->dev, "No arbiter_if in Device Tree"); - /* no arbiter interface defined in device tree */ - kbdev->arb.arb_dev = NULL; - kbdev->arb.arb_if = NULL; - return -ENODEV; - } - - pdev = of_find_device_by_node(arbiter_if_node); - if (!pdev) { - dev_err(kbdev->dev, "Failed to find arbiter_if device"); - return -EPROBE_DEFER; - } - - if (!pdev->dev.driver || !try_module_get(pdev->dev.driver->owner)) { - dev_err(kbdev->dev, "arbiter_if driver not available"); - put_device(&pdev->dev); - return -EPROBE_DEFER; - } - kbdev->arb.arb_dev = &pdev->dev; - arb_if = platform_get_drvdata(pdev); - if (!arb_if) { - dev_err(kbdev->dev, "arbiter_if driver not ready"); - module_put(pdev->dev.driver->owner); - put_device(&pdev->dev); - return -EPROBE_DEFER; - } - - kbdev->arb.arb_if = arb_if; - return 0; -} - -static void kbase_arbif_of_term(struct kbase_device *kbdev) -{ - if (!IS_ENABLED(CONFIG_OF)) - return; - - if (kbdev->arb.arb_dev) { - module_put(kbdev->arb.arb_dev->driver->owner); - put_device(kbdev->arb.arb_dev); - } - kbdev->arb.arb_dev = NULL; -} - - -/** - * kbase_arbif_init() - Kbase Arbiter interface initialisation. - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * - * Initialise Kbase Arbiter interface and assign callback functions. - * - * Return: - * * 0 - the interface was initialized or was not specified - * * in the device tree. - * * -EFAULT - the interface was specified but failed to initialize. - * * -EPROBE_DEFER - module dependencies are not yet available. - */ -int kbase_arbif_init(struct kbase_device *kbdev) -{ - struct arbiter_if_arb_vm_ops ops; - struct arbiter_if_dev *arb_if; - int err = 0; - - /* Tries to init with 'arbiter-if' if present in devicetree */ - err = kbase_arbif_of_init(kbdev); - - if (err == -ENODEV) { - /* devicetree does not support arbitration */ - return -EPERM; - } - - if (err) - return err; - - ops.arb_vm_gpu_stop = on_gpu_stop; - ops.arb_vm_gpu_granted = on_gpu_granted; - ops.arb_vm_gpu_lost = on_gpu_lost; - ops.arb_vm_max_config = on_max_config; - ops.arb_vm_update_freq = on_update_freq; - - kbdev->arb.arb_freq.arb_freq = 0; - kbdev->arb.arb_freq.freq_updated = false; - mutex_init(&kbdev->arb.arb_freq.arb_freq_lock); - - arb_if = kbdev->arb.arb_if; - - if (arb_if == NULL) { - dev_err(kbdev->dev, "No arbiter interface present"); - goto failure_term; - } - - if (!arb_if->vm_ops.vm_arb_register_dev) { - dev_err(kbdev->dev, "arbiter_if registration callback not present"); - goto failure_term; - } - - /* register kbase arbiter_if callbacks */ - err = arb_if->vm_ops.vm_arb_register_dev(arb_if, kbdev->dev, &ops); - if (err) { - dev_err(kbdev->dev, "Failed to register with arbiter. (err = %d)", err); - goto failure_term; - } - - return 0; - -failure_term: - { - kbase_arbif_of_term(kbdev); - } - - if (err != -EPROBE_DEFER) - err = -EFAULT; - return err; -} /** * kbase_arbif_destroy() - De-init Kbase arbiter interface @@ -308,9 +50,6 @@ void kbase_arbif_destroy(struct kbase_device *kbdev) if (arb_if && arb_if->vm_ops.vm_arb_unregister_dev) arb_if->vm_ops.vm_arb_unregister_dev(kbdev->arb.arb_if); - { - kbase_arbif_of_term(kbdev); - } kbdev->arb.arb_if = NULL; } diff --git a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.h b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.h index c77792115e4d..8da8e3c1d0d9 100644 --- a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.h +++ b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbif.h @@ -51,21 +51,6 @@ enum kbase_arbif_evt { }; -/** - * kbase_arbif_init() - Initialize the arbiter interface functionality. - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * - * Initialize the arbiter interface and also determines - * if Arbiter functionality is required. - * - * Return: - * * 0 - the interface was initialized or was not specified - * * in the device tree. - * * -EFAULT - the interface was specified but failed to initialize. - * * -EPROBE_DEFER - module dependencies are not yet available. - */ -int kbase_arbif_init(struct kbase_device *kbdev); - /** * kbase_arbif_destroy() - Cleanups the arbiter interface functionality. * @kbdev: The kbase device structure for the device (must be a valid pointer) diff --git a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbiter_pm.c b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbiter_pm.c index 1378e6486c37..57952106429a 100644 --- a/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbiter_pm.c +++ b/drivers/gpu/arm/valhall/arbiter/mali_kbase_arbiter_pm.c @@ -31,9 +31,7 @@ #include #include -#if MALI_USE_CSF #include -#endif /* A dmesg warning will occur if the GPU is not granted * after the following time (in milliseconds) has ellapsed. @@ -299,7 +297,9 @@ int kbase_arbiter_pm_early_init(struct kbase_device *kbdev) arb_vm_state->vm_request_timer.function = request_timer_callback; kbdev->pm.arb_vm_state = arb_vm_state; - err = kbase_arbif_init(kbdev); + /* platform does not support arbitration */ + err = -EPERM; + if (err) { if (err != -EPERM) dev_err(kbdev->dev, "Failed to initialise arbif module. (err = %d)", err); @@ -360,10 +360,8 @@ void kbase_arbiter_pm_early_term(struct kbase_device *kbdev) cancel_request_timer(kbdev); mutex_lock(&arb_vm_state->vm_state_lock); - if (arb_vm_state->vm_state > KBASE_VM_STATE_STOPPED_GPU_REQUESTED) { - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); + if (arb_vm_state->vm_state > KBASE_VM_STATE_STOPPED_GPU_REQUESTED) kbase_arbif_gpu_stopped(kbdev, false); - } mutex_unlock(&arb_vm_state->vm_state_lock); destroy_workqueue(arb_vm_state->vm_arb_wq); kbase_arbif_destroy(kbdev); @@ -410,6 +408,7 @@ void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev) { bool request_gpu = false; struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state; + unsigned long flags; lockdep_assert_held(&arb_vm_state->vm_state_lock); @@ -420,17 +419,6 @@ void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev) dev_dbg(kbdev->dev, "%s %s\n", __func__, kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state)); - /* - * Release the interrupts on external arb_if to address Xen requirements. - * Interrupts are not released with internal arb_if as the IRQs are required - * to handle messaging to/from Arbiter/Resource Group. - */ - if (arb_vm_state->interrupts_installed - ) { - arb_vm_state->interrupts_installed = false; - kbase_release_interrupts(kbdev); - } - switch (arb_vm_state->vm_state) { case KBASE_VM_STATE_STOPPING_ACTIVE: request_gpu = true; @@ -447,7 +435,17 @@ void kbase_arbiter_pm_vm_stopped(struct kbase_device *kbdev) break; } - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (kbdev->pm.backend.gpu_lost_pending) { + { + kbdev->csf.firmware_reload_needed = true; + dev_warn(kbdev->dev, "%s(): GPU LOST detected, marking MCU for cold boot", + __func__); + } + } + kbase_io_set_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); + kbdev->pm.backend.gpu_lost_pending = false; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); { kbase_arbif_gpu_stopped(kbdev, request_gpu); @@ -550,16 +548,6 @@ static void kbase_arbiter_pm_vm_gpu_start(struct kbase_device *kbdev) break; case KBASE_VM_STATE_STOPPED_GPU_REQUESTED: kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_STARTING); - arb_vm_state->interrupts_installed = true; - /* - * Re-install interrupts that were released for external arb_if to - * address Xen requirements. Interrupts are not released with internal - * arb_if as the IRQs are required to handle messaging to/from - * Arbiter/Resource Group. - */ - { - kbase_install_interrupts(kbdev); - } /* * GPU GRANTED received while in stop can be a result of a * repartitioning. @@ -569,7 +557,6 @@ static void kbase_arbiter_pm_vm_gpu_start(struct kbase_device *kbdev) queue_work(arb_vm_state->vm_arb_wq, &arb_vm_state->vm_resume_work); break; case KBASE_VM_STATE_SUSPEND_WAIT_FOR_GRANT: - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); kbase_arbif_gpu_stopped(kbdev, false); kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_SUSPENDED); break; @@ -637,7 +624,6 @@ static void kbase_arbiter_pm_vm_gpu_stop(struct kbase_device *kbdev) static void kbase_gpu_lost(struct kbase_device *kbdev) { struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state; - bool handle_gpu_lost = false; lockdep_assert_held(&arb_vm_state->vm_state_lock); @@ -648,13 +634,11 @@ static void kbase_gpu_lost(struct kbase_device *kbdev) dev_warn(kbdev->dev, "GPU lost in state %s", kbase_arbiter_pm_vm_state_str(arb_vm_state->vm_state)); kbase_arbiter_pm_vm_gpu_stop(kbdev); - handle_gpu_lost = true; break; case KBASE_VM_STATE_STOPPING_IDLE: case KBASE_VM_STATE_STOPPING_ACTIVE: case KBASE_VM_STATE_SUSPEND_PENDING: - dev_dbg(kbdev->dev, "GPU lost while stopping"); - handle_gpu_lost = true; + dev_warn(kbdev->dev, "GPU lost while stopping"); break; case KBASE_VM_STATE_SUSPENDED: case KBASE_VM_STATE_STOPPED: @@ -668,8 +652,6 @@ static void kbase_gpu_lost(struct kbase_device *kbdev) default: break; } - if (handle_gpu_lost) - kbase_pm_handle_gpu_lost(kbdev); } /** @@ -798,6 +780,7 @@ static void kbase_arbiter_pm_vm_os_resume(struct kbase_device *kbdev) void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev, enum kbase_arbif_evt evt) { struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state; + unsigned long flags; if (!kbase_has_arbiter(kbdev)) return; @@ -816,6 +799,13 @@ void kbase_arbiter_pm_vm_event(struct kbase_device *kbdev, enum kbase_arbif_evt break; case KBASE_VM_GPU_LOST_EVT: dev_dbg(kbdev->dev, "KBASE_ARBIF_GPU_LOST_EVT!"); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (!kbdev->pm.backend.gpu_lost_pending) { + dev_dbg(kbdev->dev, "skipping GPU_LOST handling"); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + break; + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); kbase_gpu_lost(kbdev); break; case KBASE_VM_OS_SUSPEND_EVENT: @@ -933,10 +923,6 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev, struct kbase_arbiter_vm_state *arb_vm_state = kbdev->pm.arb_vm_state; int res = 0; -#if !MALI_USE_CSF - CSTD_UNUSED(sched_lock_held); -#endif - if (!kbase_has_arbiter(kbdev)) return res; @@ -949,7 +935,8 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev, kbase_arbiter_pm_vm_set_state(kbdev, KBASE_VM_STATE_STOPPED_GPU_REQUESTED); kbase_arbif_gpu_request(kbdev); start_request_timer(kbdev); - } else if (arb_vm_state->vm_state == KBASE_VM_STATE_STOPPING_ACTIVE) { + } else if (suspend_handler != KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE && + arb_vm_state->vm_state == KBASE_VM_STATE_STOPPING_ACTIVE) { res = 1; break; } else if (arb_vm_state->vm_state == KBASE_VM_STATE_INITIALIZING_WITH_GPU) @@ -985,15 +972,11 @@ int kbase_arbiter_pm_ctx_active_handle_suspend(struct kbase_device *kbdev, atomic_inc(&kbdev->pm.gpu_users_waiting); mutex_unlock(&arb_vm_state->vm_state_lock); kbase_pm_unlock(kbdev); -#if MALI_USE_CSF if (sched_lock_held) kbase_csf_scheduler_unlock(kbdev); -#endif kbase_arbiter_pm_vm_wait_gpu_assignment(kbdev); -#if MALI_USE_CSF if (sched_lock_held) kbase_csf_scheduler_lock(kbdev); -#endif kbase_pm_lock(kbdev); mutex_lock(&arb_vm_state->vm_state_lock); atomic_dec(&kbdev->pm.gpu_users_waiting); diff --git a/drivers/gpu/arm/valhall/backend/gpu/Kbuild b/drivers/gpu/arm/valhall/backend/gpu/Kbuild index 78f362d9046e..dd6b3bb038c8 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/Kbuild +++ b/drivers/gpu/arm/valhall/backend/gpu/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -33,16 +33,6 @@ valhall_kbase-y += \ backend/gpu/mali_kbase_l2_mmu_config.o \ backend/gpu/mali_kbase_clk_rate_trace_mgr.o -ifeq ($(MALI_USE_CSF),0) - valhall_kbase-y += \ - backend/gpu/mali_kbase_instr_backend.o \ - backend/gpu/mali_kbase_jm_as.o \ - backend/gpu/mali_kbase_debug_job_fault_backend.o \ - backend/gpu/mali_kbase_jm_hw.o \ - backend/gpu/mali_kbase_jm_rb.o \ - backend/gpu/mali_kbase_js_backend.o -endif - valhall_kbase-$(CONFIG_MALI_VALHALL_DEVFREQ) += \ backend/gpu/mali_kbase_devfreq.o diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_cache_policy_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_cache_policy_backend.c index aa8436420234..ed42d5349978 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_cache_policy_backend.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_cache_policy_backend.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -27,7 +27,6 @@ void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, u32 mode) kbdev->current_gpu_coherency_mode = mode; -#if MALI_USE_CSF if (kbdev->gpu_props.gpu_id.arch_id >= GPU_ID_ARCH_MAKE(12, 0, 1)) { /* AMBA_ENABLE present from 12.0.1 */ u32 val = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(AMBA_ENABLE)); @@ -38,14 +37,10 @@ void kbase_cache_set_coherency_mode(struct kbase_device *kbdev, u32 mode) /* Fallback to COHERENCY_ENABLE for older versions */ kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(COHERENCY_ENABLE), mode); } -#else /* MALI_USE_CSF */ - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(COHERENCY_ENABLE), mode); -#endif /* MALI_USE_CSF */ } void kbase_amba_set_shareable_cache_support(struct kbase_device *kbdev) { -#if MALI_USE_CSF /* AMBA registers only present from 12.0.1 */ if (kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(12, 0, 1)) @@ -60,5 +55,4 @@ void kbase_amba_set_shareable_cache_support(struct kbase_device *kbdev) kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(AMBA_ENABLE), val); } } -#endif /* MALI_USE_CSF */ } diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_debug_job_fault_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_debug_job_fault_backend.c deleted file mode 100644 index af8d1e3af87c..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_debug_job_fault_backend.c +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include -#include "mali_kbase_debug_job_fault.h" - -#if IS_ENABLED(CONFIG_DEBUG_FS) - -/*GPU_CONTROL_REG(r)*/ -static unsigned int gpu_control_reg_snapshot[] = { GPU_CONTROL_ENUM(GPU_ID), - GPU_CONTROL_ENUM(SHADER_READY), - GPU_CONTROL_ENUM(TILER_READY), - GPU_CONTROL_ENUM(L2_READY) }; - -/* JOB_CONTROL_REG(r) */ -static unsigned int job_control_reg_snapshot[] = { JOB_CONTROL_ENUM(JOB_IRQ_MASK), - JOB_CONTROL_ENUM(JOB_IRQ_STATUS) }; - -/* JOB_SLOT_REG(n,r) */ -static unsigned int job_slot_reg_snapshot[] = { - JOB_SLOT_ENUM(0, HEAD) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, TAIL) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, AFFINITY) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, CONFIG) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, STATUS) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, HEAD_NEXT) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, AFFINITY_NEXT) - JOB_SLOT_BASE_ENUM(0), - JOB_SLOT_ENUM(0, CONFIG_NEXT) - JOB_SLOT_BASE_ENUM(0) -}; - -/*MMU_CONTROL_REG(r)*/ -static unsigned int mmu_reg_snapshot[] = { MMU_CONTROL_ENUM(IRQ_MASK), - MMU_CONTROL_ENUM(IRQ_STATUS) }; - -/* MMU_AS_REG(n,r) */ -static unsigned int as_reg_snapshot[] = { MMU_AS_ENUM(0, TRANSTAB) - MMU_AS_BASE_ENUM(0), - MMU_AS_ENUM(0, TRANSCFG) - MMU_AS_BASE_ENUM(0), - MMU_AS_ENUM(0, MEMATTR) - MMU_AS_BASE_ENUM(0), - MMU_AS_ENUM(0, FAULTSTATUS) - MMU_AS_BASE_ENUM(0), - MMU_AS_ENUM(0, FAULTADDRESS) - MMU_AS_BASE_ENUM(0), - MMU_AS_ENUM(0, STATUS) - MMU_AS_BASE_ENUM(0) }; - -bool kbase_debug_job_fault_reg_snapshot_init(struct kbase_context *kctx, int reg_range) -{ - uint i, j; - int offset = 0; - uint slot_number; - uint as_number; - - if (kctx->reg_dump == NULL) - return false; - - slot_number = kctx->kbdev->gpu_props.num_job_slots; - as_number = kctx->kbdev->gpu_props.num_address_spaces; - - /* get the GPU control registers*/ - for (i = 0; i < ARRAY_SIZE(gpu_control_reg_snapshot); i++) { - kctx->reg_dump[offset] = gpu_control_reg_snapshot[i]; - if (kbase_reg_is_size64(kctx->kbdev, kctx->reg_dump[offset])) - offset += 4; - else - offset += 2; - } - - /* get the Job control registers*/ - for (i = 0; i < ARRAY_SIZE(job_control_reg_snapshot); i++) { - kctx->reg_dump[offset] = job_control_reg_snapshot[i]; - if (kbase_reg_is_size64(kctx->kbdev, kctx->reg_dump[offset])) - offset += 4; - else - offset += 2; - } - - /* get the Job Slot registers*/ - for (j = 0; j < slot_number; j++) { - for (i = 0; i < ARRAY_SIZE(job_slot_reg_snapshot); i++) { - kctx->reg_dump[offset] = JOB_SLOT_BASE_OFFSET(j) + job_slot_reg_snapshot[i]; - if (kbase_reg_is_size64(kctx->kbdev, kctx->reg_dump[offset])) - offset += 4; - else - offset += 2; - } - } - - /* get the MMU registers*/ - for (i = 0; i < ARRAY_SIZE(mmu_reg_snapshot); i++) { - kctx->reg_dump[offset] = mmu_reg_snapshot[i]; - if (kbase_reg_is_size64(kctx->kbdev, kctx->reg_dump[offset])) - offset += 4; - else - offset += 2; - } - - /* get the Address space registers*/ - for (j = 0; j < as_number; j++) { - for (i = 0; i < ARRAY_SIZE(as_reg_snapshot); i++) { - kctx->reg_dump[offset] = MMU_AS_BASE_OFFSET(j) + as_reg_snapshot[i]; - if (kbase_reg_is_size64(kctx->kbdev, kctx->reg_dump[offset])) - offset += 4; - else - offset += 2; - } - } - - WARN_ON(offset >= (reg_range * 2 / 4)); - - /* set the termination flag*/ - kctx->reg_dump[offset] = REGISTER_DUMP_TERMINATION_FLAG; - kctx->reg_dump[offset + 1] = REGISTER_DUMP_TERMINATION_FLAG; - - dev_dbg(kctx->kbdev->dev, "kbase_job_fault_reg_snapshot_init:%d\n", offset); - - return true; -} - -bool kbase_job_fault_get_reg_snapshot(struct kbase_context *kctx) -{ - int offset = 0; - u32 reg_enum; - u64 val64; - - if (kctx->reg_dump == NULL) - return false; - - while (kctx->reg_dump[offset] != REGISTER_DUMP_TERMINATION_FLAG) { - reg_enum = kctx->reg_dump[offset]; - /* Get register offset from enum */ - kbase_reg_get_offset(kctx->kbdev, reg_enum, &kctx->reg_dump[offset]); - - if (kbase_reg_is_size64(kctx->kbdev, reg_enum)) { - val64 = kbase_reg_read64(kctx->kbdev, reg_enum); - - /* offset computed offset to get _HI offset */ - kctx->reg_dump[offset + 2] = kctx->reg_dump[offset] + 4; - - kctx->reg_dump[offset + 1] = (u32)(val64 & 0xFFFFFFFF); - kctx->reg_dump[offset + 3] = (u32)(val64 >> 32); - offset += 4; - } else { - kctx->reg_dump[offset + 1] = kbase_reg_read32(kctx->kbdev, reg_enum); - offset += 2; - } - } - return true; -} - -#endif diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_defs.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_defs.h index bff0b7235736..fa745bf6b471 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_defs.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_defs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -98,12 +98,6 @@ struct slot_rb { * The hwaccess_lock (a spinlock) must be held when accessing this structure */ struct kbase_backend_data { -#if !MALI_USE_CSF - struct slot_rb slot_rb[BASE_JM_MAX_NR_SLOTS]; - struct hrtimer scheduling_timer; - - bool timer_running; -#endif bool suspend_timer; atomic_t reset_gpu; diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_devfreq.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_devfreq.c index 22be72239fe3..db6a475a5301 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_devfreq.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_devfreq.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -195,7 +195,7 @@ static int kbase_devfreq_status(struct device *dev, struct devfreq_dev_status *s stat->current_frequency = kbdev->current_nominal_freq; stat->private_data = NULL; -#if MALI_USE_CSF && defined CONFIG_DEVFREQ_THERMAL +#if defined CONFIG_DEVFREQ_THERMAL if (!kbdev->devfreq_profile.is_cooling_device) kbase_ipa_reset_data(kbdev); #endif @@ -399,7 +399,6 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev) opp_freq); continue; } -#if MALI_USE_CSF if (kbase_csf_dev_has_ne(kbdev)) { u64 neural_present = kbdev->gpu_props.neural_present; u64 sc_with_ne = shader_present & neural_present; @@ -423,7 +422,6 @@ static int kbase_devfreq_init_core_mask_table(struct kbase_device *kbdev) continue; } } -#endif /* MALI_USE_CSF */ core_count_p = of_get_property(node, "opp-core-count", NULL); if (core_count_p) { diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_gpuprops_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_gpuprops_backend.c index 1cd3dafcb452..cdca4d3ed6b8 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_gpuprops_backend.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_gpuprops_backend.c @@ -44,22 +44,10 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, struct kbasep_gpuprop if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(STACK_PRESENT))) regdump->stack_present = kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(STACK_PRESENT)); -#if !MALI_USE_CSF - regdump->js_present = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(JS_PRESENT)); - /* Not a valid register on TMIX */ - - /* TGOx specific register */ - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_THREAD_TLS_ALLOC)) - regdump->thread_tls_alloc = - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(THREAD_TLS_ALLOC)); -#endif /* !MALI_USE_CSF */ - regdump->thread_max_threads = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(THREAD_MAX_THREADS)); if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(THREAD_MAX_WORKGROUP_SIZE))) regdump->thread_max_workgroup_size = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(THREAD_MAX_WORKGROUP_SIZE)); -#if MALI_USE_CSF -#endif /* MALI_USE_CSF */ if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(THREAD_MAX_BARRIER_SIZE))) regdump->thread_max_barrier_size = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(THREAD_MAX_BARRIER_SIZE)); @@ -73,7 +61,6 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, struct kbasep_gpuprop if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_CORE_FEATURES)) regdump->core_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(CORE_FEATURES)); -#if MALI_USE_CSF if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(GPU_FEATURES))) regdump->gpu_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(GPU_FEATURES)); /* Only applicable to GPUs with power control domain registers */ @@ -82,19 +69,11 @@ int kbase_backend_gpuprops_get(struct kbase_device *kbdev, struct kbasep_gpuprop regdump->neural_present = kbase_reg_read64(kbdev, HOST_POWER_ENUM(NEURAL_PRESENT)); } -#endif /* MALI_USE_CSF */ regdump->tiler_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(TILER_FEATURES)); regdump->l2_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(L2_FEATURES)); regdump->mem_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(MEM_FEATURES)); regdump->mmu_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(MMU_FEATURES)); -#if !MALI_USE_CSF - for (i = 0; i < GPU_MAX_JOB_SLOTS; i++) - regdump->js_features[i] = kbase_reg_read32(kbdev, GPU_JS_FEATURES_OFFSET(i)); -#endif /* !MALI_USE_CSF */ - -#if MALI_USE_CSF -#endif /* MALI_USE_CSF */ { for (i = 0; i < BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS; i++) regdump->texture_features[i] = @@ -131,14 +110,12 @@ int kbase_backend_gpuprops_get_l2_features(struct kbase_device *kbdev, regdump->l2_features = KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(L2_FEATURES)); regdump->l2_config = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG)); -#if MALI_USE_CSF if (kbase_hw_has_l2_slice_hash_feature(kbdev)) { uint i; for (i = 0; i < GPU_L2_SLICE_HASH_COUNT; i++) regdump->l2_slice_hash[i] = kbase_reg_read32(kbdev, GPU_L2_SLICE_HASH_OFFSET(i)); } -#endif /* MALI_USE_CSF */ if (!kbase_io_has_gpu(kbdev)) return -EIO; diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_instr_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_instr_backend.c deleted file mode 100644 index 62bb507c64d1..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_instr_backend.c +++ /dev/null @@ -1,479 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * GPU backend instrumentation APIs. - */ - -#include -#include -#include -#include -#include -#include - -#define WAIT_FOR_DUMP_TIMEOUT_MS 5000 - -static int wait_prfcnt_ready(struct kbase_device *kbdev) -{ - u32 val; - const u32 timeout_us = - kbase_get_timeout_ms(kbdev, KBASE_PRFCNT_ACTIVE_TIMEOUT) * USEC_PER_MSEC; - const int err = kbase_reg_poll32_timeout(kbdev, GPU_CONTROL_ENUM(GPU_STATUS), val, - !(val & GPU_STATUS_PRFCNT_ACTIVE), 0, timeout_us, - false); - if (err) { - dev_err(kbdev->dev, "PRFCNT_ACTIVE bit stuck\n"); - return -EBUSY; - } - return 0; -} - -int kbase_instr_hwcnt_enable_internal(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_instr_hwcnt_enable *enable) -{ - unsigned long flags; - int err = -EINVAL; - u32 irq_mask; - u32 prfcnt_config; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* alignment failure */ - if ((enable->dump_buffer == 0ULL) || (enable->dump_buffer & (2048 - 1))) - return err; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_DISABLED) { - /* Instrumentation is already enabled */ - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - return err; - } - - if (!kbase_io_has_gpu(kbdev)) { - /* GPU has been removed by Arbiter */ - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - return err; - } - - /* Enable interrupt */ - irq_mask = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), - irq_mask | PRFCNT_SAMPLE_COMPLETED); - - /* In use, this context is the owner */ - kbdev->hwcnt.kctx = kctx; - /* Remember the dump address so we can reprogram it later */ - kbdev->hwcnt.addr = enable->dump_buffer; - kbdev->hwcnt.addr_bytes = enable->dump_buffer_bytes; - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - - /* Configure */ - prfcnt_config = (u32)kctx->as_nr << PRFCNT_CONFIG_AS_SHIFT; -#ifdef CONFIG_MALI_VALHALL_PRFCNT_SET_SELECT_VIA_DEBUG_FS - prfcnt_config |= (u32)kbdev->hwcnt.backend.override_counter_set - << PRFCNT_CONFIG_SETSELECT_SHIFT; -#else - prfcnt_config |= (u32)enable->counter_set << PRFCNT_CONFIG_SETSELECT_SHIFT; -#endif - - /* Wait until prfcnt config register can be written */ - err = wait_prfcnt_ready(kbdev); - if (err) - return err; - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_CONFIG), - prfcnt_config | PRFCNT_CONFIG_MODE_OFF); - - /* Wait until prfcnt is disabled before writing configuration registers */ - err = wait_prfcnt_ready(kbdev); - if (err) - return err; - - kbase_reg_write64(kbdev, GPU_CONTROL_ENUM(PRFCNT_BASE), enable->dump_buffer); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_JM_EN), enable->fe_bm); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_SHADER_EN), enable->shader_bm); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_MMU_L2_EN), enable->mmu_l2_bm); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_TILER_EN), enable->tiler_bm); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_CONFIG), - prfcnt_config | PRFCNT_CONFIG_MODE_MANUAL); - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; - kbdev->hwcnt.backend.triggered = 1; - wake_up(&kbdev->hwcnt.backend.wait); - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - - dev_dbg(kbdev->dev, "HW counters dumping set-up for context %pK", kctx); - return 0; -} - -static void kbasep_instr_hwc_disable_hw_prfcnt(struct kbase_device *kbdev) -{ - u32 irq_mask; - - lockdep_assert_held(&kbdev->hwaccess_lock); - lockdep_assert_held(&kbdev->hwcnt.lock); - - if (!kbase_io_has_gpu(kbdev)) - /* GPU has been removed by Arbiter */ - return; - - /* Disable interrupt */ - irq_mask = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), - irq_mask & ~PRFCNT_SAMPLE_COMPLETED); - - /* Wait until prfcnt config register can be written, then disable the counters. - * Return value is ignored as we are disabling anyway. - */ - wait_prfcnt_ready(kbdev); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(PRFCNT_CONFIG), 0); - - kbdev->hwcnt.kctx = NULL; - kbdev->hwcnt.addr = 0ULL; - kbdev->hwcnt.addr_bytes = 0ULL; -} - -int kbase_instr_hwcnt_disable_internal(struct kbase_context *kctx) -{ - unsigned long flags, pm_flags; - struct kbase_device *kbdev = kctx->kbdev; - const unsigned long timeout = msecs_to_jiffies(WAIT_FOR_DUMP_TIMEOUT_MS); - unsigned int remaining; - - while (1) { - spin_lock_irqsave(&kbdev->hwaccess_lock, pm_flags); - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_UNRECOVERABLE_ERROR) { - /* Instrumentation is in unrecoverable error state, - * there is nothing for us to do. - */ - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); - /* Already disabled, return no error. */ - return 0; - } - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DISABLED) { - /* Instrumentation is not enabled */ - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); - return -EINVAL; - } - - if (kbdev->hwcnt.kctx != kctx) { - /* Instrumentation has been setup for another context */ - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); - return -EINVAL; - } - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_IDLE) - break; - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); - - /* Ongoing dump/setup - wait for its completion */ - remaining = wait_event_timeout(kbdev->hwcnt.backend.wait, - kbdev->hwcnt.backend.triggered != 0, timeout); - - if (remaining == 0) - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_UNRECOVERABLE_ERROR; - } - - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED; - kbdev->hwcnt.backend.triggered = 0; - - kbasep_instr_hwc_disable_hw_prfcnt(kbdev); - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, pm_flags); - - dev_dbg(kbdev->dev, "HW counters dumping disabled for context %pK", kctx); - - return 0; -} - -int kbase_instr_hwcnt_request_dump(struct kbase_context *kctx) -{ - unsigned long flags; - int err = -EINVAL; - struct kbase_device *kbdev = kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - if (kbdev->hwcnt.kctx != kctx) { - /* The instrumentation has been setup for another context */ - goto unlock; - } - - if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_IDLE) { - /* HW counters are disabled or another dump is ongoing, or we're - * resetting, or we are in unrecoverable error state. - */ - goto unlock; - } - - if (!kbase_io_has_gpu(kbdev)) { - /* GPU has been removed by Arbiter */ - goto unlock; - } - - kbdev->hwcnt.backend.triggered = 0; - - /* Mark that we're dumping - the PF handler can signal that we faulted - */ - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DUMPING; - - /* Wait until prfcnt is ready to request dump */ - err = wait_prfcnt_ready(kbdev); - if (err) - goto unlock; - - /* Reconfigure the dump address */ - kbase_reg_write64(kbdev, GPU_CONTROL_ENUM(PRFCNT_BASE), kbdev->hwcnt.addr); - - /* Start dumping */ - KBASE_KTRACE_ADD(kbdev, CORE_GPU_PRFCNT_SAMPLE, NULL, kbdev->hwcnt.addr); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), GPU_COMMAND_PRFCNT_SAMPLE); - - dev_dbg(kbdev->dev, "HW counters dumping done for context %pK", kctx); - -unlock: - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - return err; -} -KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_request_dump); - -bool kbase_instr_hwcnt_dump_complete(struct kbase_context *kctx, bool *const success) -{ - unsigned long flags; - bool complete = false; - struct kbase_device *kbdev = kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_IDLE) { - *success = true; - complete = true; - } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { - *success = false; - complete = true; - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; - } - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - - return complete; -} -KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_dump_complete); - -void kbase_instr_hwcnt_sample_done(struct kbase_device *kbdev) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - /* If the state is in unrecoverable error, we already wake_up the waiter - * and don't need to do any action when sample is done. - */ - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { - kbdev->hwcnt.backend.triggered = 1; - wake_up(&kbdev->hwcnt.backend.wait); - } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING) { - /* All finished and idle */ - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; - kbdev->hwcnt.backend.triggered = 1; - wake_up(&kbdev->hwcnt.backend.wait); - } - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); -} - -int kbase_instr_hwcnt_wait_for_dump(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - unsigned long flags; - int err; - - unsigned long remaining; - const unsigned long timeout = msecs_to_jiffies(WAIT_FOR_DUMP_TIMEOUT_MS); - - /* Wait for dump & cache clean to complete */ - remaining = wait_event_timeout(kbdev->hwcnt.backend.wait, - kbdev->hwcnt.backend.triggered != 0, timeout); - if (remaining == 0) { - err = -ETIME; - /* Set the backend state so it's clear things have gone bad (could be a HW issue) - */ - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_UNRECOVERABLE_ERROR; - goto timed_out; - } - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { - err = -EINVAL; - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_IDLE; - } else if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_UNRECOVERABLE_ERROR) { - err = -EIO; - } else { - /* Dump done */ - KBASE_DEBUG_ASSERT(kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_IDLE); - err = 0; - } - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); -timed_out: - return err; -} - -int kbase_instr_hwcnt_clear(struct kbase_context *kctx) -{ - unsigned long flags; - int err = -EINVAL; - struct kbase_device *kbdev = kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - /* Check it's the context previously set up and we're not in IDLE - * state. - */ - if (kbdev->hwcnt.kctx != kctx || kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_IDLE) - goto unlock; - - if (!kbase_io_has_gpu(kbdev)) { - /* GPU has been removed by Arbiter */ - goto unlock; - } - - /* Wait until prfcnt is ready to clear */ - err = wait_prfcnt_ready(kbdev); - if (err) - goto unlock; - - /* Clear the counters */ - KBASE_KTRACE_ADD(kbdev, CORE_GPU_PRFCNT_CLEAR, NULL, 0); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), GPU_COMMAND_PRFCNT_CLEAR); - -unlock: - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - return err; -} -KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_clear); - -void kbase_instr_hwcnt_on_unrecoverable_error(struct kbase_device *kbdev) -{ - unsigned long flags; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - /* If we already in unrecoverable error state, early return. */ - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_UNRECOVERABLE_ERROR) { - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - return; - } - - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_UNRECOVERABLE_ERROR; - - /* Need to disable HW if it's not disabled yet. */ - if (kbdev->hwcnt.backend.state != KBASE_INSTR_STATE_DISABLED) - kbasep_instr_hwc_disable_hw_prfcnt(kbdev); - - /* Wake up any waiters. */ - kbdev->hwcnt.backend.triggered = 1; - wake_up(&kbdev->hwcnt.backend.wait); - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); -} -KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_on_unrecoverable_error); - -void kbase_instr_hwcnt_on_before_reset(struct kbase_device *kbdev) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - - /* A reset is the only way to exit the unrecoverable error state */ - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_UNRECOVERABLE_ERROR) - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED; - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); -} -KBASE_EXPORT_SYMBOL(kbase_instr_hwcnt_on_before_reset); - -int kbase_instr_backend_init(struct kbase_device *kbdev) -{ - spin_lock_init(&kbdev->hwcnt.lock); - - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_DISABLED; - - init_waitqueue_head(&kbdev->hwcnt.backend.wait); - -#ifdef CONFIG_MALI_VALHALL_PRFCNT_SET_SELECT_VIA_DEBUG_FS -/* Use the build time option for the override default. */ -#if defined(CONFIG_MALI_VALHALL_PRFCNT_SET_SECONDARY) - kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_PHYSICAL_SET_SECONDARY; -#elif defined(CONFIG_MALI_VALHALL_PRFCNT_SET_TERTIARY) - kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_PHYSICAL_SET_TERTIARY; -#else - /* Default to primary */ - kbdev->hwcnt.backend.override_counter_set = KBASE_HWCNT_PHYSICAL_SET_PRIMARY; -#endif -#endif - return 0; -} - -void kbase_instr_backend_term(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); -} - -#ifdef CONFIG_MALI_VALHALL_PRFCNT_SET_SELECT_VIA_DEBUG_FS -void kbase_instr_backend_debugfs_init(struct kbase_device *kbdev) -{ - /* No validation is done on the debugfs input. Invalid input could cause - * performance counter errors. This is acceptable since this is a debug - * only feature and users should know what they are doing. - * - * Valid inputs are the values accepted bythe SET_SELECT bits of the - * PRFCNT_CONFIG register as defined in the architecture specification. - */ - debugfs_create_u8("hwcnt_set_select", 0644, kbdev->mali_debugfs_directory, - (u8 *)&kbdev->hwcnt.backend.override_counter_set); -} -#endif diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_irq_linux.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_irq_linux.c index 11bb1c57ca96..05290d403ad5 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_irq_linux.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_irq_linux.c @@ -62,12 +62,8 @@ static irqreturn_t kbase_job_irq_handler(int irq, void *data) dev_dbg(kbdev->dev, "%s: irq %d irqstatus 0x%x\n", __func__, irq, val); -#if MALI_USE_CSF /* call the csf interrupt handler */ kbase_csf_interrupt(kbdev, val); -#else - kbase_job_done(kbdev, val); -#endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); @@ -108,7 +104,6 @@ static irqreturn_t kbase_mmu_irq_handler(int irq, void *data) return IRQ_HANDLED; } -#if MALI_USE_CSF static irqreturn_t kbase_pwr_irq_handler(int irq, void *data) { unsigned long flags; @@ -138,7 +133,6 @@ static irqreturn_t kbase_pwr_irq_handler(int irq, void *data) return irq_state; } -#endif /* MALI_USE_CSF */ static irqreturn_t kbase_gpuonly_irq_handler(int irq, void *data) @@ -181,7 +175,6 @@ static irqreturn_t kbase_gpuonly_irq_handler(int irq, void *data) static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) { irqreturn_t irq_state = kbase_gpuonly_irq_handler(irq, data); -#if MALI_USE_CSF struct kbase_device *kbdev = kbase_untag(data); /* Skip if HOST_POWER page is not available */ @@ -189,7 +182,6 @@ static irqreturn_t kbase_gpu_irq_handler(int irq, void *data) if (kbase_pwr_irq_handler(irq, data) == IRQ_HANDLED) irq_state = IRQ_HANDLED; } -#endif /* MALI_USE_CSF */ return irq_state; } @@ -350,6 +342,40 @@ static enum hrtimer_restart kbasep_test_interrupt_timeout(struct hrtimer *timer) return HRTIMER_NORESTART; } +struct interrupt_masks { + u32 job; + u32 mmu; + u32 gpu; + u32 pwr; +}; + +static void store_interrupt_masks(struct interrupt_masks *masks, struct kbase_device *const kbdev) +{ + /* Store all interrupt masks */ + masks->job = kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK)); + masks->mmu = kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK)); + masks->gpu = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)); + if (kbdev->pm.backend.has_host_pwr_iface) + masks->pwr = kbase_reg_read32(kbdev, HOST_POWER_ENUM(PWR_IRQ_MASK)); + + /* Set all masks to 0 to disable all interrupt sources */ + kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK), 0x0); + kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), 0x0); + kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), 0x0); + if (kbdev->pm.backend.has_host_pwr_iface) + kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_MASK), 0x0); +} + +static void restore_interrupt_masks(struct interrupt_masks *masks, struct kbase_device *const kbdev) +{ + /* Restore all interrupt masks to their previous values */ + kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK), masks->job); + kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), masks->mmu); + kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), masks->gpu); + if (kbdev->pm.backend.has_host_pwr_iface) + kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_MASK), masks->pwr); +} + /** * validate_interrupt - Validate an interrupt * @kbdev: Kbase device @@ -364,9 +390,9 @@ static enum hrtimer_restart kbasep_test_interrupt_timeout(struct hrtimer *timer) static int validate_interrupt(struct kbase_device *const kbdev, u32 tag) { int err = 0; + struct interrupt_masks masks = { 0 }; irq_handler_t handler; const int irq = (kbdev->nr_irqs == 1) ? 0 : tag; - u32 old_mask_val; u16 mask_offset; u16 rawstat_offset; @@ -389,10 +415,8 @@ static int validate_interrupt(struct kbase_device *const kbdev, u32 tag) return -EINVAL; } - /* store old mask */ - old_mask_val = kbase_reg_read32(kbdev, mask_offset); - /* mask interrupts */ - kbase_reg_write32(kbdev, mask_offset, 0x0); + /* store masks and disable all possible interrupt sources */ + store_interrupt_masks(&masks, kbdev); if (kbdev->irqs[irq].irq) { /* release original handler and install test handler */ @@ -441,8 +465,8 @@ static int validate_interrupt(struct kbase_device *const kbdev, u32 tag) err = -EINVAL; } } - /* restore old mask */ - kbase_reg_write32(kbdev, mask_offset, old_mask_val); + /* restore old masks */ + restore_interrupt_masks(&masks, kbdev); return err; } @@ -487,7 +511,6 @@ int kbase_install_interrupts(struct kbase_device *kbdev) { u32 irq_index; -#if MALI_USE_CSF if (kbdev->gpu_props.gpu_id.arch_id >= GPU_ID_ARCH_MAKE(14, 8, 0)) { if (kbdev->nr_irqs != 1) { dev_err(kbdev->dev, "Incorrect number of irq entries (%u)", kbdev->nr_irqs); @@ -499,7 +522,6 @@ int kbase_install_interrupts(struct kbase_device *kbdev) return -EINVAL; } } -#endif /* MALI_USE_CSF */ for (irq_index = 0; irq_index < kbdev->nr_irqs; irq_index++) { const int result = request_irq(kbdev->irqs[irq_index].irq, kbase_get_interrupt_handler(kbdev, irq_index), diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_as.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_as.c deleted file mode 100644 index 960ac9905343..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_as.c +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Register backend context / address space management - */ - -#include -#include -#include - -/** - * assign_and_activate_kctx_addr_space - Assign an AS to a context - * @kbdev: Kbase device - * @kctx: Kbase context - * @current_as: Address Space to assign - * - * Assign an Address Space (AS) to a context, and add the context to the Policy. - * - * This includes - * setting up the global runpool_irq structure and the context on the AS, - * Activating the MMU on the AS, - * Allowing jobs to be submitted on the AS. - * - * Context: - * kbasep_js_kctx_info.jsctx_mutex held, - * kbasep_js_device_data.runpool_mutex held, - * AS transaction mutex held, - * Runpool IRQ lock held - */ -static void assign_and_activate_kctx_addr_space(struct kbase_device *kbdev, - struct kbase_context *kctx, - struct kbase_as *current_as) -{ - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - - CSTD_UNUSED(current_as); - - lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); - lockdep_assert_held(&js_devdata->runpool_mutex); - lockdep_assert_held(&kbdev->hwaccess_lock); - -#if !MALI_USE_CSF - /* Attribute handling */ - kbasep_js_ctx_attr_runpool_retain_ctx(kbdev, kctx); -#endif - - /* Allow it to run jobs */ - kbasep_js_set_submit_allowed(js_devdata, kctx); - - kbase_js_runpool_inc_context_count(kbdev, kctx); -} - -bool kbase_backend_use_ctx_sched(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js) -{ - int i; - - if (kbdev->hwaccess.active_kctx[js] == kctx) { - /* Context is already active */ - return true; - } - - for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { - if (kbdev->as_to_kctx[i] == kctx) { - /* Context already has ASID - mark as active */ - return true; - } - } - - /* Context does not have address space assigned */ - return false; -} - -void kbase_backend_release_ctx_irq(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - int as_nr = kctx->as_nr; - - if (as_nr == KBASEP_AS_NR_INVALID) { - WARN(1, "Attempting to release context without ASID\n"); - return; - } - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (atomic_read(&kctx->refcount) != 1) { - WARN(1, "Attempting to release active ASID\n"); - return; - } - - kbasep_js_clear_submit_allowed(&kbdev->js_data, kctx); - - kbase_ctx_sched_release_ctx(kctx); - kbase_js_runpool_dec_context_count(kbdev, kctx); -} - -void kbase_backend_release_ctx_noirq(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - CSTD_UNUSED(kbdev); - CSTD_UNUSED(kctx); -} - -int kbase_backend_find_and_release_free_address_space(struct kbase_device *kbdev, - struct kbase_context *kctx) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - unsigned long flags; - int i; - - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - for (i = 0; i < kbdev->nr_hw_address_spaces; i++) { - struct kbasep_js_kctx_info *as_js_kctx_info; - struct kbase_context *as_kctx; - - as_kctx = kbdev->as_to_kctx[i]; - as_js_kctx_info = &as_kctx->jctx.sched_info; - - /* Don't release privileged or active contexts, or contexts with - * jobs running. - * Note that a context will have at least 1 reference (which - * was previously taken by kbasep_js_schedule_ctx()) until - * descheduled. - */ - if (as_kctx && !kbase_ctx_flag(as_kctx, KCTX_PRIVILEGED) && - atomic_read(&as_kctx->refcount) == 1) { - if (!kbase_ctx_sched_inc_refcount_nolock(as_kctx)) { - WARN(1, "Failed to retain active context\n"); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - return KBASEP_AS_NR_INVALID; - } - - kbasep_js_clear_submit_allowed(js_devdata, as_kctx); - - /* Drop and retake locks to take the jsctx_mutex on the - * context we're about to release without violating lock - * ordering - */ - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - /* Release context from address space */ - mutex_lock(&as_js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - - kbasep_js_runpool_release_ctx_nolock(kbdev, as_kctx); - - if (!kbase_ctx_flag(as_kctx, KCTX_SCHEDULED)) { - kbasep_js_runpool_requeue_or_kill_ctx(kbdev, as_kctx, true); - - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex); - - return i; - } - - /* Context was retained while locks were dropped, - * continue looking for free AS - */ - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&as_js_kctx_info->ctx.jsctx_mutex); - - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - } - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - return KBASEP_AS_NR_INVALID; -} - -bool kbase_backend_use_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, int as_nr) -{ - struct kbasep_js_device_data *js_devdata; - struct kbase_as *new_address_space = NULL; - int js; - - js_devdata = &kbdev->js_data; - - for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { - if (kbdev->hwaccess.active_kctx[js] == kctx) { - WARN(1, "Context is already scheduled in\n"); - return false; - } - } - - new_address_space = &kbdev->as[as_nr]; - - lockdep_assert_held(&js_devdata->runpool_mutex); - lockdep_assert_held(&kbdev->mmu_hw_mutex); - lockdep_assert_held(&kbdev->hwaccess_lock); - - assign_and_activate_kctx_addr_space(kbdev, kctx, new_address_space); - - if (kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) { - /* We need to retain it to keep the corresponding address space - */ - kbase_ctx_sched_retain_ctx_refcount(kctx); - } - - return true; -} diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_hw.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_hw.c deleted file mode 100644 index d815fd80ebb9..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_hw.c +++ /dev/null @@ -1,1280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Base kernel job manager APIs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev); -static u64 kbasep_apply_limited_core_mask(const struct kbase_device *kbdev, const u64 affinity, - const u64 limited_core_mask); - -static u64 kbase_job_write_affinity(struct kbase_device *kbdev, base_jd_core_req core_req, - unsigned int js, const u64 limited_core_mask) -{ - u64 affinity; - bool skip_affinity_check = false; - - if ((core_req & (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T)) == BASE_JD_REQ_T) { - /* Tiler-only atom, affinity value can be programed as 0 */ - affinity = 0; - skip_affinity_check = true; - } else if ((core_req & - (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP))) { - affinity = kbdev->pm.backend.shaders_avail & kbdev->pm.debug_core_mask[js]; - - /* Bifrost onwards GPUs only have 1 coherent group which is equal to - * shader_present - */ - affinity &= kbdev->gpu_props.curr_config.shader_present; - } else { - /* Use all cores */ - affinity = kbdev->pm.backend.shaders_avail & kbdev->pm.debug_core_mask[js]; - } - - if (core_req & BASE_JD_REQ_LIMITED_CORE_MASK) { - /* Limiting affinity due to BASE_JD_REQ_LIMITED_CORE_MASK by applying the limited core mask. */ - affinity = kbasep_apply_limited_core_mask(kbdev, affinity, limited_core_mask); - } - - if (unlikely(!affinity && !skip_affinity_check)) { -#ifdef CONFIG_MALI_VALHALL_DEBUG - u64 shaders_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); - - WARN_ON(!(shaders_ready & kbdev->pm.backend.shaders_avail)); -#endif - - affinity = kbdev->pm.backend.shaders_avail; - - if (core_req & BASE_JD_REQ_LIMITED_CORE_MASK) { - /* Limiting affinity again to make sure it only enables shader cores with backed TLS memory. */ - affinity = - kbasep_apply_limited_core_mask(kbdev, affinity, limited_core_mask); - -#ifdef CONFIG_MALI_VALHALL_DEBUG - /* affinity should never be 0 */ - WARN_ON(!affinity); -#endif - } - } - - kbase_reg_write64(kbdev, JOB_SLOT_OFFSET(js, AFFINITY_NEXT), affinity); - - return affinity; -} - -static inline bool kbasep_jm_wait_js_free(struct kbase_device *kbdev, unsigned int js, - struct kbase_context *kctx) -{ - u32 val; - const u32 timeout_us = kbdev->js_data.js_free_wait_time_ms * USEC_PER_MSEC; - /* wait for the JS_COMMAND_NEXT register to reach the given status value */ - const int err = kbase_reg_poll32_timeout(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT), val, - !val, 0, timeout_us, false); - - if (!err) - return true; - - dev_err(kbdev->dev, "Timeout in waiting for job slot %u to become free for ctx %d_%u", js, - kctx->tgid, kctx->id); - - return false; -} - -int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, unsigned int js) -{ - struct kbase_context *kctx; - u32 cfg; - u64 jc_head = katom->jc; - u64 affinity; - struct slot_rb *ptr_slot_rb = &kbdev->hwaccess.backend.slot_rb[js]; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - kctx = katom->kctx; - - /* Command register must be available */ - if (!kbasep_jm_wait_js_free(kbdev, js, kctx)) - return -EPERM; - - dev_dbg(kctx->kbdev->dev, "Write JS_HEAD_NEXT 0x%llx for atom %pK\n", jc_head, - (void *)katom); - - kbase_reg_write64(kbdev, JOB_SLOT_OFFSET(js, HEAD_NEXT), jc_head); - - affinity = kbase_job_write_affinity(kbdev, katom->core_req, js, kctx->limited_core_mask); - - /* start MMU, medium priority, cache clean/flush on end, clean/flush on - * start - */ - cfg = (u32)kctx->as_nr; - - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION) && - !(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET)) - cfg |= JS_CONFIG_ENABLE_FLUSH_REDUCTION; - - if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_START)) { - /* Force a cache maintenance operation if the newly submitted - * katom to the slot is from a different kctx. For a JM GPU - * that has the feature KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER, - * applies a FLUSH_INV_SHADER_OTHER. Otherwise, do a - * FLUSH_CLEAN_INVALIDATE. - */ - u64 tagged_kctx = ptr_slot_rb->last_kctx_tagged; - - if (tagged_kctx != SLOT_RB_NULL_TAG_VAL && tagged_kctx != SLOT_RB_TAG_KCTX(kctx)) { - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_INV_SHADER_OTHER)) - cfg |= JS_CONFIG_START_FLUSH_INV_SHADER_OTHER; - else - cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE; - } else - cfg |= JS_CONFIG_START_FLUSH_NO_ACTION; - } else - cfg |= JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE; - - if (0 != (katom->core_req & BASE_JD_REQ_SKIP_CACHE_END) && - !(kbdev->serialize_jobs & KBASE_SERIALIZE_RESET)) - cfg |= JS_CONFIG_END_FLUSH_NO_ACTION; - else if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_CLEAN_ONLY_SAFE)) - cfg |= JS_CONFIG_END_FLUSH_CLEAN; - else - cfg |= JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE; - - cfg |= JS_CONFIG_THREAD_PRI(8); - - if (katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED) - cfg |= JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK; - - if (!ptr_slot_rb->job_chain_flag) { - cfg |= JS_CONFIG_JOB_CHAIN_FLAG; - katom->atom_flags |= KBASE_KATOM_FLAGS_JOBCHAIN; - ptr_slot_rb->job_chain_flag = true; - } else { - katom->atom_flags &= ~KBASE_KATOM_FLAGS_JOBCHAIN; - ptr_slot_rb->job_chain_flag = false; - } - - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, CONFIG_NEXT), cfg); - - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION)) - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, FLUSH_ID_NEXT), katom->flush_id); - - /* Write an approximate start timestamp. - * It's approximate because there might be a job in the HEAD register. - */ - katom->start_timestamp = ktime_get_raw(); - - /* GO ! */ - dev_dbg(kbdev->dev, "JS: Submitting atom %pK from ctx %pK to js[%d] with head=0x%llx", - katom, kctx, js, jc_head); - - KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, JM_SUBMIT, kctx, katom, jc_head, js, (u32)affinity); - - KBASE_TLSTREAM_AUX_EVENT_JOB_SLOT(kbdev, kctx, js, kbase_jd_atom_id(kctx, katom), - TL_JS_EVENT_START); - - KBASE_TLSTREAM_TL_ATTRIB_ATOM_CONFIG(kbdev, katom, jc_head, affinity, cfg); - KBASE_TLSTREAM_TL_RET_CTX_LPU(kbdev, kctx, &kbdev->gpu_props.js_features[katom->slot_nr]); - KBASE_TLSTREAM_TL_RET_ATOM_AS(kbdev, katom, &kbdev->as[kctx->as_nr]); - KBASE_TLSTREAM_TL_RET_ATOM_LPU(kbdev, katom, &kbdev->gpu_props.js_features[js], - "ctx_nr,atom_nr"); - kbase_kinstr_jm_atom_hw_submit(katom); - - /* Update the slot's last katom submission kctx */ - ptr_slot_rb->last_kctx_tagged = SLOT_RB_TAG_KCTX(kctx); - - trace_sysgraph_gpu(SGR_SUBMIT, kctx->id, kbase_jd_atom_id(kctx, katom), js); - - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT), JS_COMMAND_START); - - return 0; -} - -/** - * kbasep_job_slot_update_head_start_timestamp - Update timestamp - * @kbdev: kbase device - * @js: job slot - * @end_timestamp: timestamp - * - * Update the start_timestamp of the job currently in the HEAD, based on the - * fact that we got an IRQ for the previous set of completed jobs. - * - * The estimate also takes into account the time the job was submitted, to - * work out the best estimate (which might still result in an over-estimate to - * the calculated time spent) - */ -static void kbasep_job_slot_update_head_start_timestamp(struct kbase_device *kbdev, unsigned int js, - ktime_t end_timestamp) -{ - ktime_t timestamp_diff; - struct kbase_jd_atom *katom; - - /* Checking the HEAD position for the job slot */ - katom = kbase_gpu_inspect(kbdev, js, 0); - if (katom != NULL) { - timestamp_diff = ktime_sub(end_timestamp, katom->start_timestamp); - if (ktime_to_ns(timestamp_diff) >= 0) { - /* Only update the timestamp if it's a better estimate - * than what's currently stored. This is because our - * estimate that accounts for the throttle time may be - * too much of an overestimate - */ - katom->start_timestamp = end_timestamp; - } - } -} - -/** - * kbasep_trace_tl_event_lpu_softstop - Call event_lpu_softstop timeline - * tracepoint - * @kbdev: kbase device - * @js: job slot - * - * Make a tracepoint call to the instrumentation module informing that - * softstop happened on given lpu (job slot). - */ -static void kbasep_trace_tl_event_lpu_softstop(struct kbase_device *kbdev, unsigned int js) -{ - KBASE_TLSTREAM_TL_EVENT_LPU_SOFTSTOP(kbdev, &kbdev->gpu_props.js_features[js]); -} - -void kbase_job_done(struct kbase_device *kbdev, u32 done) -{ - u32 count = 0; - ktime_t end_timestamp; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - KBASE_KTRACE_ADD_JM(kbdev, JM_IRQ, NULL, NULL, 0, done); - - end_timestamp = ktime_get_raw(); - - while (done) { - unsigned int i; - u32 failed = done >> 16; - - /* treat failed slots as finished slots */ - u32 finished = (done & 0xFFFF) | failed; - - /* Note: This is inherently unfair, as we always check for lower - * numbered interrupts before the higher numbered ones. - */ - i = (unsigned int)ffs((int)finished) - 1u; - - do { - u32 nr_done; - u32 active; - u32 completion_code = BASE_JD_EVENT_DONE; /* assume OK */ - u64 job_tail = 0; - - if (failed & (1u << i)) { - /* read out the job slot status code if the job - * slot reported failure - */ - completion_code = - kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(i, STATUS)); - - if (completion_code == BASE_JD_EVENT_STOPPED) { - u64 job_head; - - KBASE_TLSTREAM_AUX_EVENT_JOB_SLOT(kbdev, NULL, i, 0, - TL_JS_EVENT_SOFT_STOP); - - kbasep_trace_tl_event_lpu_softstop(kbdev, i); - - /* Soft-stopped job - read the value of - * JS_TAIL so that the job chain can - * be resumed - */ - job_tail = - kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(i, TAIL)); - job_head = - kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(i, HEAD)); - /* For a soft-stopped job chain js_tail should - * same as the js_head, but if not then the - * job chain was incorrectly marked as - * soft-stopped. In such case we should not - * be resuming the job chain from js_tail and - * report the completion_code as UNKNOWN. - */ - if (job_tail != job_head) - completion_code = BASE_JD_EVENT_UNKNOWN; - - } else if (completion_code == BASE_JD_EVENT_NOT_STARTED) { - /* PRLAM-10673 can cause a TERMINATED - * job to come back as NOT_STARTED, - * but the error interrupt helps us - * detect it - */ - completion_code = BASE_JD_EVENT_TERMINATED; - } - - kbase_gpu_irq_evict(kbdev, i, completion_code); - - /* Some jobs that encounter a BUS FAULT may - * result in corrupted state causing future - * jobs to hang. Reset GPU before allowing - * any other jobs on the slot to continue. - */ - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_3076)) { - if (completion_code == BASE_JD_EVENT_JOB_BUS_FAULT) { - if (kbase_prepare_to_reset_gpu_locked( - kbdev, RESET_FLAGS_NONE)) - kbase_reset_gpu_locked(kbdev); - } - } - } - - kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_CLEAR), - done & ((1u << i) | (1u << (i + 16)))); - active = kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_JS_STATE)); - - if (((active >> i) & 1) == 0 && (((done >> (i + 16)) & 1) == 0)) { - /* There is a potential race we must work - * around: - * - * 1. A job slot has a job in both current and - * next registers - * 2. The job in current completes - * successfully, the IRQ handler reads - * RAWSTAT and calls this function with the - * relevant bit set in "done" - * 3. The job in the next registers becomes the - * current job on the GPU - * 4. Sometime before the JOB_IRQ_CLEAR line - * above the job on the GPU _fails_ - * 5. The IRQ_CLEAR clears the done bit but not - * the failed bit. This atomically sets - * JOB_IRQ_JS_STATE. However since both jobs - * have now completed the relevant bits for - * the slot are set to 0. - * - * If we now did nothing then we'd incorrectly - * assume that _both_ jobs had completed - * successfully (since we haven't yet observed - * the fail bit being set in RAWSTAT). - * - * So at this point if there are no active jobs - * left we check to see if RAWSTAT has a failure - * bit set for the job slot. If it does we know - * that there has been a new failure that we - * didn't previously know about, so we make sure - * that we record this in active (but we wait - * for the next loop to deal with it). - * - * If we were handling a job failure (i.e. done - * has the relevant high bit set) then we know - * that the value read back from - * JOB_IRQ_JS_STATE is the correct number of - * remaining jobs because the failed job will - * have prevented any futher jobs from starting - * execution. - */ - u32 rawstat = - kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_RAWSTAT)); - - if ((rawstat >> (i + 16)) & 1) { - /* There is a failed job that we've - * missed - add it back to active - */ - active |= (1u << i); - } - } - - dev_dbg(kbdev->dev, "Job ended with status 0x%08X\n", completion_code); - - nr_done = kbase_backend_nr_atoms_submitted(kbdev, i); - nr_done -= (active >> i) & 1; - nr_done -= (active >> (i + 16)) & 1; - - if (nr_done == 0 || nr_done > SLOT_RB_SIZE) { - dev_warn(kbdev->dev, "Spurious interrupt on slot %u", i); - - goto spurious; - } - - count += nr_done; - - while (nr_done) { - if (likely(nr_done == 1)) { - kbase_gpu_complete_hw(kbdev, i, completion_code, job_tail, - &end_timestamp); - kbase_jm_try_kick_all(kbdev); - } else { - /* More than one job has completed. - * Since this is not the last job being - * reported this time it must have - * passed. This is because the hardware - * will not allow further jobs in a job - * slot to complete until the failed job - * is cleared from the IRQ status. - */ - kbase_gpu_complete_hw(kbdev, i, BASE_JD_EVENT_DONE, 0, - &end_timestamp); -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - /* Increment the end timestamp value by 1 ns to - * avoid having the same value for 'start_time_ns' - * and 'end_time_ns' for the 2nd atom whose job - * completion IRQ got merged with the 1st atom. - */ - end_timestamp = ktime_add(end_timestamp, ns_to_ktime(1)); -#endif - } - nr_done--; - } -spurious: - done = kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_RAWSTAT)); - - failed = done >> 16; - finished = (done & 0xFFFF) | failed; - if (done) - end_timestamp = ktime_get_raw(); - } while (finished & (1u << i)); - - kbasep_job_slot_update_head_start_timestamp(kbdev, i, end_timestamp); - } - - if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_COMMITTED) { - /* If we're trying to reset the GPU then we might be able to do - * it early (without waiting for a timeout) because some jobs - * have completed - */ - kbasep_try_reset_gpu_early_locked(kbdev); - } - KBASE_KTRACE_ADD_JM(kbdev, JM_IRQ_END, NULL, NULL, 0, count); -} - -void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, unsigned int js, - u32 action, base_jd_core_req core_reqs, - struct kbase_jd_atom *target_katom) -{ -#if KBASE_KTRACE_ENABLE - u32 status_reg_before; - u64 job_in_head_before; - u32 status_reg_after; - - WARN_ON(action & (~(u32)JS_COMMAND_MASK)); - - /* Check the head pointer */ - job_in_head_before = kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(js, HEAD)); - status_reg_before = kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(js, STATUS)); -#endif - - if (action == JS_COMMAND_SOFT_STOP) { - if (kbase_jd_katom_is_protected(target_katom)) { -#ifdef CONFIG_MALI_VALHALL_DEBUG - dev_dbg(kbdev->dev, - "Attempt made to soft-stop a job that cannot be soft-stopped. core_reqs = 0x%x", - (unsigned int)core_reqs); -#else - CSTD_UNUSED(core_reqs); -#endif /* CONFIG_MALI_VALHALL_DEBUG */ - return; - } - - /* We are about to issue a soft stop, so mark the atom as having - * been soft stopped - */ - target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_SOFT_STOPPED; - - /* Mark the point where we issue the soft-stop command */ - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_ISSUE(kbdev, target_katom); - - action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? - JS_COMMAND_SOFT_STOP_1 : - JS_COMMAND_SOFT_STOP_0; - } else if (action == JS_COMMAND_HARD_STOP) { - target_katom->atom_flags |= KBASE_KATOM_FLAG_BEEN_HARD_STOPPED; - - action = (target_katom->atom_flags & KBASE_KATOM_FLAGS_JOBCHAIN) ? - JS_COMMAND_HARD_STOP_1 : - JS_COMMAND_HARD_STOP_0; - } - - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, COMMAND), action); - -#if KBASE_KTRACE_ENABLE - status_reg_after = kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(js, STATUS)); - if (status_reg_after == BASE_JD_EVENT_ACTIVE) { - struct kbase_jd_atom *head; - struct kbase_context *head_kctx; - - head = kbase_gpu_inspect(kbdev, js, 0); - if (unlikely(!head)) { - dev_err(kbdev->dev, "Can't get a katom from js(%d)\n", js); - return; - } - head_kctx = head->kctx; - - if (status_reg_before == BASE_JD_EVENT_ACTIVE) - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_CHECK_HEAD, head_kctx, head, - job_in_head_before, js); - else - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); - - switch (action) { - case JS_COMMAND_SOFT_STOP: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP, head_kctx, head, head->jc, js); - break; - case JS_COMMAND_SOFT_STOP_0: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP_0, head_kctx, head, head->jc, - js); - break; - case JS_COMMAND_SOFT_STOP_1: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP_1, head_kctx, head, head->jc, - js); - break; - case JS_COMMAND_HARD_STOP: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP, head_kctx, head, head->jc, js); - break; - case JS_COMMAND_HARD_STOP_0: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_0, head_kctx, head, head->jc, - js); - break; - case JS_COMMAND_HARD_STOP_1: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, head_kctx, head, head->jc, - js); - break; - default: - WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, - (void *)target_katom, (void *)target_katom->kctx); - break; - } - } else { - if (status_reg_before == BASE_JD_EVENT_ACTIVE) - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, - job_in_head_before, js); - else - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_CHECK_HEAD, NULL, NULL, 0, js); - - switch (action) { - case JS_COMMAND_SOFT_STOP: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP, NULL, NULL, 0, js); - break; - case JS_COMMAND_SOFT_STOP_0: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP_0, NULL, NULL, 0, js); - break; - case JS_COMMAND_SOFT_STOP_1: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_SOFTSTOP_1, NULL, NULL, 0, js); - break; - case JS_COMMAND_HARD_STOP: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP, NULL, NULL, 0, js); - break; - case JS_COMMAND_HARD_STOP_0: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_0, NULL, NULL, 0, js); - break; - case JS_COMMAND_HARD_STOP_1: - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_HARDSTOP_1, NULL, NULL, 0, js); - break; - default: - WARN(1, "Unknown action %d on atom %pK in kctx %pK\n", action, - (void *)target_katom, (void *)target_katom->kctx); - break; - } - } -#endif -} - -void kbase_backend_jm_kill_running_jobs_from_kctx(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - unsigned int i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) - kbase_job_slot_hardstop(kctx, i, NULL); -} - -void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, - struct kbase_jd_atom *target_katom) -{ - struct kbase_device *kbdev; - unsigned int target_js = target_katom->slot_nr; - int i; - bool stop_sent = false; - - kbdev = kctx->kbdev; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = 0; i < kbase_backend_nr_atoms_on_slot(kbdev, target_js); i++) { - struct kbase_jd_atom *slot_katom; - - slot_katom = kbase_gpu_inspect(kbdev, target_js, i); - if (!slot_katom) - continue; - - if (kbase_js_atom_runs_before(kbdev, target_katom, slot_katom, - KBASE_ATOM_ORDERING_FLAG_SEQNR)) { - if (!stop_sent) - KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITIZED(kbdev, target_katom); - - kbase_job_slot_softstop(kbdev, target_js, slot_katom); - stop_sent = true; - } - } -} - -void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - unsigned long timeout = msecs_to_jiffies(ZAP_TIMEOUT); - - timeout = wait_event_timeout(kctx->jctx.zero_jobs_wait, kctx->jctx.job_nr == 0, - (long)timeout); - - if (timeout != 0) - timeout = wait_event_timeout(kctx->jctx.sched_info.ctx.is_scheduled_wait, - !kbase_ctx_flag(kctx, KCTX_SCHEDULED), (long)timeout); - - /* Neither wait timed out; all done! */ - if (timeout != 0) - goto exit; - - if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) { - dev_err(kbdev->dev, - "Issuing GPU soft-reset because jobs failed to be killed (within %d ms) as part of context termination (e.g. process exit)\n", - ZAP_TIMEOUT); - kbase_reset_gpu(kbdev); - } - - /* Wait for the reset to complete */ - kbase_reset_gpu_wait(kbdev); -exit: - dev_dbg(kbdev->dev, "Zap: Finished Context %pK", kctx); - - /* Ensure that the signallers of the waitqs have finished */ - mutex_lock(&kctx->jctx.lock); - mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - mutex_unlock(&kctx->jctx.lock); -} - -u32 kbase_backend_get_current_flush_id(struct kbase_device *kbdev) -{ - u32 flush_id = 0; - - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_FLUSH_REDUCTION)) { - mutex_lock(&kbdev->pm.lock); - if (kbase_io_is_gpu_powered(kbdev)) - flush_id = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(LATEST_FLUSH)); - mutex_unlock(&kbdev->pm.lock); - } - - return flush_id; -} - -int kbase_job_slot_init(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - return 0; -} -KBASE_EXPORT_TEST_API(kbase_job_slot_init); - -void kbase_job_slot_halt(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); -} - -void kbase_job_slot_term(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); -} -KBASE_EXPORT_TEST_API(kbase_job_slot_term); - -/** - * kbase_job_slot_softstop_swflags - Soft-stop a job with flags - * @kbdev: The kbase device - * @js: The job slot to soft-stop - * @target_katom: The job that should be soft-stopped (or NULL for any job) - * @sw_flags: Flags to pass in about the soft-stop - * - * Context: - * The job slot lock must be held when calling this function. - * The job slot must not already be in the process of being soft-stopped. - * - * Soft-stop the specified job slot, with extra information about the stop - * - * Where possible any job in the next register is evicted before the soft-stop. - */ -void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, unsigned int js, - struct kbase_jd_atom *target_katom, u32 sw_flags) -{ - dev_dbg(kbdev->dev, "Soft-stop atom %pK with flags 0x%x (s:%d)\n", target_katom, sw_flags, - js); - - if (sw_flags & JS_COMMAND_MASK) { - WARN(true, "Atom %pK in kctx %pK received non-NOP flags %d\n", (void *)target_katom, - target_katom ? (void *)target_katom->kctx : NULL, sw_flags); - sw_flags &= ~((u32)JS_COMMAND_MASK); - } - kbase_backend_soft_hard_stop_slot(kbdev, NULL, js, target_katom, - JS_COMMAND_SOFT_STOP | sw_flags); -} - -void kbase_job_slot_softstop(struct kbase_device *kbdev, unsigned int js, - struct kbase_jd_atom *target_katom) -{ - kbase_job_slot_softstop_swflags(kbdev, js, target_katom, 0u); -} - -void kbase_job_slot_hardstop(struct kbase_context *kctx, unsigned int js, - struct kbase_jd_atom *target_katom) -{ - struct kbase_device *kbdev = kctx->kbdev; - bool stopped; - - stopped = kbase_backend_soft_hard_stop_slot(kbdev, kctx, js, target_katom, - JS_COMMAND_HARD_STOP); - CSTD_UNUSED(stopped); -} - -void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, - base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom) -{ - u32 hw_action = action & JS_COMMAND_MASK; - - CSTD_UNUSED(core_reqs); - - /* For soft-stop, don't enter if soft-stop not allowed, or isn't - * causing disjoint. - */ - if (hw_action == JS_COMMAND_SOFT_STOP && (kbase_jd_katom_is_protected(target_katom) || - (0 == (action & JS_COMMAND_SW_CAUSES_DISJOINT)))) - return; - - /* Nothing to do if already logged disjoint state on this atom */ - if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) - return; - - target_katom->atom_flags |= KBASE_KATOM_FLAG_IN_DISJOINT; - kbase_disjoint_state_up(kbdev); -} - -void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, struct kbase_jd_atom *target_katom) -{ - if (target_katom->atom_flags & KBASE_KATOM_FLAG_IN_DISJOINT) { - target_katom->atom_flags &= ~KBASE_KATOM_FLAG_IN_DISJOINT; - kbase_disjoint_state_down(kbdev); - } -} - -int kbase_reset_gpu_prevent_and_wait(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - WARN(true, "%s Not implemented for JM GPUs", __func__); - return -EINVAL; -} - -int kbase_reset_gpu_try_prevent(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - WARN(true, "%s Not implemented for JM GPUs", __func__); - return -EINVAL; -} - -void kbase_reset_gpu_allow(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - WARN(true, "%s Not implemented for JM GPUs", __func__); -} - -void kbase_reset_gpu_assert_prevented(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - WARN(true, "%s Not implemented for JM GPUs", __func__); -} - -void kbase_reset_gpu_assert_failed_or_prevented(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - WARN(true, "%s Not implemented for JM GPUs", __func__); -} - -static void kbase_debug_dump_registers(struct kbase_device *kbdev) -{ - unsigned int i; - - kbase_io_history_dump(kbdev); - - dev_err(kbdev->dev, "Register state:"); - dev_err(kbdev->dev, " GPU_IRQ_RAWSTAT=0x%08x GPU_STATUS=0x%08x", - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_RAWSTAT)), - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_STATUS))); - dev_err(kbdev->dev, " JOB_IRQ_RAWSTAT=0x%08x JOB_IRQ_JS_STATE=0x%08x", - kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_RAWSTAT)), - kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_JS_STATE))); - for (i = 0; i < 3; i++) { - dev_err(kbdev->dev, " JS%u_STATUS=0x%08x JS%u_HEAD=0x%016llx", i, - kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(i, STATUS)), i, - kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(i, HEAD))); - } - dev_err(kbdev->dev, " MMU_IRQ_RAWSTAT=0x%08x GPU_FAULTSTATUS=0x%08x", - kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_RAWSTAT)), - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_FAULTSTATUS))); - dev_err(kbdev->dev, " GPU_IRQ_MASK=0x%08x JOB_IRQ_MASK=0x%08x MMU_IRQ_MASK=0x%08x", - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)), - kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK)), - kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK))); - dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x", - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(PWR_OVERRIDE0)), - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(PWR_OVERRIDE1))); - dev_err(kbdev->dev, " SHADER_CONFIG=0x%08x L2_MMU_CONFIG=0x%08x", - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(SHADER_CONFIG)), - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_MMU_CONFIG))); - dev_err(kbdev->dev, " TILER_CONFIG=0x%08x JM_CONFIG=0x%08x", - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(TILER_CONFIG)), - kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(JM_CONFIG))); -} - -static void kbasep_reset_timeout_worker(struct work_struct *data) -{ - unsigned long flags; - struct kbase_device *kbdev; - ktime_t end_timestamp = ktime_get_raw(); - struct kbasep_js_device_data *js_devdata; - bool silent = false; - - kbdev = container_of(data, struct kbase_device, hwaccess.backend.reset_work); - - js_devdata = &kbdev->js_data; - - if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_SILENT) - silent = true; - - if (kbase_is_quick_reset_enabled(kbdev)) - silent = true; - - KBASE_KTRACE_ADD_JM(kbdev, JM_BEGIN_RESET_WORKER, NULL, NULL, 0u, 0); - - /* Disable GPU hardware counters. - * This call will block until counters are disabled. - */ - kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); - - /* Make sure the timer has completed - this cannot be done from - * interrupt context, so this cannot be done within - * kbasep_try_reset_gpu_early. - */ - hrtimer_cancel(&kbdev->hwaccess.backend.reset_timer); - - if (kbase_pm_context_active_handle_suspend(kbdev, - KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { - /* This would re-activate the GPU. Since it's already idle, - * there's no need to reset it - */ - atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING); - kbase_disjoint_state_down(kbdev); - wake_up(&kbdev->hwaccess.backend.reset_wait); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - return; - } - - WARN(kbdev->irq_reset_flush, "%s: GPU reset already in flight\n", __func__); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - spin_lock(&kbdev->mmu_mask_change); - kbase_pm_reset_start_locked(kbdev); - - /* We're about to flush out the IRQs and their bottom half's */ - kbdev->irq_reset_flush = true; - - /* Disable IRQ to avoid IRQ handlers to kick in after releasing the - * spinlock; this also clears any outstanding interrupts - */ - kbase_pm_disable_interrupts_nolock(kbdev); - - spin_unlock(&kbdev->mmu_mask_change); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* Ensure that any IRQ handlers have finished - * Must be done without any locks IRQ handlers will take - */ - kbase_synchronize_irqs(kbdev); - - /* Flush out any in-flight work items */ - kbase_flush_mmu_wqs(kbdev); - - /* The flush has completed so reset the active indicator */ - kbdev->irq_reset_flush = false; - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TMIX_8463)) { - u64 val; - const u32 timeout_us = - kbase_get_timeout_ms(kbdev, KBASE_CLEAN_CACHE_TIMEOUT) * USEC_PER_MSEC; - /* Ensure that L2 is not transitioning when we send the reset command */ - const int err = kbase_reg_poll64_timeout(kbdev, GPU_CONTROL_ENUM(L2_PWRTRANS), val, - !val, 0, timeout_us, false); - - WARN(err, "L2 power transition timed out while trying to reset\n"); - } - - mutex_lock(&kbdev->pm.lock); - /* We hold the pm lock, so there ought to be a current policy */ - if (unlikely(!kbdev->pm.backend.pm_current_policy)) - dev_warn(kbdev->dev, "No power policy set!"); - - /* All slot have been soft-stopped and we've waited - * SOFT_STOP_RESET_TIMEOUT for the slots to clear, at this point we - * assume that anything that is still left on the GPU is stuck there and - * we'll kill it when we reset the GPU - */ - - if (!silent) - dev_err(kbdev->dev, "Resetting GPU (allowing up to %d ms)", RESET_TIMEOUT); - - /* Output the state of some interesting registers to help in the - * debugging of GPU resets - */ - if (!silent) - kbase_debug_dump_registers(kbdev); - - /* Complete any jobs that were still on the GPU */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbdev->protected_mode = false; - if (!kbdev->pm.backend.protected_entry_transition_override) - kbase_backend_reset(kbdev, &end_timestamp); - kbase_pm_metrics_update(kbdev, NULL); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* Tell hardware counters a reset is about to occur. - * If the instr backend is in an unrecoverable error state (e.g. due to - * HW being unresponsive), this will transition the backend out of - * it, on the assumption a reset will fix whatever problem there was. - */ - kbase_instr_hwcnt_on_before_reset(kbdev); - - /* Reset the GPU */ - kbase_pm_init_hw(kbdev, 0); - - mutex_unlock(&kbdev->pm.lock); - - mutex_lock(&js_devdata->runpool_mutex); - - mutex_lock(&kbdev->mmu_hw_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_ctx_sched_restore_all_as(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - - kbase_pm_enable_interrupts(kbdev); - - kbase_disjoint_state_down(kbdev); - - mutex_unlock(&js_devdata->runpool_mutex); - - mutex_lock(&kbdev->pm.lock); - - kbase_pm_reset_complete(kbdev); - - /* Find out what cores are required now */ - kbase_pm_update_cores_state(kbdev); - - /* Synchronously request and wait for those cores, because if - * instrumentation is enabled it would need them immediately. - */ - kbase_pm_wait_for_desired_state(kbdev); - - mutex_unlock(&kbdev->pm.lock); - - atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING); - - wake_up(&kbdev->hwaccess.backend.reset_wait); - if (!silent) - dev_err(kbdev->dev, "Reset complete"); - - /* Try submitting some jobs to restart processing */ - KBASE_KTRACE_ADD_JM(kbdev, JM_SUBMIT_AFTER_RESET, NULL, NULL, 0u, 0); - kbase_js_sched_all(kbdev); - - /* Process any pending slot updates */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_backend_slot_update(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - kbase_pm_context_idle(kbdev); - - /* Re-enable GPU hardware counters */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - KBASE_KTRACE_ADD_JM(kbdev, JM_END_RESET_WORKER, NULL, NULL, 0u, 0); -} - -static enum hrtimer_restart kbasep_reset_timer_callback(struct hrtimer *timer) -{ - struct kbase_device *kbdev = - container_of(timer, struct kbase_device, hwaccess.backend.reset_timer); - - /* Reset still pending? */ - if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED, - KBASE_RESET_GPU_HAPPENING) == KBASE_RESET_GPU_COMMITTED) - queue_work(kbdev->hwaccess.backend.reset_workq, - &kbdev->hwaccess.backend.reset_work); - - return HRTIMER_NORESTART; -} - -/* - * If all jobs are evicted from the GPU then we can reset the GPU - * immediately instead of waiting for the timeout to elapse - */ - -static void kbasep_try_reset_gpu_early_locked(struct kbase_device *kbdev) -{ - unsigned int i; - u32 pending_jobs = 0; - - /* Count the number of jobs */ - for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) - pending_jobs += kbase_backend_nr_atoms_submitted(kbdev, i); - - if (pending_jobs > 0) { - /* There are still jobs on the GPU - wait */ - return; - } - - /* To prevent getting incorrect registers when dumping failed job, - * skip early reset. - */ - if (atomic_read(&kbdev->job_fault_debug) > 0) - return; - - /* Check that the reset has been committed to (i.e. kbase_reset_gpu has - * been called), and that no other thread beat this thread to starting - * the reset - */ - if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED, - KBASE_RESET_GPU_HAPPENING) != KBASE_RESET_GPU_COMMITTED) { - /* Reset has already occurred */ - return; - } - - queue_work(kbdev->hwaccess.backend.reset_workq, &kbdev->hwaccess.backend.reset_work); -} - -static void kbasep_try_reset_gpu_early(struct kbase_device *kbdev) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbasep_try_reset_gpu_early_locked(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -} - -/** - * kbase_prepare_to_reset_gpu_locked - Prepare for resetting the GPU - * @kbdev: kbase device - * @flags: Bitfield indicating impact of reset (see flag defines) - * - * This function soft-stops all the slots to ensure that as many jobs as - * possible are saved. - * - * Return: boolean which should be interpreted as follows: - * true - Prepared for reset, kbase_reset_gpu_locked should be called. - * false - Another thread is performing a reset, kbase_reset_gpu should - * not be called. - */ -bool kbase_prepare_to_reset_gpu_locked(struct kbase_device *kbdev, unsigned int flags) -{ - unsigned int i; - - if (kbase_io_is_aw_removed(kbdev)) { - /* GPU access has been removed, reset will be done by - * Arbiter instead - */ - return false; - } - - if (flags & RESET_FLAGS_HWC_UNRECOVERABLE_ERROR) - kbase_instr_hwcnt_on_unrecoverable_error(kbdev); - - if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING, - KBASE_RESET_GPU_PREPARED) != KBASE_RESET_GPU_NOT_PENDING) { - /* Some other thread is already resetting the GPU */ - return false; - } - - kbase_disjoint_state_up(kbdev); - - for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) - kbase_job_slot_softstop(kbdev, i, NULL); - - return true; -} - -bool kbase_prepare_to_reset_gpu(struct kbase_device *kbdev, unsigned int flags) -{ - unsigned long lock_flags; - bool ret; - - spin_lock_irqsave(&kbdev->hwaccess_lock, lock_flags); - ret = kbase_prepare_to_reset_gpu_locked(kbdev, flags); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, lock_flags); - - return ret; -} -KBASE_EXPORT_TEST_API(kbase_prepare_to_reset_gpu); - -/* - * This function should be called after kbase_prepare_to_reset_gpu if it - * returns true. It should never be called without a corresponding call to - * kbase_prepare_to_reset_gpu. - * - * After this function is called (or not called if kbase_prepare_to_reset_gpu - * returned false), the caller should wait for - * kbdev->hwaccess.backend.reset_waitq to be signalled to know when the reset - * has completed. - */ -void kbase_reset_gpu(struct kbase_device *kbdev) -{ - /* Note this is an assert/atomic_set because it is a software issue for - * a race to be occurring here - */ - if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) - return; - atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); - - if (!kbase_is_quick_reset_enabled(kbdev)) - dev_err(kbdev->dev, - "Preparing to soft-reset GPU: Waiting (up to %d ms) for all jobs to complete soft-stop\n", - kbdev->reset_timeout_ms); - - hrtimer_start(&kbdev->hwaccess.backend.reset_timer, - HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), HRTIMER_MODE_REL); - - /* Try resetting early */ - kbasep_try_reset_gpu_early(kbdev); -} -KBASE_EXPORT_TEST_API(kbase_reset_gpu); - -void kbase_reset_gpu_locked(struct kbase_device *kbdev) -{ - /* Note this is an assert/atomic_set because it is a software issue for - * a race to be occurring here - */ - if (WARN_ON(atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_PREPARED)) - return; - atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_COMMITTED); - - if (!kbase_is_quick_reset_enabled(kbdev)) - dev_err(kbdev->dev, - "Preparing to soft-reset GPU: Waiting (up to %d ms) for all jobs to complete soft-stop\n", - kbdev->reset_timeout_ms); - hrtimer_start(&kbdev->hwaccess.backend.reset_timer, - HR_TIMER_DELAY_MSEC(kbdev->reset_timeout_ms), HRTIMER_MODE_REL); - - /* Try resetting early */ - kbasep_try_reset_gpu_early_locked(kbdev); -} - -int kbase_reset_gpu_silent(struct kbase_device *kbdev) -{ - if (atomic_cmpxchg(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING, - KBASE_RESET_GPU_SILENT) != KBASE_RESET_GPU_NOT_PENDING) { - /* Some other thread is already resetting the GPU */ - return -EAGAIN; - } - - kbase_disjoint_state_up(kbdev); - - queue_work(kbdev->hwaccess.backend.reset_workq, &kbdev->hwaccess.backend.reset_work); - - return 0; -} - -bool kbase_reset_gpu_is_active(struct kbase_device *kbdev) -{ - if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_NOT_PENDING) - return false; - - return true; -} - -bool kbase_reset_gpu_is_not_pending(struct kbase_device *kbdev) -{ - return atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_NOT_PENDING; -} - -int kbase_reset_gpu_wait(struct kbase_device *kbdev) -{ - wait_event(kbdev->hwaccess.backend.reset_wait, - atomic_read(&kbdev->hwaccess.backend.reset_gpu) == KBASE_RESET_GPU_NOT_PENDING); - - return 0; -} -KBASE_EXPORT_TEST_API(kbase_reset_gpu_wait); - -int kbase_reset_gpu_init(struct kbase_device *kbdev) -{ - kbdev->hwaccess.backend.reset_workq = alloc_workqueue("Mali reset workqueue", 0, 1); - if (kbdev->hwaccess.backend.reset_workq == NULL) - return -ENOMEM; - - INIT_WORK(&kbdev->hwaccess.backend.reset_work, kbasep_reset_timeout_worker); - - hrtimer_init(&kbdev->hwaccess.backend.reset_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - kbdev->hwaccess.backend.reset_timer.function = kbasep_reset_timer_callback; - - return 0; -} - -void kbase_reset_gpu_term(struct kbase_device *kbdev) -{ - destroy_workqueue(kbdev->hwaccess.backend.reset_workq); -} - -static u64 kbasep_apply_limited_core_mask(const struct kbase_device *kbdev, const u64 affinity, - const u64 limited_core_mask) -{ - const u64 result = affinity & limited_core_mask; - -#ifdef CONFIG_MALI_VALHALL_DEBUG - dev_dbg(kbdev->dev, - "Limiting affinity due to BASE_JD_REQ_LIMITED_CORE_MASK from 0x%lx to 0x%lx (mask is 0x%lx)\n", - (unsigned long)affinity, (unsigned long)result, (unsigned long)limited_core_mask); -#else - CSTD_UNUSED(kbdev); -#endif - - return result; -} diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_internal.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_internal.h deleted file mode 100644 index 2dd651a096fd..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_internal.h +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Job Manager backend-specific low-level APIs. - */ - -#ifndef _KBASE_JM_HWACCESS_H_ -#define _KBASE_JM_HWACCESS_H_ - -#include -#include -#include - -#include -#include - -/** - * kbase_job_done_slot() - Complete the head job on a particular job-slot - * @kbdev: Device pointer - * @s: Job slot - * @completion_code: Completion code of job reported by GPU - * @job_tail: Job tail address reported by GPU - * @end_timestamp: Timestamp of job completion - */ -void kbase_job_done_slot(struct kbase_device *kbdev, int s, u32 completion_code, u64 job_tail, - ktime_t *end_timestamp); - -/** - * kbase_job_hw_submit() - Submit a job to the GPU - * @kbdev: Device pointer - * @katom: Atom to submit - * @js: Job slot to submit on - * - * The caller must check kbasep_jm_is_submit_slots_free() != false before - * calling this. - * - * The following locking conditions are made on the caller: - * - it must hold the hwaccess_lock - * - * Return: 0 if the job was successfully submitted to hardware, an error otherwise. - */ -int kbase_job_hw_submit(struct kbase_device *kbdev, struct kbase_jd_atom *katom, unsigned int js); - -#if !MALI_USE_CSF -/** - * kbasep_job_slot_soft_or_hard_stop_do_action() - Perform a soft or hard stop - * on the specified atom - * @kbdev: Device pointer - * @js: Job slot to stop on - * @action: The action to perform, either JS_COMMAND_HARD_STOP or - * JS_COMMAND_SOFT_STOP - * @core_reqs: Core requirements of atom to stop - * @target_katom: Atom to stop - * - * The following locking conditions are made on the caller: - * - it must hold the hwaccess_lock - */ -void kbasep_job_slot_soft_or_hard_stop_do_action(struct kbase_device *kbdev, unsigned int js, - u32 action, base_jd_core_req core_reqs, - struct kbase_jd_atom *target_katom); -#endif /* !MALI_USE_CSF */ - -/** - * kbase_backend_soft_hard_stop_slot() - Soft or hard stop jobs on a given job - * slot belonging to a given context. - * @kbdev: Device pointer - * @kctx: Context pointer. May be NULL - * @katom: Specific atom to stop. May be NULL - * @js: Job slot to hard stop - * @action: The action to perform, either JS_COMMAND_HARD_STOP or - * JS_COMMAND_SOFT_STOP - * - * If no context is provided then all jobs on the slot will be soft or hard - * stopped. - * - * If a katom is provided then only that specific atom will be stopped. In this - * case the kctx parameter is ignored. - * - * Jobs that are on the slot but are not yet on the GPU will be unpulled and - * returned to the job scheduler. - * - * Return: true if an atom was stopped, false otherwise - */ -bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js, struct kbase_jd_atom *katom, u32 action); - -/** - * kbase_job_slot_init - Initialise job slot framework - * @kbdev: Device pointer - * - * Called on driver initialisation - * - * Return: 0 on success - */ -int kbase_job_slot_init(struct kbase_device *kbdev); - -/** - * kbase_job_slot_halt - Halt the job slot framework - * @kbdev: Device pointer - * - * Should prevent any further job slot processing - */ -void kbase_job_slot_halt(struct kbase_device *kbdev); - -/** - * kbase_job_slot_term - Terminate job slot framework - * @kbdev: Device pointer - * - * Called on driver termination - */ -void kbase_job_slot_term(struct kbase_device *kbdev); - -/** - * kbase_gpu_cache_clean - Cause a GPU cache clean & flush - * @kbdev: Device pointer - * - * Caller must not be in IRQ context - */ -void kbase_gpu_cache_clean(struct kbase_device *kbdev); - -#endif /* _KBASE_JM_HWACCESS_H_ */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.c deleted file mode 100644 index b211dd9748ca..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.c +++ /dev/null @@ -1,1793 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Register-based HW access backend specific APIs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) -#include -#endif -#include -#include -#include -#include -#include - -/** - * SLOT_RB_EMPTY - Return whether the specified ringbuffer is empty. - * - * @rb: ring buffer - * - * Note: HW access lock must be held - */ -#define SLOT_RB_EMPTY(rb) (rb->write_idx == rb->read_idx) - -/** - * SLOT_RB_ENTRIES - Return number of atoms currently in the specified ringbuffer. - * - * @rb: ring buffer - * - * Note: HW access lock must be held - */ -#define SLOT_RB_ENTRIES(rb) ((int)(s8)(rb->write_idx - rb->read_idx)) - -static void kbase_gpu_release_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - ktime_t *end_timestamp); - -/** - * kbase_gpu_enqueue_atom - Enqueue an atom in the HW access ringbuffer - * @kbdev: Device pointer - * @katom: Atom to enqueue - * - * Context: Caller must hold the HW access lock - */ -static void kbase_gpu_enqueue_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[katom->slot_nr]; - - WARN_ON(SLOT_RB_ENTRIES(rb) >= SLOT_RB_SIZE); - - lockdep_assert_held(&kbdev->hwaccess_lock); - - rb->entries[rb->write_idx & SLOT_RB_MASK].katom = katom; - rb->write_idx++; - - katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_BLOCKED; -} - -/** - * kbase_gpu_dequeue_atom - Remove an atom from the HW access ringbuffer, once - * it has been completed - * @kbdev: Device pointer - * @js: Job slot to remove atom from - * @end_timestamp: Pointer to timestamp of atom completion. May be NULL, in - * which case current time will be used. - * - * Context: Caller must hold the HW access lock - * - * Return: Atom removed from ringbuffer - */ -static struct kbase_jd_atom *kbase_gpu_dequeue_atom(struct kbase_device *kbdev, unsigned int js, - ktime_t *end_timestamp) -{ - struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; - struct kbase_jd_atom *katom; - - if (SLOT_RB_EMPTY(rb)) { - WARN(1, "GPU ringbuffer unexpectedly empty\n"); - return NULL; - } - - lockdep_assert_held(&kbdev->hwaccess_lock); - - katom = rb->entries[rb->read_idx & SLOT_RB_MASK].katom; - - kbase_gpu_release_atom(kbdev, katom, end_timestamp); - - rb->read_idx++; - - katom->gpu_rb_state = KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB; - - return katom; -} - -struct kbase_jd_atom *kbase_gpu_inspect(struct kbase_device *kbdev, unsigned int js, int idx) -{ - struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if ((SLOT_RB_ENTRIES(rb) - 1) < idx) - return NULL; /* idx out of range */ - - return rb->entries[(rb->read_idx + idx) & SLOT_RB_MASK].katom; -} - -struct kbase_jd_atom *kbase_backend_inspect_tail(struct kbase_device *kbdev, unsigned int js) -{ - struct slot_rb *rb = &kbdev->hwaccess.backend.slot_rb[js]; - - if (SLOT_RB_EMPTY(rb)) - return NULL; - - return rb->entries[(rb->write_idx - 1) & SLOT_RB_MASK].katom; -} - -bool kbase_gpu_atoms_submitted_any(struct kbase_device *kbdev) -{ - unsigned int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - int i; - - for (i = 0; i < SLOT_RB_SIZE; i++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); - - if (katom && katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) - return true; - } - } - return false; -} - -u32 kbase_backend_nr_atoms_submitted(struct kbase_device *kbdev, unsigned int js) -{ - u32 nr = 0; - int i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = 0; i < SLOT_RB_SIZE; i++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); - - if (katom && (katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED)) - nr++; - } - - return nr; -} - -int kbase_backend_nr_atoms_on_slot(struct kbase_device *kbdev, unsigned int js) -{ - int nr = 0; - int i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = 0; i < SLOT_RB_SIZE; i++) { - if (kbase_gpu_inspect(kbdev, js, i)) - nr++; - } - - return nr; -} - -static int kbase_gpu_nr_atoms_on_slot_min(struct kbase_device *kbdev, unsigned int js, - enum kbase_atom_gpu_rb_state min_rb_state) -{ - int nr = 0; - int i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = 0; i < SLOT_RB_SIZE; i++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); - - if (katom && (katom->gpu_rb_state >= min_rb_state)) - nr++; - } - - return nr; -} - -/** - * check_secure_atom - Check if the given atom is in the given secure state and - * has a ringbuffer state of at least - * KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION - * @katom: Atom pointer - * @secure: Desired secure state - * - * Return: true if atom is in the given state, false otherwise - */ -static bool check_secure_atom(struct kbase_jd_atom *katom, bool secure) -{ - if (katom->gpu_rb_state >= KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION && - ((kbase_jd_katom_is_protected(katom) && secure) || - (!kbase_jd_katom_is_protected(katom) && !secure))) - return true; - - return false; -} - -/** - * kbase_gpu_check_secure_atoms - Check if there are any atoms in the given - * secure state in the ringbuffers of at least - * state - * KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE - * @kbdev: Device pointer - * @secure: Desired secure state - * - * Return: true if any atoms are in the given state, false otherwise - */ -static bool kbase_gpu_check_secure_atoms(struct kbase_device *kbdev, bool secure) -{ - unsigned int js; - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - int i; - - for (i = 0; i < SLOT_RB_SIZE; i++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, i); - - if (katom) { - if (check_secure_atom(katom, secure)) - return true; - } - } - } - - return false; -} - -int kbase_backend_slot_free(struct kbase_device *kbdev, unsigned int js) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) { - /* The GPU is being reset - so prevent submission */ - return 0; - } - - return SLOT_RB_SIZE - kbase_backend_nr_atoms_on_slot(kbdev, js); -} - -/** - * trace_atom_completion_for_gpu_metrics - Report the completion of atom for the - * purpose of emitting power/gpu_work_period - * tracepoint. - * - * @katom: Pointer to the atom that completed execution on GPU. - * @end_timestamp: Pointer to the timestamp of atom completion. May be NULL, in - * which case current time will be used. - * - * The function would also report the start for an atom that was in the HEAD_NEXT - * register. - * - * Note: Caller must hold the HW access lock. - */ -static inline void trace_atom_completion_for_gpu_metrics(struct kbase_jd_atom *const katom, - ktime_t *end_timestamp) -{ -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - u64 complete_ns; - struct kbase_context *kctx = katom->kctx; - struct kbase_jd_atom *queued = kbase_gpu_inspect(kctx->kbdev, katom->slot_nr, 1); - -#ifdef CONFIG_MALI_VALHALL_DEBUG - WARN_ON(!kbase_gpu_inspect(kctx->kbdev, katom->slot_nr, 0)); -#endif - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - if (unlikely(queued == katom)) - return; - - /* A protected atom and a non-protected atom cannot be in the RB_SUBMITTED - * state at the same time in the job slot ringbuffer. Atom submission state - * machine prevents the submission of a non-protected atom until all - * protected atoms have completed and GPU has exited the protected mode. - * This implies that if the queued atom is in RB_SUBMITTED state, it shall - * be a protected atom and so we can return early. - */ - if (unlikely(kbase_jd_katom_is_protected(katom))) - return; - - if (likely(end_timestamp)) - complete_ns = ktime_to_ns(*end_timestamp); - else - complete_ns = ktime_get_raw_ns(); - - kbase_gpu_metrics_ctx_end_activity(kctx, complete_ns); - if (queued && queued->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) - kbase_gpu_metrics_ctx_start_activity(queued->kctx, complete_ns); -#else - CSTD_UNUSED(katom); - CSTD_UNUSED(end_timestamp); -#endif -} - -static void kbase_gpu_release_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - ktime_t *end_timestamp) -{ - struct kbase_context *kctx = katom->kctx; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - switch (katom->gpu_rb_state) { - case KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB: - /* Should be impossible */ - WARN(1, "Attempting to release atom not in ringbuffer\n"); - break; - - case KBASE_ATOM_GPU_RB_SUBMITTED: - trace_atom_completion_for_gpu_metrics(katom, end_timestamp); - kbase_kinstr_jm_atom_hw_release(katom); - /* Inform power management at start/finish of atom so it can - * update its GPU utilisation metrics. Mark atom as not - * submitted beforehand. - */ - katom->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; - kbase_pm_metrics_update(kbdev, end_timestamp); - - /* Inform platform at start/finish of atom */ - kbasep_platform_event_atom_complete(katom); - - if (katom->core_req & BASE_JD_REQ_PERMON) - kbase_pm_release_gpu_cycle_counter_nolock(kbdev); - - KBASE_TLSTREAM_TL_NRET_ATOM_LPU(kbdev, katom, - &kbdev->gpu_props.js_features[katom->slot_nr]); - KBASE_TLSTREAM_TL_NRET_ATOM_AS(kbdev, katom, &kbdev->as[kctx->as_nr]); - KBASE_TLSTREAM_TL_NRET_CTX_LPU(kbdev, kctx, - &kbdev->gpu_props.js_features[katom->slot_nr]); - - /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_READY: - /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE: - break; - - case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION: - if (kbase_jd_katom_is_protected(katom) && - (katom->protected_state.enter != KBASE_ATOM_ENTER_PROTECTED_CHECK) && - (katom->protected_state.enter != KBASE_ATOM_ENTER_PROTECTED_HWCNT)) { - kbase_pm_protected_override_disable(kbdev); - kbase_pm_update_cores_state_nolock(kbdev); - } - if (kbase_jd_katom_is_protected(katom) && - (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_IDLE_L2)) - kbase_pm_protected_entry_override_disable(kbdev); - if (!kbase_jd_katom_is_protected(katom) && - (katom->protected_state.exit != KBASE_ATOM_EXIT_PROTECTED_CHECK) && - (katom->protected_state.exit != KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT)) { - kbase_pm_protected_override_disable(kbdev); - kbase_pm_update_cores_state_nolock(kbdev); - } - - if (katom->protected_state.enter != KBASE_ATOM_ENTER_PROTECTED_CHECK || - katom->protected_state.exit != KBASE_ATOM_EXIT_PROTECTED_CHECK) - kbdev->protected_mode_transition = false; - - /* If the atom is at KBASE_ATOM_ENTER_PROTECTED_HWCNT state, it means - * one of two events prevented it from progressing to the next state and - * ultimately reach protected mode: - * - hwcnts were enabled, and the atom had to schedule a worker to - * disable them. - * - the hwcnts were already disabled, but some other error occurred. - * In the first case, if the worker has not yet completed - * (kbdev->protected_mode_hwcnt_disabled == false), we need to re-enable - * them and signal to the worker they have already been enabled - */ - if (kbase_jd_katom_is_protected(katom) && - (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_HWCNT)) { - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - } - } - - /* If the atom has suspended hwcnt but has not yet entered - * protected mode, then resume hwcnt now. If the GPU is now in - * protected mode then hwcnt will be resumed by GPU reset so - * don't resume it here. - */ - if (kbase_jd_katom_is_protected(katom) && - ((katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_IDLE_L2) || - (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY) || - (katom->protected_state.enter == KBASE_ATOM_ENTER_PROTECTED_FINISHED))) { - WARN_ON(!kbdev->protected_mode_hwcnt_disabled); - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - } - } - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) { - if (katom->atom_flags & KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT) { - kbase_pm_protected_l2_override(kbdev, false); - katom->atom_flags &= ~KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT; - } - } - - /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV: - /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_BLOCKED: - /* ***FALLTHROUGH: TRANSITION TO LOWER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_RETURN_TO_JS: - break; - } - - katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_BLOCKED; - katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; -} - -static void kbase_gpu_mark_atom_for_return(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, JM_MARK_FOR_RETURN_TO_JS, katom->kctx, katom, - katom->jc, katom->slot_nr, katom->event_code); - kbase_gpu_release_atom(kbdev, katom, NULL); - katom->gpu_rb_state = KBASE_ATOM_GPU_RB_RETURN_TO_JS; -} - -/** - * other_slots_busy - Determine if any job slots other than @js are currently - * running atoms - * @kbdev: Device pointer - * @js: Job slot - * - * Return: true if any slots other than @js are busy, false otherwise - */ -static inline bool other_slots_busy(struct kbase_device *kbdev, unsigned int js) -{ - unsigned int slot; - - for (slot = 0; slot < kbdev->gpu_props.num_job_slots; slot++) { - if (slot == js) - continue; - - if (kbase_gpu_nr_atoms_on_slot_min(kbdev, slot, KBASE_ATOM_GPU_RB_SUBMITTED)) - return true; - } - - return false; -} - -static inline bool kbase_gpu_in_protected_mode(struct kbase_device *kbdev) -{ - return kbdev->protected_mode; -} - -static void kbase_gpu_disable_coherent(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* - * When entering into protected mode, we must ensure that the - * GPU is not operating in coherent mode as well. This is to - * ensure that no protected memory can be leaked. - */ - if (kbdev->system_coherency == COHERENCY_ACE) - kbase_cache_set_coherency_mode(kbdev, COHERENCY_ACE_LITE); -} - -static int kbase_gpu_protected_mode_enter(struct kbase_device *kbdev) -{ - int err = -EINVAL; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - WARN_ONCE(!kbdev->protected_ops, - "Cannot enter protected mode: protected callbacks not specified.\n"); - - if (kbdev->protected_ops) { - /* Switch GPU to protected mode */ - err = kbdev->protected_ops->protected_mode_enable(kbdev->protected_dev); - - if (err) { - dev_warn(kbdev->dev, "Failed to enable protected mode: %d\n", err); - } else { - kbdev->protected_mode = true; - kbase_ipa_protection_mode_switch_event(kbdev); - } - } - - return err; -} - -static int kbase_gpu_protected_mode_reset(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - WARN_ONCE(!kbdev->protected_ops, - "Cannot exit protected mode: protected callbacks not specified.\n"); - - if (!kbdev->protected_ops) - return -EINVAL; - - /* The protected mode disable callback will be called as part of reset - */ - return kbase_reset_gpu_silent(kbdev); -} - -static int kbase_jm_protected_entry(struct kbase_device *kbdev, struct kbase_jd_atom **katom, - int idx, unsigned int js) -{ - int err = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - err = kbase_gpu_protected_mode_enter(kbdev); - - /* - * Regardless of result before this call, we are no longer - * transitioning the GPU. - */ - - kbdev->protected_mode_transition = false; - kbase_pm_protected_override_disable(kbdev); - kbase_pm_update_cores_state_nolock(kbdev); - - KBASE_TLSTREAM_AUX_PROTECTED_ENTER_END(kbdev, kbdev); - if (err) { - /* - * Failed to switch into protected mode. - * - * At this point we expect: - * katom->gpu_rb_state = KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION && - * katom->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_FINISHED - * ==> - * kbdev->protected_mode_hwcnt_disabled = false - */ - katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID; - kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); - /* - * Only return if head atom or previous atom - * already removed - as atoms must be returned - * in order. - */ - if (idx == 0 || katom[0]->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { - kbase_gpu_dequeue_atom(kbdev, js, NULL); - kbase_jm_return_atom_to_js(kbdev, katom[idx]); - } - - return -EINVAL; - } - - /* - * Protected mode sanity checks. - */ - WARN(kbase_jd_katom_is_protected(katom[idx]) != kbase_gpu_in_protected_mode(kbdev), - "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", - kbase_jd_katom_is_protected(katom[idx]), kbase_gpu_in_protected_mode(kbdev)); - katom[idx]->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; - - return err; -} - -static int kbase_jm_enter_protected_mode(struct kbase_device *kbdev, struct kbase_jd_atom **katom, - int idx, unsigned int js) -{ - int err = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - switch (katom[idx]->protected_state.enter) { - case KBASE_ATOM_ENTER_PROTECTED_CHECK: - KBASE_TLSTREAM_AUX_PROTECTED_ENTER_START(kbdev, kbdev); - /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV - * should ensure that we are not already transitiong, and that - * there are no atoms currently on the GPU. - */ - WARN_ON(kbdev->protected_mode_transition); - WARN_ON(kbase_gpu_atoms_submitted_any(kbdev)); - /* If hwcnt is disabled, it means we didn't clean up correctly - * during last exit from protected mode. - */ - WARN_ON(kbdev->protected_mode_hwcnt_disabled); - - katom[idx]->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_HWCNT; - - kbdev->protected_mode_transition = true; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_ENTER_PROTECTED_HWCNT: - /* See if we can get away with disabling hwcnt atomically */ - kbdev->protected_mode_hwcnt_desired = false; - if (!kbdev->protected_mode_hwcnt_disabled) { - if (kbase_hwcnt_context_disable_atomic(kbdev->hwcnt_gpu_ctx)) - kbdev->protected_mode_hwcnt_disabled = true; - } - - /* We couldn't disable atomically, so kick off a worker */ - if (!kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_queue_work(kbdev->hwcnt_gpu_ctx, - &kbdev->protected_mode_hwcnt_disable_work); - return -EAGAIN; - } - - /* Once reaching this point GPU must be switched to protected - * mode or hwcnt re-enabled. - */ - - if (kbase_pm_protected_entry_override_enable(kbdev)) - return -EAGAIN; - - /* - * Not in correct mode, begin protected mode switch. - * Entering protected mode requires us to power down the L2, - * and drop out of fully coherent mode. - */ - katom[idx]->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_IDLE_L2; - - kbase_pm_protected_override_enable(kbdev); - /* - * Only if the GPU reset hasn't been initiated, there is a need - * to invoke the state machine to explicitly power down the - * shader cores and L2. - */ - if (!kbdev->pm.backend.protected_entry_transition_override) - kbase_pm_update_cores_state_nolock(kbdev); - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_ENTER_PROTECTED_IDLE_L2: - /* Avoid unnecessary waiting on non-ACE platforms. */ - if (kbdev->system_coherency == COHERENCY_ACE) { - if (kbdev->pm.backend.l2_always_on) { - /* - * If the GPU reset hasn't completed, then L2 - * could still be powered up. - */ - if (kbase_reset_gpu_is_active(kbdev)) - return -EAGAIN; - } - - if (kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2) || - kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_L2) || - !kbase_io_has_gpu(kbdev)) { - /* - * The L2 is still powered, wait for all - * the users to finish with it before doing - * the actual reset. - */ - return -EAGAIN; - } - } - - katom[idx]->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY: - /* - * When entering into protected mode, we must ensure that the - * GPU is not operating in coherent mode as well. This is to - * ensure that no protected memory can be leaked. - */ - kbase_gpu_disable_coherent(kbdev); - - kbase_pm_protected_entry_override_disable(kbdev); - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) { - /* - * Power on L2 caches; this will also result in the - * correct value written to coherency enable register. - */ - kbase_pm_protected_l2_override(kbdev, true); - - /* - * Set the flag on the atom that additional - * L2 references are taken. - */ - katom[idx]->atom_flags |= KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT; - } - - katom[idx]->protected_state.enter = KBASE_ATOM_ENTER_PROTECTED_FINISHED; - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) - return -EAGAIN; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_ENTER_PROTECTED_FINISHED: - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TGOX_R1_1234)) { - /* - * Check that L2 caches are powered and, if so, - * enter protected mode. - */ - if (kbdev->pm.backend.l2_state == KBASE_L2_ON) { - /* - * Remove additional L2 reference and reset - * the atom flag which denotes it. - */ - if (katom[idx]->atom_flags & KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT) { - kbase_pm_protected_l2_override(kbdev, false); - katom[idx]->atom_flags &= - ~KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT; - } - - err = kbase_jm_protected_entry(kbdev, katom, idx, js); - - if (err) - return err; - } else { - /* - * still waiting for L2 caches to power up - */ - return -EAGAIN; - } - } else { - err = kbase_jm_protected_entry(kbdev, katom, idx, js); - - if (err) - return err; - } - } - - return 0; -} - -static int kbase_jm_exit_protected_mode(struct kbase_device *kbdev, struct kbase_jd_atom **katom, - int idx, unsigned int js) -{ - int err = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - switch (katom[idx]->protected_state.exit) { - case KBASE_ATOM_EXIT_PROTECTED_CHECK: - KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_START(kbdev, kbdev); - /* The checks in KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV - * should ensure that we are not already transitiong, and that - * there are no atoms currently on the GPU. - */ - WARN_ON(kbdev->protected_mode_transition); - WARN_ON(kbase_gpu_atoms_submitted_any(kbdev)); - - /* - * Exiting protected mode requires a reset, but first the L2 - * needs to be powered down to ensure it's not active when the - * reset is issued. - */ - katom[idx]->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_IDLE_L2; - - kbdev->protected_mode_transition = true; - kbase_pm_protected_override_enable(kbdev); - kbase_pm_update_cores_state_nolock(kbdev); - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_EXIT_PROTECTED_IDLE_L2: - if (kbdev->pm.backend.l2_state != KBASE_L2_OFF) { - /* - * The L2 is still powered, wait for all the users to - * finish with it before doing the actual reset. - */ - return -EAGAIN; - } - katom[idx]->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_RESET; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_EXIT_PROTECTED_RESET: - /* L2 cache has been turned off (which is needed prior to the reset of GPU - * to exit the protected mode), so the override flag can be safely cleared. - * Even if L2 cache is powered up again before the actual reset, it should - * not be an issue (there are no jobs running on the GPU). - */ - kbase_pm_protected_override_disable(kbdev); - - /* Issue the reset to the GPU */ - err = kbase_gpu_protected_mode_reset(kbdev); - - if (err == -EAGAIN) - return -EAGAIN; - - if (err) { - kbdev->protected_mode_transition = false; - - /* Failed to exit protected mode, fail atom */ - katom[idx]->event_code = BASE_JD_EVENT_JOB_INVALID; - kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); - /* Only return if head atom or previous atom - * already removed - as atoms must be returned in order - */ - if (idx == 0 || - katom[0]->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { - kbase_gpu_dequeue_atom(kbdev, js, NULL); - kbase_jm_return_atom_to_js(kbdev, katom[idx]); - } - - /* If we're exiting from protected mode, hwcnt must have - * been disabled during entry. - */ - WARN_ON(!kbdev->protected_mode_hwcnt_disabled); - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - } - - return -EINVAL; - } - - katom[idx]->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT: - /* A GPU reset is issued when exiting protected mode. Once the - * reset is done all atoms' state will also be reset. For this - * reason, if the atom is still in this state we can safely - * say that the reset has not completed i.e., we have not - * finished exiting protected mode yet. - */ - return -EAGAIN; - } - - return 0; -} - -void kbase_backend_slot_update(struct kbase_device *kbdev) -{ - unsigned int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (kbase_reset_gpu_is_active(kbdev) || !kbase_io_has_gpu(kbdev)) - return; - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - struct kbase_jd_atom *katom[2]; - int idx; - - katom[0] = kbase_gpu_inspect(kbdev, js, 0); - katom[1] = kbase_gpu_inspect(kbdev, js, 1); - WARN_ON(katom[1] && !katom[0]); - - for (idx = 0; idx < SLOT_RB_SIZE; idx++) { - bool cores_ready; -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - bool trace_atom_submit_for_gpu_metrics = true; -#endif - int ret; - - if (!katom[idx]) - continue; - - switch (katom[idx]->gpu_rb_state) { - case KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB: - /* Should be impossible */ - WARN(1, "Attempting to update atom not in ringbuffer\n"); - break; - - case KBASE_ATOM_GPU_RB_WAITING_BLOCKED: - if (katom[idx]->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) - break; - - katom[idx]->gpu_rb_state = - KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV: - if (kbase_gpu_check_secure_atoms( - kbdev, !kbase_jd_katom_is_protected(katom[idx]))) - break; - - if ((idx == 1) && (kbase_jd_katom_is_protected(katom[0]) != - kbase_jd_katom_is_protected(katom[1]))) - break; - - if (kbdev->protected_mode_transition) - break; - - katom[idx]->gpu_rb_state = - KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION: - - /* - * Exiting protected mode must be done before - * the references on the cores are taken as - * a power down the L2 is required which - * can't happen after the references for this - * atom are taken. - */ - - if (!kbase_gpu_in_protected_mode(kbdev) && - kbase_jd_katom_is_protected(katom[idx])) { - /* Atom needs to transition into protected mode. */ - ret = kbase_jm_enter_protected_mode(kbdev, katom, idx, js); - if (ret) - break; - } else if (kbase_gpu_in_protected_mode(kbdev) && - !kbase_jd_katom_is_protected(katom[idx])) { - /* Atom needs to transition out of protected mode. */ - ret = kbase_jm_exit_protected_mode(kbdev, katom, idx, js); - if (ret) - break; - } - katom[idx]->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; - - /* Atom needs no protected mode transition. */ - - katom[idx]->gpu_rb_state = - KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE: - if (katom[idx]->will_fail_event_code) { - kbase_gpu_mark_atom_for_return(kbdev, katom[idx]); - /* Set EVENT_DONE so this atom will be - * completed, not unpulled. - */ - katom[idx]->event_code = BASE_JD_EVENT_DONE; - /* Only return if head atom or previous - * atom already removed - as atoms must - * be returned in order. - */ - if (idx == 0 || katom[0]->gpu_rb_state == - KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { - kbase_gpu_dequeue_atom(kbdev, js, NULL); - kbase_jm_return_atom_to_js(kbdev, katom[idx]); - } - break; - } - - cores_ready = kbase_pm_cores_requested(kbdev, true); - - if (!cores_ready) - break; - - katom[idx]->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_READY: - - if (idx == 1) { - enum kbase_atom_gpu_rb_state atom_0_gpu_rb_state = - katom[0]->gpu_rb_state; - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - trace_atom_submit_for_gpu_metrics = - (atom_0_gpu_rb_state == - KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB); -#endif - - /* Only submit if head atom or previous - * atom already submitted - */ - if ((atom_0_gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED && - atom_0_gpu_rb_state != - KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB)) - break; - - /* If intra-slot serialization in use - * then don't submit atom to NEXT slot - */ - if (kbdev->serialize_jobs & KBASE_SERIALIZE_INTRA_SLOT) - break; - } - - /* If inter-slot serialization in use then don't - * submit atom if any other slots are in use - */ - if ((kbdev->serialize_jobs & KBASE_SERIALIZE_INTER_SLOT) && - other_slots_busy(kbdev, js)) - break; - - /* Check if this job needs the cycle counter - * enabled before submission - */ - if (katom[idx]->core_req & BASE_JD_REQ_PERMON) - kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev); - - if (!kbase_job_hw_submit(kbdev, katom[idx], js)) { - katom[idx]->gpu_rb_state = KBASE_ATOM_GPU_RB_SUBMITTED; - - /* Inform power management at start/finish of - * atom so it can update its GPU utilisation - * metrics. - */ - kbase_pm_metrics_update(kbdev, - &katom[idx]->start_timestamp); - - /* Inform platform at start/finish of atom */ - kbasep_platform_event_atom_submit(katom[idx]); -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - if (likely(trace_atom_submit_for_gpu_metrics && - !kbase_jd_katom_is_protected(katom[idx]))) - kbase_gpu_metrics_ctx_start_activity( - katom[idx]->kctx, - ktime_to_ns(katom[idx]->start_timestamp)); -#endif - } else { - if (katom[idx]->core_req & BASE_JD_REQ_PERMON) - kbase_pm_release_gpu_cycle_counter_nolock(kbdev); - - break; - } - - /* ***TRANSITION TO HIGHER STATE*** */ - fallthrough; - case KBASE_ATOM_GPU_RB_SUBMITTED: - break; - - case KBASE_ATOM_GPU_RB_RETURN_TO_JS: - /* Only return if head atom or previous atom - * already removed - as atoms must be returned - * in order - */ - if (idx == 0 || - katom[0]->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { - kbase_gpu_dequeue_atom(kbdev, js, NULL); - kbase_jm_return_atom_to_js(kbdev, katom[idx]); - } - break; - } - } - } -} - -void kbase_backend_run_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - dev_dbg(kbdev->dev, "Backend running atom %pK\n", (void *)katom); - - kbase_gpu_enqueue_atom(kbdev, katom); - kbase_backend_slot_update(kbdev); -} - -/** - * kbase_rb_atom_might_depend - determine if one atom in the slot ringbuffer - * might depend on another from the same kctx - * @katom_a: dependee atom - * @katom_b: atom to query - * - * This can be used on atoms that belong to different slot ringbuffers - * - * Return: true if @katom_b might depend on @katom_a, false if it cannot depend. - */ -static inline bool kbase_rb_atom_might_depend(const struct kbase_jd_atom *katom_a, - const struct kbase_jd_atom *katom_b) -{ - if (katom_a->kctx != katom_b->kctx) - return false; - return (katom_b->pre_dep || (katom_b->atom_flags & (KBASE_KATOM_FLAG_X_DEP_BLOCKED | - KBASE_KATOM_FLAG_FAIL_BLOCKER))); -} - -static inline void kbase_gpu_remove_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - u32 action, bool disjoint) -{ - struct kbase_context *kctx = katom->kctx; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; - kbase_gpu_mark_atom_for_return(kbdev, katom); - kbase_jsctx_slot_prio_blocked_set(kctx, katom->slot_nr, katom->sched_priority); - - if (disjoint) - kbase_job_check_enter_disjoint(kbdev, action, katom->core_req, katom); -} - -/** - * kbase_gpu_irq_evict - evict a slot's JS_HEAD_NEXT atom from the HW if it is - * related to a failed JS_HEAD atom - * @kbdev: kbase device - * @js: job slot to check - * @completion_code: completion code of the failed atom - * - * Note: 'STOPPED' atoms are considered 'failed', as they are in the HW, but - * unlike other failure codes we _can_ re-run them. - * - * This forms step 1 in a 2-step process of removing any related atoms from a - * slot's JS_HEAD_NEXT (ringbuffer index 1), should there have - * been a 'failure' on an atom in JS_HEAD (ringbuffer index 0). - * - * This step only removes the atoms from the HW, and marks them as - * (potentially) ready to run again. - * - * Step 2 is on marking the JS_HEAD atom as complete - * (kbase_gpu_complete_hw()), to dequeue said atoms and return them to the JS - * as appropriate, or re-submit them. - * - * Hence, this function must evict at a minimum the atoms related to the atom - * in JS_HEAD that kbase_gpu_complete_hw() will also dequeue. It is acceptable - * if this function evicts more atoms than kbase_gpu_complete_hw() dequeues, as - * the next kbase_backend_slot_update() will resubmit any remaining. - * - * Return: true if an atom was evicted, false otherwise. - */ -bool kbase_gpu_irq_evict(struct kbase_device *kbdev, unsigned int js, u32 completion_code) -{ - struct kbase_jd_atom *katom; - struct kbase_jd_atom *next_katom; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - katom = kbase_gpu_inspect(kbdev, js, 0); - if (!katom) { - dev_err(kbdev->dev, "Can't get a katom from js(%u)\n", js); - return false; - } - next_katom = kbase_gpu_inspect(kbdev, js, 1); - - if (next_katom && next_katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED && - (kbase_rb_atom_might_depend(katom, next_katom) || - kbase_js_atom_runs_before(kbdev, katom, next_katom, 0u)) && - kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(js, HEAD_NEXT)) != 0) { - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT), JS_COMMAND_NOP); - - if (completion_code == BASE_JD_EVENT_STOPPED) { - kbase_gpu_remove_atom(kbdev, next_katom, JS_COMMAND_SOFT_STOP, false); - KBASE_TLSTREAM_TL_NRET_ATOM_LPU( - kbdev, next_katom, - &kbdev->gpu_props.js_features[next_katom->slot_nr]); - KBASE_TLSTREAM_TL_NRET_ATOM_AS(kbdev, next_katom, - &kbdev->as[next_katom->kctx->as_nr]); - KBASE_TLSTREAM_TL_NRET_CTX_LPU( - kbdev, next_katom->kctx, - &kbdev->gpu_props.js_features[next_katom->slot_nr]); - } else { - next_katom->gpu_rb_state = KBASE_ATOM_GPU_RB_READY; - - if (next_katom->core_req & BASE_JD_REQ_PERMON) - kbase_pm_release_gpu_cycle_counter_nolock(kbdev); - } - - /* On evicting the next_katom, the last submission kctx on the - * given job slot then reverts back to the one that owns katom. - * The aim is to enable the next submission that can determine - * if the read only shader core L1 cache should be invalidated. - */ - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = - SLOT_RB_TAG_KCTX(katom->kctx); - - return true; - } - - return false; -} - -/** - * kbase_gpu_complete_hw - complete the atom in a slot's JS_HEAD - * @kbdev: kbase device - * @js: job slot to check - * @completion_code: completion code of the completed atom - * @job_tail: value read from JS_TAIL, for STOPPED atoms - * @end_timestamp: pointer to approximate ktime value when the katom completed - * - * Among other operations, this also executes step 2 of a 2-step process of - * removing any related atoms from a slot's JS_HEAD_NEXT (ringbuffer index 1), - * should there have been a 'failure' on an atom in JS_HEAD (ringbuffer index - * 0). The first step is done in kbase_gpu_irq_evict(). - * - * Note: 'STOPPED' atoms are considered 'failed', as they are in the HW, but - * unlike other failure codes we _can_ re-run them. - * - * When the JS_HEAD atom is considered to be 'failed', then this will dequeue - * and return to the JS some (usually all) of the atoms evicted from the HW - * during the kbase_gpu_irq_evict() for that JS_HEAD atom. If it dequeues an - * atom, that atom must not have been running or must already be evicted, as - * otherwise we would be in the incorrect state of having an atom both running - * on the HW and returned to the JS. - */ - -void kbase_gpu_complete_hw(struct kbase_device *kbdev, unsigned int js, u32 completion_code, - u64 job_tail, ktime_t *end_timestamp) -{ - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, 0); - struct kbase_context *kctx = NULL; - - if (unlikely(!katom)) { - dev_err(kbdev->dev, "Can't get a katom from js(%d)\n", js); - return; - } - - kctx = katom->kctx; - - dev_dbg(kbdev->dev, "Atom %pK completed on hw with code 0x%x and job_tail 0x%llx (s:%d)\n", - (void *)katom, completion_code, job_tail, js); - - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* - * When a hard-stop is followed close after a soft-stop, the completion - * code may be set to STOPPED, even though the job is terminated - */ - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TMIX_8438)) { - if (completion_code == BASE_JD_EVENT_STOPPED && - (katom->atom_flags & KBASE_KATOM_FLAG_BEEN_HARD_STOPPED)) { - completion_code = BASE_JD_EVENT_TERMINATED; - } - } - - if ((katom->core_req & BASE_JD_REQ_SKIP_CACHE_END) && - completion_code != BASE_JD_EVENT_DONE && !(completion_code & BASE_JD_SW_EVENT)) { - /* When a job chain fails, on a T60x or when - * BASE_JD_REQ_SKIP_CACHE_END is set, the GPU cache is not - * flushed. To prevent future evictions causing possible memory - * corruption we need to flush the cache manually before any - * affected memory gets reused. - */ - katom->need_cache_flush_cores_retained = true; - } - - katom = kbase_gpu_dequeue_atom(kbdev, js, end_timestamp); - - if (completion_code == BASE_JD_EVENT_STOPPED) { - struct kbase_jd_atom *next_katom = kbase_gpu_inspect(kbdev, js, 0); - - /* - * Dequeue next atom from ringbuffers on same slot if required. - * This atom will already have been removed from the NEXT - * registers by kbase_gpu_soft_hard_stop_slot(), to ensure that - * the atoms on this slot are returned in the correct order. - */ - if (next_katom && kbase_js_atom_runs_before(kbdev, katom, next_katom, 0u)) { - WARN_ON(next_katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED); - kbase_gpu_dequeue_atom(kbdev, js, end_timestamp); - kbase_jm_return_atom_to_js(kbdev, next_katom); - } - } else if (completion_code != BASE_JD_EVENT_DONE) { - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - unsigned int i; - - if (!kbase_ctx_flag(katom->kctx, KCTX_DYING) && - !kbase_ctx_flag(katom->kctx, KCTX_PAGE_FAULT_REPORT_SKIP)) { - dev_warn(kbdev->dev, "error detected from slot %d, job status 0x%08x (%s)", - js, completion_code, kbase_gpu_exception_name(completion_code)); - - } - -#if KBASE_KTRACE_DUMP_ON_JOB_SLOT_ERROR != 0 - KBASE_KTRACE_DUMP(kbdev); -#endif - kbasep_js_clear_submit_allowed(js_devdata, katom->kctx); - - /* - * Remove all atoms on the same context from ringbuffers. This - * will not remove atoms that are already on the GPU, as these - * are guaranteed not to have fail dependencies on the failed - * atom. - */ - for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) { - struct kbase_jd_atom *katom_idx0 = kbase_gpu_inspect(kbdev, i, 0); - struct kbase_jd_atom *katom_idx1 = kbase_gpu_inspect(kbdev, i, 1); - - if (katom_idx0 && kbase_rb_atom_might_depend(katom, katom_idx0) && - katom_idx0->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { - /* Dequeue katom_idx0 from ringbuffer */ - kbase_gpu_dequeue_atom(kbdev, i, end_timestamp); - - if (katom_idx1 && kbase_rb_atom_might_depend(katom, katom_idx1) && - katom_idx0->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { - /* Dequeue katom_idx1 from ringbuffer */ - kbase_gpu_dequeue_atom(kbdev, i, end_timestamp); - - katom_idx1->event_code = BASE_JD_EVENT_STOPPED; - kbase_jm_return_atom_to_js(kbdev, katom_idx1); - } - katom_idx0->event_code = BASE_JD_EVENT_STOPPED; - kbase_jm_return_atom_to_js(kbdev, katom_idx0); - - } else if (katom_idx1 && kbase_rb_atom_might_depend(katom, katom_idx1) && - katom_idx1->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { - /* Can not dequeue this atom yet - will be - * dequeued when atom at idx0 completes - */ - katom_idx1->event_code = BASE_JD_EVENT_STOPPED; - kbase_gpu_mark_atom_for_return(kbdev, katom_idx1); - } - } - } - - KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, JM_JOB_DONE, kctx, katom, katom->jc, js, - completion_code); - - if (job_tail != 0 && job_tail != katom->jc) { - /* Some of the job has been executed */ - dev_dbg(kbdev->dev, "Update job chain address of atom %pK to resume from 0x%llx\n", - (void *)katom, job_tail); - - /* Some of the job has been executed, so we update the job chain address to where - * we should resume from - */ - katom->jc = job_tail; - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JM_UPDATE_HEAD, katom->kctx, katom, job_tail, js); - } - - /* Only update the event code for jobs that weren't cancelled */ - if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED) - katom->event_code = (enum base_jd_event_code)completion_code; - - /* Complete the job, and start new ones - * - * Also defer remaining work onto the workqueue: - * - Re-queue Soft-stopped jobs - * - For any other jobs, queue the job back into the dependency system - * - Schedule out the parent context if necessary, and schedule a new - * one in. - */ - if (kbdev->serialize_jobs & KBASE_SERIALIZE_RESET) - kbase_reset_gpu_silent(kbdev); - - if (completion_code == BASE_JD_EVENT_STOPPED) - katom = kbase_jm_return_atom_to_js(kbdev, katom); - else - katom = kbase_jm_complete(kbdev, katom, end_timestamp); - - if (katom) { - dev_dbg(kbdev->dev, "Cross-slot dependency %pK has become runnable.\n", - (void *)katom); - - /* Cross-slot dependency has now become runnable. Try to submit it. */ - - /* Check if there are lower priority jobs to soft stop */ - kbase_job_slot_ctx_priority_check_locked(kctx, katom); - - kbase_jm_try_kick(kbdev, 1UL << katom->slot_nr); - } - - /* For partial shader core off L2 cache flush */ - kbase_pm_update_state(kbdev); - - /* Job completion may have unblocked other atoms. Try to update all job - * slots - */ - kbase_backend_slot_update(kbdev); -} - -void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp) -{ - unsigned int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* Reset should always take the GPU out of protected mode */ - WARN_ON(kbase_gpu_in_protected_mode(kbdev)); - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - int atom_idx = 0; - int idx; - - for (idx = 0; idx < SLOT_RB_SIZE; idx++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, atom_idx); - bool keep_in_jm_rb = false; - - if (!katom) - break; - if (katom->protected_state.exit == KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT) { - /* protected mode sanity checks */ - WARN(kbase_jd_katom_is_protected(katom) != - kbase_gpu_in_protected_mode(kbdev), - "Protected mode of atom (%d) doesn't match protected mode of GPU (%d)", - kbase_jd_katom_is_protected(katom), - kbase_gpu_in_protected_mode(kbdev)); - WARN(!(kbase_jd_katom_is_protected(katom) && js == 0) && - kbase_jd_katom_is_protected(katom), - "Protected atom on JS%u not supported", js); - } - if ((katom->gpu_rb_state < KBASE_ATOM_GPU_RB_SUBMITTED) && - !kbase_ctx_flag(katom->kctx, KCTX_DYING)) - keep_in_jm_rb = true; - - kbase_gpu_release_atom(kbdev, katom, NULL); - - /* - * If the atom wasn't on HW when the reset was issued - * then leave it in the RB and next time we're kicked - * it will be processed again from the starting state. - */ - if (kbase_io_has_gpu(kbdev) && keep_in_jm_rb) { - katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; - /* As the atom was not removed, increment the - * index so that we read the correct atom in the - * next iteration. - */ - atom_idx++; - continue; - } - - /* - * The atom was on the HW when the reset was issued - * all we can do is fail the atom. - */ - kbase_gpu_dequeue_atom(kbdev, js, NULL); - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - kbase_jm_complete(kbdev, katom, end_timestamp); - } - - /* Clear the slot's last katom submission kctx on reset */ - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = SLOT_RB_NULL_TAG_VAL; - } - - /* Re-enable GPU hardware counters if we're resetting from protected - * mode. - */ - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - - KBASE_TLSTREAM_AUX_PROTECTED_LEAVE_END(kbdev, kbdev); - } - - kbdev->protected_mode_transition = false; - kbase_pm_protected_override_disable(kbdev); -} - -/** - * should_stop_next_atom - given a soft/hard stop action, determine if the next - * atom on a slot should be stopped - * @kbdev: kbase devices - * @head_katom: atom currently in the JS_HEAD - * @next_katom: atom currently in the JS_HEAD_NEXT - * @action: COMMAND_<...> action for soft/hard-stop - * - * This is used in cases where @head_katom is the target of the soft/hard-stop. - * It only makes sense to call this when @head_katom and @next_katom are from - * the same slot. - * - * Return: true if @next_katom should also be stopped with the given action, - * false otherwise - */ -static bool should_stop_next_atom(struct kbase_device *kbdev, - const struct kbase_jd_atom *head_katom, - const struct kbase_jd_atom *next_katom, u32 action) -{ - bool ret = false; - u32 hw_action = action & JS_COMMAND_MASK; - - switch (hw_action) { - case JS_COMMAND_SOFT_STOP: - ret = kbase_js_atom_runs_before(kbdev, head_katom, next_katom, 0u); - break; - case JS_COMMAND_HARD_STOP: - /* Unlike soft-stop, a hard-stop targeting a particular atom - * should not cause atoms from unrelated contexts to be - * removed - */ - ret = (head_katom->kctx == next_katom->kctx); - break; - default: - /* Other stop actions are possible, but the driver should not - * be generating them at this point in the call chain - */ - WARN(1, "Unexpected stop action: 0x%.8x", hw_action); - break; - } - return ret; -} - -static inline void kbase_gpu_stop_atom(struct kbase_device *kbdev, unsigned int js, - struct kbase_jd_atom *katom, u32 action) -{ - struct kbase_context *kctx = katom->kctx; - u32 hw_action = action & JS_COMMAND_MASK; - - kbase_job_check_enter_disjoint(kbdev, action, katom->core_req, katom); - kbasep_job_slot_soft_or_hard_stop_do_action(kbdev, js, hw_action, katom->core_req, katom); - kbase_jsctx_slot_prio_blocked_set(kctx, js, katom->sched_priority); -} - -static int should_stop_x_dep_slot(struct kbase_jd_atom *katom) -{ - if (katom->x_post_dep) { - struct kbase_jd_atom *dep_atom = katom->x_post_dep; - - if (dep_atom->gpu_rb_state != KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB && - dep_atom->gpu_rb_state != KBASE_ATOM_GPU_RB_RETURN_TO_JS) - return (int)dep_atom->slot_nr; - } - return -1; -} - -bool kbase_backend_soft_hard_stop_slot(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js, struct kbase_jd_atom *katom, u32 action) -{ - struct kbase_jd_atom *katom_idx0; - struct kbase_context *kctx_idx0 = NULL; - struct kbase_jd_atom *katom_idx1; - struct kbase_context *kctx_idx1 = NULL; - - bool katom_idx0_valid, katom_idx1_valid; - - bool ret = false; - - int stop_x_dep_idx0 = -1, stop_x_dep_idx1 = -1; - int prio_idx0 = 0, prio_idx1 = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - katom_idx0 = kbase_gpu_inspect(kbdev, js, 0); - katom_idx1 = kbase_gpu_inspect(kbdev, js, 1); - - if (katom_idx0) { - kctx_idx0 = katom_idx0->kctx; - prio_idx0 = katom_idx0->sched_priority; - } - if (katom_idx1) { - kctx_idx1 = katom_idx1->kctx; - prio_idx1 = katom_idx1->sched_priority; - } - - if (katom) { - katom_idx0_valid = (katom_idx0 == katom); - if (katom_idx1) - katom_idx1_valid = (katom_idx1 == katom); - else - katom_idx1_valid = false; - } else { - katom_idx0_valid = (katom_idx0 && (!kctx || kctx_idx0 == kctx)); - katom_idx1_valid = (katom_idx1 && (!kctx || kctx_idx1 == kctx)); - } - /* If there's an atom in JS_HEAD_NEXT that we haven't already decided - * to stop, but we're stopping the JS_HEAD atom, see if they are - * related/ordered in some way that would require the same stop action - */ - if (!katom_idx1_valid && katom_idx0_valid && katom_idx1) - katom_idx1_valid = should_stop_next_atom(kbdev, katom_idx0, katom_idx1, action); - - if (katom_idx0_valid) - stop_x_dep_idx0 = should_stop_x_dep_slot(katom_idx0); - if (katom_idx1_valid) - stop_x_dep_idx1 = should_stop_x_dep_slot(katom_idx1); - - if (katom_idx0_valid) { - if (katom_idx0->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { - /* Simple case - just dequeue and return */ - kbase_gpu_dequeue_atom(kbdev, js, NULL); - if (katom_idx1_valid) { - kbase_gpu_dequeue_atom(kbdev, js, NULL); - katom_idx1->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; - kbase_jm_return_atom_to_js(kbdev, katom_idx1); - kbase_jsctx_slot_prio_blocked_set(kctx_idx1, js, prio_idx1); - } - - katom_idx0->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; - kbase_jm_return_atom_to_js(kbdev, katom_idx0); - kbase_jsctx_slot_prio_blocked_set(kctx_idx0, js, prio_idx0); - } else { - /* katom_idx0 is on GPU */ - if (katom_idx1_valid && - katom_idx1->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) { - /* katom_idx0 and katom_idx1 are on GPU */ - - if (kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT)) == - 0) { - /* idx0 has already completed - stop - * idx1 if needed - */ - if (katom_idx1_valid) { - kbase_gpu_stop_atom(kbdev, js, katom_idx1, action); - ret = true; - } - } else { - /* idx1 is in NEXT registers - attempt - * to remove - */ - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT), - JS_COMMAND_NOP); - - if (kbase_reg_read64(kbdev, - JOB_SLOT_OFFSET(js, HEAD_NEXT)) != 0) { - /* idx1 removed successfully, - * will be handled in IRQ - */ - kbase_gpu_remove_atom(kbdev, katom_idx1, action, - true); - /* Revert the last_context. */ - kbdev->hwaccess.backend.slot_rb[js] - .last_kctx_tagged = - SLOT_RB_TAG_KCTX(katom_idx0->kctx); - - stop_x_dep_idx1 = - should_stop_x_dep_slot(katom_idx1); - - /* stop idx0 if still on GPU */ - kbase_gpu_stop_atom(kbdev, js, katom_idx0, action); - ret = true; - } else if (katom_idx1_valid) { - /* idx0 has already completed, - * stop idx1 if needed - */ - kbase_gpu_stop_atom(kbdev, js, katom_idx1, action); - ret = true; - } - } - } else if (katom_idx1_valid) { - /* idx1 not on GPU but must be dequeued*/ - - /* idx1 will be handled in IRQ */ - kbase_gpu_remove_atom(kbdev, katom_idx1, action, false); - /* stop idx0 */ - /* This will be repeated for anything removed - * from the next registers, since their normal - * flow was also interrupted, and this function - * might not enter disjoint state e.g. if we - * don't actually do a hard stop on the head - * atom - */ - kbase_gpu_stop_atom(kbdev, js, katom_idx0, action); - ret = true; - } else { - /* no atom in idx1 */ - /* just stop idx0 */ - kbase_gpu_stop_atom(kbdev, js, katom_idx0, action); - ret = true; - } - } - } else if (katom_idx1_valid) { - if (katom_idx1->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) { - /* Mark for return */ - /* idx1 will be returned once idx0 completes */ - kbase_gpu_remove_atom(kbdev, katom_idx1, action, false); - } else { - /* idx1 is on GPU */ - if (kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT)) == 0) { - /* idx0 has already completed - stop idx1 */ - kbase_gpu_stop_atom(kbdev, js, katom_idx1, action); - ret = true; - } else { - /* idx1 is in NEXT registers - attempt to - * remove - */ - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(js, COMMAND_NEXT), - JS_COMMAND_NOP); - - if (kbase_reg_read64(kbdev, JOB_SLOT_OFFSET(js, HEAD_NEXT)) != 0) { - /* idx1 removed successfully, will be - * handled in IRQ once idx0 completes - */ - kbase_gpu_remove_atom(kbdev, katom_idx1, action, false); - /* Revert the last_context, or mark as purged */ - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = - kctx_idx0 ? SLOT_RB_TAG_KCTX(katom_idx0->kctx) : - SLOT_RB_TAG_PURGED; - } else { - /* idx0 has already completed - stop - * idx1 - */ - kbase_gpu_stop_atom(kbdev, js, katom_idx1, action); - ret = true; - } - } - } - } - - if (stop_x_dep_idx0 != -1) - kbase_backend_soft_hard_stop_slot(kbdev, kctx, (unsigned int)stop_x_dep_idx0, NULL, - action); - - if (stop_x_dep_idx1 != -1) - kbase_backend_soft_hard_stop_slot(kbdev, kctx, (unsigned int)stop_x_dep_idx1, NULL, - action); - - return ret; -} - -void kbase_backend_cache_clean(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - if (katom->need_cache_flush_cores_retained) { - kbase_gpu_start_cache_clean(kbdev, GPU_COMMAND_CACHE_CLN_INV_FULL); - kbase_gpu_wait_cache_clean(kbdev); - - katom->need_cache_flush_cores_retained = false; - } -} - -void kbase_backend_complete_wq(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - /* - * If cache flush required due to HW workaround then perform the flush - * now - */ - kbase_backend_cache_clean(kbdev, katom); -} - -void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev, base_jd_core_req core_req) -{ - CSTD_UNUSED(core_req); - - if (!kbdev->pm.active_count) { - kbase_pm_lock(kbdev); - kbase_pm_update_active(kbdev); - kbase_pm_unlock(kbdev); - } -} - -void kbase_gpu_dump_slots(struct kbase_device *kbdev) -{ - unsigned long flags; - unsigned int js; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - dev_info(kbdev->dev, "%s:\n", __func__); - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - int idx; - - for (idx = 0; idx < SLOT_RB_SIZE; idx++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, idx); - - if (katom) - dev_info(kbdev->dev, " js%u idx%d : katom=%pK gpu_rb_state=%d\n", - js, idx, katom, katom->gpu_rb_state); - else - dev_info(kbdev->dev, " js%u idx%d : empty\n", js, idx); - } - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -} - -void kbase_backend_slot_kctx_purge_locked(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - unsigned int js; - bool tracked = false; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - u64 tagged_kctx = kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged; - - if (tagged_kctx == SLOT_RB_TAG_KCTX(kctx)) { - /* Marking the slot kctx tracking field is purged */ - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = SLOT_RB_TAG_PURGED; - tracked = true; - } - } - - if (tracked) { - /* The context had run some jobs before the purge, other slots - * in SLOT_RB_NULL_TAG_VAL condition needs to be marked as - * purged as well. - */ - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - if (kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged == - SLOT_RB_NULL_TAG_VAL) - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = - SLOT_RB_TAG_PURGED; - } - } -} diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.h deleted file mode 100644 index 32be0bf44655..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_jm_rb.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2014-2018, 2020-2022 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Register-based HW access backend specific APIs - */ - -#ifndef _KBASE_HWACCESS_GPU_H_ -#define _KBASE_HWACCESS_GPU_H_ - -#include - -/** - * kbase_gpu_irq_evict - Evict an atom from a NEXT slot - * - * @kbdev: Device pointer - * @js: Job slot to evict from - * @completion_code: Event code from job that was run. - * - * Evict the atom in the NEXT slot for the specified job slot. This function is - * called from the job complete IRQ handler when the previous job has failed. - * - * Return: true if job evicted from NEXT registers, false otherwise - */ -bool kbase_gpu_irq_evict(struct kbase_device *kbdev, unsigned int js, u32 completion_code); - -/** - * kbase_gpu_complete_hw - Complete an atom on job slot js - * - * @kbdev: Device pointer - * @js: Job slot that has completed - * @completion_code: Event code from job that has completed - * @job_tail: The tail address from the hardware if the job has partially - * completed - * @end_timestamp: Time of completion - */ -void kbase_gpu_complete_hw(struct kbase_device *kbdev, unsigned int js, u32 completion_code, - u64 job_tail, ktime_t *end_timestamp); - -/** - * kbase_gpu_inspect - Inspect the contents of the HW access ringbuffer - * - * @kbdev: Device pointer - * @js: Job slot to inspect - * @idx: Index into ringbuffer. 0 is the job currently running on - * the slot, 1 is the job waiting, all other values are invalid. - * Return: The atom at that position in the ringbuffer - * or NULL if no atom present - */ -struct kbase_jd_atom *kbase_gpu_inspect(struct kbase_device *kbdev, unsigned int js, int idx); - -/** - * kbase_gpu_dump_slots - Print the contents of the slot ringbuffers - * - * @kbdev: Device pointer - */ -void kbase_gpu_dump_slots(struct kbase_device *kbdev); - -#endif /* _KBASE_HWACCESS_GPU_H_ */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_backend.c deleted file mode 100644 index dd0d915be48c..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_backend.c +++ /dev/null @@ -1,371 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Register-based HW access backend specific job scheduler APIs - */ - -#include -#include -#include -#include -#include -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) -#include -#endif - -/* - * Hold the runpool_mutex for this - */ -static inline bool timer_callback_should_run(struct kbase_device *kbdev, int nr_running_ctxs) -{ - lockdep_assert_held(&kbdev->js_data.runpool_mutex); - -#ifdef CONFIG_MALI_VALHALL_DEBUG - if (kbdev->js_data.softstop_always) { - /* Debug support for allowing soft-stop on a single context */ - return true; - } -#endif /* CONFIG_MALI_VALHALL_DEBUG */ - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_9435)) { - /* Timeouts would have to be 4x longer (due to micro- - * architectural design) to support OpenCL conformance tests, so - * only run the timer when there's: - * - 2 or more CL contexts - * - 1 or more GLES contexts - * - * NOTE: We will treat a context that has both Compute and Non- - * Compute jobs will be treated as an OpenCL context (hence, we - * don't check KBASEP_JS_CTX_ATTR_NON_COMPUTE). - */ - { - int nr_compute_ctxs = kbasep_js_ctx_attr_count_on_runpool( - kbdev, KBASEP_JS_CTX_ATTR_COMPUTE); - int nr_noncompute_ctxs = nr_running_ctxs - nr_compute_ctxs; - - return (bool)(nr_compute_ctxs >= 2 || nr_noncompute_ctxs > 0); - } - } else { - /* Run the timer callback whenever you have at least 1 context - */ - return (bool)(nr_running_ctxs > 0); - } -} - -static enum hrtimer_restart timer_callback(struct hrtimer *timer) -{ - unsigned long flags; - struct kbase_device *kbdev; - struct kbasep_js_device_data *js_devdata; - struct kbase_backend_data *backend; - unsigned int s; - bool reset_needed = false; - - KBASE_DEBUG_ASSERT(timer != NULL); - - backend = container_of(timer, struct kbase_backend_data, scheduling_timer); - kbdev = container_of(backend, struct kbase_device, hwaccess.backend); - js_devdata = &kbdev->js_data; - - /* Loop through the slots */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - for (s = 0; s < kbdev->gpu_props.num_job_slots; s++) { - struct kbase_jd_atom *atom = NULL; - - if (kbase_backend_nr_atoms_on_slot(kbdev, s) > 0) { - atom = kbase_gpu_inspect(kbdev, s, 0); - KBASE_DEBUG_ASSERT(atom != NULL); - } - - if (atom != NULL) { - /* The current version of the model doesn't support - * Soft-Stop - */ - if (!kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_5736)) { - u32 ticks = atom->ticks++; - -#if !defined(CONFIG_MALI_VALHALL_JOB_DUMP) && !defined(CONFIG_MALI_VECTOR_DUMP) - u32 soft_stop_ticks, hard_stop_ticks, gpu_reset_ticks; - if (atom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { - soft_stop_ticks = js_devdata->soft_stop_ticks_cl; - hard_stop_ticks = js_devdata->hard_stop_ticks_cl; - gpu_reset_ticks = js_devdata->gpu_reset_ticks_cl; - } else { - soft_stop_ticks = js_devdata->soft_stop_ticks; - if (kbase_is_quick_reset_enabled(kbdev)) { - hard_stop_ticks = 2; - gpu_reset_ticks = 3; - } else { - hard_stop_ticks = js_devdata->hard_stop_ticks_ss; - gpu_reset_ticks = js_devdata->gpu_reset_ticks_ss; - } - } - - /* If timeouts have been changed then ensure - * that atom tick count is not greater than the - * new soft_stop timeout. This ensures that - * atoms do not miss any of the timeouts due to - * races between this worker and the thread - * changing the timeouts. - */ - if (backend->timeouts_updated && ticks > soft_stop_ticks) - ticks = atom->ticks = soft_stop_ticks; - - /* Job is Soft-Stoppable */ - if (ticks == soft_stop_ticks) { - /* Job has been scheduled for at least - * js_devdata->soft_stop_ticks ticks. - * Soft stop the slot so we can run - * other jobs. - */ -#if !KBASE_DISABLE_SCHEDULING_SOFT_STOPS - int disjoint_threshold = - KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD; - u32 softstop_flags = 0u; - - dev_dbg(kbdev->dev, "Soft-stop"); - /* nr_user_contexts_running is updated - * with the runpool_mutex, but we can't - * take that here. - * - * However, if it's about to be - * increased then the new context can't - * run any jobs until they take the - * hwaccess_lock, so it's OK to observe - * the older value. - * - * Similarly, if it's about to be - * decreased, the last job from another - * context has already finished, so - * it's not too bad that we observe the - * older value and register a disjoint - * event when we try soft-stopping - */ - if (js_devdata->nr_user_contexts_running >= - disjoint_threshold) - softstop_flags |= JS_COMMAND_SW_CAUSES_DISJOINT; - - kbase_job_slot_softstop_swflags(kbdev, s, atom, - softstop_flags); -#endif - } else if (ticks == hard_stop_ticks) { - /* Job has been scheduled for at least - * js_devdata->hard_stop_ticks_ss ticks. - * It should have been soft-stopped by - * now. Hard stop the slot. - */ -#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS - u32 ms = js_devdata->scheduling_period_ns / 1000000u; - if (!kbase_is_quick_reset_enabled(kbdev)) - dev_warn( - kbdev->dev, - "JS: Job Hard-Stopped (took more than %u ticks at %u ms/tick)", - ticks, ms); - kbase_job_slot_hardstop(atom->kctx, s, atom); -#endif - } else if (ticks == gpu_reset_ticks) { - /* Job has been scheduled for at least - * js_devdata->gpu_reset_ticks_ss ticks. - * It should have left the GPU by now. - * Signal that the GPU needs to be - * reset. - */ - reset_needed = true; - } -#else /* !CONFIG_MALI_VALHALL_JOB_DUMP */ - /* NOTE: During CONFIG_MALI_VALHALL_JOB_DUMP, we use - * the alternate timeouts, which makes the hard- - * stop and GPU reset timeout much longer. We - * also ensure that we don't soft-stop at all. - */ - if (ticks == js_devdata->soft_stop_ticks) { - /* Job has been scheduled for at least - * js_devdata->soft_stop_ticks. We do - * not soft-stop during - * CONFIG_MALI_VALHALL_JOB_DUMP, however. - */ - dev_dbg(kbdev->dev, "Soft-stop"); - } else if (ticks == js_devdata->hard_stop_ticks_dumping) { - /* Job has been scheduled for at least - * js_devdata->hard_stop_ticks_dumping - * ticks. Hard stop the slot. - */ -#if !KBASE_DISABLE_SCHEDULING_HARD_STOPS - u32 ms = js_devdata->scheduling_period_ns / 1000000u; - dev_warn( - kbdev->dev, - "JS: Job Hard-Stopped (took more than %u ticks at %u ms/tick)", - ticks, ms); - kbase_job_slot_hardstop(atom->kctx, s, atom); -#endif - } else if (ticks == js_devdata->gpu_reset_ticks_dumping) { - /* Job has been scheduled for at least - * js_devdata->gpu_reset_ticks_dumping - * ticks. It should have left the GPU by - * now. Signal that the GPU needs to be - * reset. - */ - reset_needed = true; - } -#endif /* !CONFIG_MALI_VALHALL_JOB_DUMP */ - } - } - } - if (reset_needed) { - if (kbase_is_quick_reset_enabled(kbdev)) - dev_err(kbdev->dev, "quick reset"); - else - dev_err(kbdev->dev, - "JS: Job has been on the GPU for too long (JS_RESET_TICKS_SS/DUMPING timeout hit). Issuing GPU soft-reset to resolve."); - - if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE)) - kbase_reset_gpu_locked(kbdev); - } - /* the timer is re-issued if there is contexts in the run-pool */ - - if (backend->timer_running) - hrtimer_start(&backend->scheduling_timer, - HR_TIMER_DELAY_NSEC(js_devdata->scheduling_period_ns), - HRTIMER_MODE_REL); - - backend->timeouts_updated = false; - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return HRTIMER_NORESTART; -} - -void kbase_backend_ctx_count_changed(struct kbase_device *kbdev) -{ - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - unsigned long flags; - /* Timer must stop if we are suspending */ - const bool suspend_timer = backend->suspend_timer; - const int nr_running_ctxs = atomic_read(&kbdev->js_data.nr_contexts_runnable); - - lockdep_assert_held(&js_devdata->runpool_mutex); - - if (suspend_timer || !timer_callback_should_run(kbdev, nr_running_ctxs)) { - /* Take spinlock to force synchronisation with timer */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - backend->timer_running = false; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - /* From now on, return value of timer_callback_should_run() - * will also cause the timer to not requeue itself. Its return - * value cannot change, because it depends on variables updated - * with the runpool_mutex held, which the caller of this must - * also hold - */ - hrtimer_cancel(&backend->scheduling_timer); - } - - if (!suspend_timer && timer_callback_should_run(kbdev, nr_running_ctxs) && - !backend->timer_running) { - /* Take spinlock to force synchronisation with timer */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - backend->timer_running = true; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - hrtimer_start(&backend->scheduling_timer, - HR_TIMER_DELAY_NSEC(js_devdata->scheduling_period_ns), - HRTIMER_MODE_REL); - - KBASE_KTRACE_ADD_JM(kbdev, JS_POLICY_TIMER_START, NULL, NULL, 0u, 0u); - } - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - if (unlikely(suspend_timer)) { - js_devdata->gpu_metrics_timer_needed = false; - /* Cancel the timer as System suspend is happening */ - hrtimer_cancel(&js_devdata->gpu_metrics_timer); - js_devdata->gpu_metrics_timer_running = false; - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - /* Explicitly emit the tracepoint on System suspend */ - kbase_gpu_metrics_emit_tracepoint(kbdev, ktime_get_raw_ns()); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - return; - } - - if (!nr_running_ctxs) { - /* Just set the flag to not restart the timer on expiry */ - js_devdata->gpu_metrics_timer_needed = false; - return; - } - - /* There are runnable contexts so the timer is needed */ - if (!js_devdata->gpu_metrics_timer_needed) { - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - js_devdata->gpu_metrics_timer_needed = true; - /* No need to restart the timer if it is already running. */ - if (!js_devdata->gpu_metrics_timer_running) { - hrtimer_start(&js_devdata->gpu_metrics_timer, - HR_TIMER_DELAY_NSEC(kbase_gpu_metrics_get_tp_emit_interval()), - HRTIMER_MODE_REL); - js_devdata->gpu_metrics_timer_running = true; - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } -#endif -} - -int kbase_backend_timer_init(struct kbase_device *kbdev) -{ - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - - hrtimer_init(&backend->scheduling_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - backend->scheduling_timer.function = timer_callback; - backend->timer_running = false; - - return 0; -} - -void kbase_backend_timer_term(struct kbase_device *kbdev) -{ - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - - hrtimer_cancel(&backend->scheduling_timer); -} - -void kbase_backend_timer_suspend(struct kbase_device *kbdev) -{ - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - - backend->suspend_timer = true; - - kbase_backend_ctx_count_changed(kbdev); -} - -void kbase_backend_timer_resume(struct kbase_device *kbdev) -{ - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - - backend->suspend_timer = false; - - kbase_backend_ctx_count_changed(kbdev); -} - -void kbase_backend_timeouts_changed(struct kbase_device *kbdev) -{ - struct kbase_backend_data *backend = &kbdev->hwaccess.backend; - - backend->timeouts_updated = true; -} diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_internal.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_internal.h deleted file mode 100644 index 4f7c371a1f1a..000000000000 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_js_internal.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2014-2015, 2020-2021 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Register-based HW access backend specific job scheduler APIs - */ - -#ifndef _KBASE_JS_BACKEND_H_ -#define _KBASE_JS_BACKEND_H_ - -/** - * kbase_backend_timer_init() - Initialise the JS scheduling timer - * @kbdev: Device pointer - * - * This function should be called at driver initialisation - * - * Return: 0 on success - */ -int kbase_backend_timer_init(struct kbase_device *kbdev); - -/** - * kbase_backend_timer_term() - Terminate the JS scheduling timer - * @kbdev: Device pointer - * - * This function should be called at driver termination - */ -void kbase_backend_timer_term(struct kbase_device *kbdev); - -/** - * kbase_backend_timer_suspend - Suspend is happening, stop the JS scheduling - * timer - * @kbdev: Device pointer - * - * This function should be called on suspend, after the active count has reached - * zero. This is required as the timer may have been started on job submission - * to the job scheduler, but before jobs are submitted to the GPU. - * - * Caller must hold runpool_mutex. - */ -void kbase_backend_timer_suspend(struct kbase_device *kbdev); - -/** - * kbase_backend_timer_resume - Resume is happening, re-evaluate the JS - * scheduling timer - * @kbdev: Device pointer - * - * This function should be called on resume. Note that is not guaranteed to - * re-start the timer, only evalute whether it should be re-started. - * - * Caller must hold runpool_mutex. - */ -void kbase_backend_timer_resume(struct kbase_device *kbdev); - -#endif /* _KBASE_JS_BACKEND_H_ */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.c index 527d0c5717e6..d752f2d9a6da 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.c @@ -36,7 +36,6 @@ #include -#if MALI_USE_CSF #include /* Index of the last value register for each type of core, with the 1st value @@ -55,11 +54,8 @@ static u32 gpu_control_base_addr; /* Array for storing the value of SELECT register for each type of core */ static u64 ipa_ctl_select_config[KBASE_IPA_CORE_TYPE_NUM]; static u32 ipa_control_timer_enabled; -#endif -#if MALI_USE_CSF static u32 sysc_alloc_regs[SYSC_ALLOC_COUNT]; -#endif #define LO_MASK(M) ((M)&0xFFFFFFFF) #define HI_MASK(M) ((M)&0xFFFFFFFF00000000) @@ -69,13 +65,8 @@ static u32 sysc_alloc_regs[SYSC_ALLOC_COUNT]; * significant bits, which are set to THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_SOFTWARE in * midgard_model_read_reg(). */ -#if MALI_USE_CSF #define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 24)) -#else -#define THREAD_FEATURES_PARTIAL(MAX_REGISTERS, MAX_TASK_QUEUE, MAX_TG_SPLIT) \ - ((MAX_REGISTERS) | ((MAX_TASK_QUEUE) << 16) | ((MAX_TG_SPLIT) << 24)) -#endif struct error_status_t hw_error_status; @@ -133,24 +124,18 @@ enum pwr_on_index { INDEX_TILER, INDEX_SHADER, INDEX_STACK, -#if MALI_USE_CSF INDEX_BASE, INDEX_NEURAL, -#endif INDEX_DOMAIN_COUNT }; struct dummy_model_t { int reset_completed; int reset_completed_mask; -#if !MALI_USE_CSF - int prfcnt_sample_completed; -#endif /* !MALI_USE_CSF */ int power_changed_mask; /* 2 bits: _ALL,_SINGLE */ int power_changed; /* 1 bit */ bool clean_caches_completed; bool clean_caches_completed_irq_enabled; -#if MALI_USE_CSF bool flush_pa_range_completed; bool flush_pa_range_completed_irq_enabled; /* Representations of COMMAND_NOT_ALLOWED and COMMAND_INVALID bits in @@ -164,7 +149,6 @@ struct dummy_model_t { u64 command_arg; /* PWR_CMDARG register */ u64 gov_core_mask; -#endif uint32_t domain_power_on[INDEX_DOMAIN_COUNT]; u32 coherency_enable; unsigned int job_irq_js_state; @@ -462,9 +446,6 @@ static const struct control_reg_values_t all_control_reg_values[] = { static struct { spinlock_t access_lock; -#if !MALI_USE_CSF - unsigned long prfcnt_base; -#endif /* !MALI_USE_CSF */ u32 *prfcnt_base_cpu; u32 time; @@ -474,11 +455,7 @@ static struct { u64 l2_present; u64 shader_present; -#if !MALI_USE_CSF - u64 jm_counters[KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; -#else u64 cshw_counters[KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; -#endif /* !MALI_USE_CSF */ u64 tiler_counters[KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; u64 l2_counters[KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS * KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; u64 shader_counters[KBASE_DUMMY_MODEL_MAX_SHADER_CORES * KBASE_DUMMY_MODEL_COUNTER_PER_CORE]; @@ -510,7 +487,6 @@ static u32 get_implementation_register(u32 reg, return 0; } -#if MALI_USE_CSF static u32 hctrl_get_implementation_register(u32 reg, const struct control_reg_values_t *const control_reg_values) @@ -531,7 +507,6 @@ hctrl_get_implementation_register(u32 reg, return 0; } -#endif void gpu_device_set_data(void *model, void *data) { @@ -553,7 +528,6 @@ static char *no_mali_gpu = CONFIG_MALI_VALHALL_NO_MALI_DEFAULT_GPU; module_param(no_mali_gpu, charp, 0000); MODULE_PARM_DESC(no_mali_gpu, "GPU to identify as"); -#if MALI_USE_CSF static u32 gpu_model_get_prfcnt_value(enum kbase_ipa_core_type core_type, u32 cnt_idx, bool is_low_word) { @@ -628,7 +602,6 @@ static u32 gpu_model_get_prfcnt_value(enum kbase_ipa_core_type core_type, u32 cn else return (value >> 32); } -#endif /* MALI_USE_CSF */ /** * gpu_model_clear_prfcnt_values_nolock - Clear performance counter values @@ -639,18 +612,13 @@ static u32 gpu_model_get_prfcnt_value(enum kbase_ipa_core_type core_type, u32 cn static void gpu_model_clear_prfcnt_values_nolock(void) { lockdep_assert_held(&performance_counters.access_lock); -#if !MALI_USE_CSF - memset(performance_counters.jm_counters, 0, sizeof(performance_counters.jm_counters)); -#else memset(performance_counters.cshw_counters, 0, sizeof(performance_counters.cshw_counters)); -#endif /* !MALI_USE_CSF */ memset(performance_counters.tiler_counters, 0, sizeof(performance_counters.tiler_counters)); memset(performance_counters.l2_counters, 0, sizeof(performance_counters.l2_counters)); memset(performance_counters.shader_counters, 0, sizeof(performance_counters.shader_counters)); } -#if MALI_USE_CSF void gpu_model_clear_prfcnt_values(void) { unsigned long flags; @@ -660,7 +628,6 @@ void gpu_model_clear_prfcnt_values(void) spin_unlock_irqrestore(&performance_counters.access_lock, flags); } KBASE_EXPORT_TEST_API(gpu_model_clear_prfcnt_values); -#endif /* MALI_USE_CSF */ /** * gpu_model_dump_prfcnt_blocks() - Dump performance counter values to buffer @@ -689,11 +656,9 @@ static void gpu_model_dump_prfcnt_blocks(u64 *values, u32 *out_index, u32 block_ for (block_idx = 0; block_idx < block_count; block_idx++) { /* only dump values if core is present */ if (!(blocks_present & (1U << block_idx))) { -#if MALI_USE_CSF /* if CSF dump zeroed out block */ memset(&prfcnt_base[*out_index], 0, KBASE_DUMMY_MODEL_BLOCK_SIZE); *out_index += KBASE_DUMMY_MODEL_VALUES_PER_BLOCK; -#endif /* MALI_USE_CSF */ continue; } @@ -724,13 +689,8 @@ static void gpu_model_dump_nolock(void) lockdep_assert_held(&performance_counters.access_lock); -#if !MALI_USE_CSF - gpu_model_dump_prfcnt_blocks(performance_counters.jm_counters, &index, 1, - performance_counters.prfcnt_en.fe, 0x1); -#else gpu_model_dump_prfcnt_blocks(performance_counters.cshw_counters, &index, 1, performance_counters.prfcnt_en.fe, 0x1); -#endif /* !MALI_USE_CSF */ gpu_model_dump_prfcnt_blocks(performance_counters.tiler_counters, &index, 1, performance_counters.prfcnt_en.tiler, DUMMY_IMPLEMENTATION_TILER_PRESENT); @@ -763,16 +723,6 @@ static void gpu_model_raise_irq(void *model, u32 irq) gpu_device_raise_irq(model, irq); } -#if !MALI_USE_CSF -static void midgard_model_dump_prfcnt(void) -{ - unsigned long flags; - - spin_lock_irqsave(&performance_counters.access_lock, flags); - gpu_model_dump_nolock(); - spin_unlock_irqrestore(&performance_counters.access_lock, flags); -} -#else void gpu_model_prfcnt_dump_request(u32 *sample_buf, struct gpu_model_prfcnt_en enable_maps) { unsigned long flags; @@ -796,7 +746,6 @@ void gpu_model_glb_request_job_irq(void *model) spin_unlock_irqrestore(&hw_error_status.access_lock, flags); gpu_model_raise_irq(model, MODEL_LINUX_JOB_IRQ); } -#endif /* !MALI_USE_CSF */ static void init_register_statuses(struct dummy_model_t *dummy) { @@ -830,117 +779,6 @@ static void update_register_statuses(struct dummy_model_t *dummy, u32 job_slot) if (hw_error_status.errors_mask & IS_A_JOB_ERROR) { if (job_slot == hw_error_status.current_job_slot) { -#if !MALI_USE_CSF - if (hw_error_status.js_status[job_slot] == 0) { - /* status reg is clean; it can be written */ - - switch (hw_error_status.errors_mask & IS_A_JOB_ERROR) { - case KBASE_JOB_INTERRUPTED: - hw_error_status.js_status[job_slot] = JS_STATUS_INTERRUPTED; - break; - - case KBASE_JOB_STOPPED: - hw_error_status.js_status[job_slot] = JS_STATUS_STOPPED; - break; - - case KBASE_JOB_TERMINATED: - hw_error_status.js_status[job_slot] = JS_STATUS_TERMINATED; - break; - - case KBASE_JOB_CONFIG_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_CONFIG_FAULT; - break; - - case KBASE_JOB_POWER_FAULT: - hw_error_status.js_status[job_slot] = JS_STATUS_POWER_FAULT; - break; - - case KBASE_JOB_READ_FAULT: - hw_error_status.js_status[job_slot] = JS_STATUS_READ_FAULT; - break; - - case KBASE_JOB_WRITE_FAULT: - hw_error_status.js_status[job_slot] = JS_STATUS_WRITE_FAULT; - break; - - case KBASE_JOB_AFFINITY_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_AFFINITY_FAULT; - break; - - case KBASE_JOB_BUS_FAULT: - hw_error_status.js_status[job_slot] = JS_STATUS_BUS_FAULT; - break; - - case KBASE_INSTR_INVALID_PC: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_INVALID_PC; - break; - - case KBASE_INSTR_INVALID_ENC: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_INVALID_ENC; - break; - - case KBASE_INSTR_TYPE_MISMATCH: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_TYPE_MISMATCH; - break; - - case KBASE_INSTR_OPERAND_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_OPERAND_FAULT; - break; - - case KBASE_INSTR_TLS_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_TLS_FAULT; - break; - - case KBASE_INSTR_BARRIER_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_BARRIER_FAULT; - break; - - case KBASE_INSTR_ALIGN_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_INSTR_ALIGN_FAULT; - break; - - case KBASE_DATA_INVALID_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_DATA_INVALID_FAULT; - break; - - case KBASE_TILE_RANGE_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_TILE_RANGE_FAULT; - break; - - case KBASE_ADDR_RANGE_FAULT: - hw_error_status.js_status[job_slot] = - JS_STATUS_ADDRESS_RANGE_FAULT; - break; - - case KBASE_OUT_OF_MEMORY: - hw_error_status.js_status[job_slot] = - JS_STATUS_OUT_OF_MEMORY; - break; - - case KBASE_UNKNOWN: - hw_error_status.js_status[job_slot] = JS_STATUS_UNKNOWN; - break; - - default: - model_error_log(KBASE_CORE, - "\nAtom Chain 0x%llx: Invalid Error Mask!", - hw_error_status.current_jc); - break; - } - } -#endif /* !MALI_USE_CSF */ - /* we set JOB_FAIL_ */ hw_error_status.job_irq_rawstat |= (dummy->slots[job_slot].job_complete_irq_asserted) @@ -1049,40 +887,6 @@ static void update_register_statuses(struct dummy_model_t *dummy, u32 job_slot) hw_error_status.errors_mask = 0; /*clear error mask */ } -#if !MALI_USE_CSF -static void update_job_irq_js_state(struct dummy_model_t *dummy, int mask) -{ - int i; - - lockdep_assert_held(&hw_error_status.access_lock); - pr_debug("%s", "Updating the JS_ACTIVE register"); - - for (i = 0; i < NUM_SLOTS; i++) { - int slot_active = dummy->slots[i].job_active; - int next_busy = dummy->slots[i].job_queued; - - if ((mask & (1 << i)) || (mask & (1 << (i + 16)))) { - /* clear the bits we're updating */ - dummy->job_irq_js_state &= ~((1 << (16 + i)) | (1 << i)); - if (hw_error_status.js_status[i]) { - dummy->job_irq_js_state |= next_busy << (i + 16); - if (mask & (1 << (i + 16))) { - /* clear job slot status */ - hw_error_status.js_status[i] = 0; - /* continue execution of jobchain */ - dummy->slots[i].job_active = dummy->slots[i].job_queued; - } - } else { - /* set bits if needed */ - dummy->job_irq_js_state |= - ((slot_active << i) | (next_busy << (i + 16))); - } - } - } - pr_debug("The new snapshot is 0x%08X\n", dummy->job_irq_js_state); -} -#endif /* !MALI_USE_CSF */ - /** * find_gpu_rev() - Append GPU HW revision to the GPU name, if needed. * @new_gpu_name: Caller-allocated string for the new GPU name. @@ -1121,6 +925,9 @@ static const struct control_reg_values_t *find_control_reg_values(const char *gp const struct control_reg_values_t *ret = NULL; char *gpu_with_rev = kmalloc(strlen(gpu) + GPU_REV_STR_LEN + 1, GFP_KERNEL); + if (gpu_with_rev == NULL) + return NULL; + /* Fix gpu name in case there are multiple entries for different HW versions. */ find_gpu_rev(gpu_with_rev, gpu); @@ -1164,10 +971,15 @@ void *midgard_model_create(struct kbase_device *kbdev) dummy->job_irq_js_state = 0; init_register_statuses(dummy); dummy->control_reg_values = find_control_reg_values(no_mali_gpu); + + if (dummy->control_reg_values == NULL) { + kfree(dummy); + return NULL; + } + dummy->arch_id = get_arch_id(dummy->control_reg_values->gpu_id); gpu_control_base_addr = GPU_CONTROL_BASE; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { performance_counters.l2_present = hctrl_get_implementation_register( GET_HOST_POWER_REG(HOST_POWER_L2_PRESENT_LO), @@ -1175,9 +987,7 @@ void *midgard_model_create(struct kbase_device *kbdev) performance_counters.shader_present = hctrl_get_implementation_register( GET_HOST_POWER_REG(HOST_POWER_SHADER_PRESENT_LO), dummy->control_reg_values); - } else -#endif /* MALI_USE_CSF */ - { + } else { performance_counters.l2_present = get_implementation_register( GET_GPU_CONTROL_REG(L2_PRESENT_LO), dummy->control_reg_values); performance_counters.shader_present = get_implementation_register( @@ -1299,73 +1109,6 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) spin_lock_irqsave(&hw_error_status.access_lock, flags); -#if !MALI_USE_CSF - if ((addr >= JOB_CONTROL_REG(JOB_SLOT0)) && (addr < (JOB_CONTROL_REG(JOB_SLOT15) + 0x80))) { - unsigned int slot_idx = (addr >> 7) & 0xf; - - KBASE_DEBUG_ASSERT(slot_idx < NUM_SLOTS); - if (addr == JOB_SLOT_REG(slot_idx, JS_HEAD_NEXT_LO)) { - hw_error_status.current_jc &= ~((u64)(0xFFFFFFFF)); - hw_error_status.current_jc |= (u64)value; - } - if (addr == JOB_SLOT_REG(slot_idx, JS_HEAD_NEXT_HI)) { - hw_error_status.current_jc &= (u64)0xFFFFFFFF; - hw_error_status.current_jc |= ((u64)value) << 32; - } - if (addr == JOB_SLOT_REG(slot_idx, JS_COMMAND_NEXT) && value == 1) { - pr_debug("%s", "start detected"); - KBASE_DEBUG_ASSERT(!dummy->slots[slot_idx].job_active || - !dummy->slots[slot_idx].job_queued); - if ((dummy->slots[slot_idx].job_active) || - (hw_error_status.job_irq_rawstat & (1 << (slot_idx + 16)))) { - pr_debug( - "~~~~~~~~~~~ Start: job slot is already active or there are IRQ pending ~~~~~~~~~"); - dummy->slots[slot_idx].job_queued = 1; - } else { - dummy->slots[slot_idx].job_active = 1; - } - } - - if (addr == JOB_SLOT_REG(slot_idx, JS_COMMAND_NEXT) && value == 0) - dummy->slots[slot_idx].job_queued = 0; - - if ((addr == JOB_SLOT_REG(slot_idx, JS_COMMAND)) && - (value == JS_COMMAND_SOFT_STOP || value == JS_COMMAND_HARD_STOP)) { - /*dummy->slots[slot_idx].job_active = 0; */ - hw_error_status.current_job_slot = slot_idx; - if (value == JS_COMMAND_SOFT_STOP) { - hw_error_status.errors_mask = KBASE_JOB_STOPPED; - } else { /*value == 3 */ - - if (dummy->slots[slot_idx].job_disabled != 0) { - pr_debug("enabling slot after HARD_STOP"); - dummy->slots[slot_idx].job_disabled = 0; - } - hw_error_status.errors_mask = KBASE_JOB_TERMINATED; - } - } - } else if (addr == JOB_CONTROL_REG(JOB_IRQ_CLEAR)) { - int i; - - for (i = 0; i < NUM_SLOTS; i++) { - if (value & ((1u << i) | (1u << (i + 16)))) - dummy->slots[i].job_complete_irq_asserted = 0; - /* hw_error_status.js_status[i] is cleared in - * update_job_irq_js_state - */ - } - pr_debug("%s", "job irq cleared"); - update_job_irq_js_state(dummy, value); - /*remove error condition for JOB */ - hw_error_status.job_irq_rawstat &= ~(value); - hw_error_status.job_irq_status &= ~(value); - } else if (addr == JOB_CONTROL_REG(JOB_IRQ_MASK)) { - int i; - - for (i = 0; i < NUM_SLOTS; i++) - dummy->slots[i].job_irq_mask = (value >> i) & 0x01; - pr_debug("job irq mask to value %x", value); -#else /* MALI_USE_CSF */ if (addr == JOB_CONTROL_REG(JOB_IRQ_CLEAR)) { pr_debug("%s", "job irq cleared"); @@ -1376,25 +1119,16 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) hw_error_status.job_irq_status |= value; } else if (addr == JOB_CONTROL_REG(JOB_IRQ_MASK)) { /* ignore JOB_IRQ_MASK as it is handled by CSFFW */ -#endif /* !MALI_USE_CSF */ } else if (addr == GET_GPU_CONTROL_REG(GPU_IRQ_MASK)) { pr_debug("GPU_IRQ_MASK set to 0x%x", value); -#if MALI_USE_CSF if (!dummy->kbdev->pm.backend.has_host_pwr_iface) { dummy->reset_completed_mask = (value >> 8) & 0x01; dummy->power_changed_mask = (value >> 9) & 0x03; } -#else - dummy->reset_completed_mask = (value >> 8) & 0x01; - dummy->power_changed_mask = (value >> 9) & 0x03; -#endif dummy->clean_caches_completed_irq_enabled = (value & (1u << 17)) != 0u; -#if MALI_USE_CSF dummy->flush_pa_range_completed_irq_enabled = (value & (1u << 20)) != 0u; -#endif } else if (addr == GET_GPU_CONTROL_REG(COHERENCY_ENABLE)) { dummy->coherency_enable = value; -#if MALI_USE_CSF } else if (addr == GET_HOST_POWER_REG(PWR_IRQ_MASK)) { pr_debug("PWR_IRQ_MASK set to 0x%x", value); dummy->power_changed_mask = (value & PWR_IRQ_POWER_CHANGED_SINGLE) | @@ -1531,28 +1265,12 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) if (value & (POWER_CHANGED_SINGLE | POWER_CHANGED_ALL)) dummy->power_changed = 0; } -#else - } else if (addr == GET_GPU_CONTROL_REG(GPU_IRQ_CLEAR)) { - if (value & RESET_COMPLETED) { - pr_debug("%s", "gpu RESET_COMPLETED irq cleared"); - dummy->reset_completed = 0; - } - if (value & (POWER_CHANGED_SINGLE | POWER_CHANGED_ALL)) - dummy->power_changed = 0; -#endif /* MALI_USE_CSF */ if (value & CLEAN_CACHES_COMPLETED) dummy->clean_caches_completed = false; -#if MALI_USE_CSF if (value & (1u << 20)) dummy->flush_pa_range_completed = false; -#endif /* MALI_USE_CSF */ - -#if !MALI_USE_CSF - if (value & PRFCNT_SAMPLE_COMPLETED) /* (1 << 16) */ - dummy->prfcnt_sample_completed = 0; -#endif /* !MALI_USE_CSF */ /*update error status */ hw_error_status.gpu_error_irq &= ~(value); @@ -1566,41 +1284,26 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) /* completed reset instantly */ dummy->reset_completed = 1; break; -#if MALI_USE_CSF case GPU_COMMAND_CACHE_CLN_INV_L2: case GPU_COMMAND_CACHE_CLN_INV_L2_LSC: case GPU_COMMAND_CACHE_CLN_INV_FULL: -#else - case GPU_COMMAND_CLEAN_CACHES: - case GPU_COMMAND_CLEAN_INV_CACHES: -#endif pr_debug("clean caches requested"); dummy->clean_caches_completed = true; break; -#if MALI_USE_CSF case GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2: case GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC: case GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_FULL: pr_debug("pa range flush requested"); dummy->flush_pa_range_completed = true; break; -#endif /* MALI_USE_CSF */ -#if !MALI_USE_CSF - case GPU_COMMAND_PRFCNT_SAMPLE: - midgard_model_dump_prfcnt(); - dummy->prfcnt_sample_completed = 1; -#endif /* !MALI_USE_CSF */ default: break; } -#if MALI_USE_CSF } else if (addr >= GET_GPU_CONTROL_REG(GPU_COMMAND_ARG0_LO) && addr <= GET_GPU_CONTROL_REG(GPU_COMMAND_ARG1_HI)) { /* Writes ignored */ -#endif } else if (addr == GET_GPU_CONTROL_REG(L2_CONFIG)) { dummy->l2_config = value; -#if MALI_USE_CSF } else if (addr >= CSF_HW_DOORBELL_PAGE_OFFSET && addr < CSF_HW_DOORBELL_PAGE_OFFSET + (dummy->kbdev->csf.num_doorbells * CSF_HW_DOORBELL_PAGE_SIZE)) { @@ -1650,7 +1353,6 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) } } else if (addr == GPU_GOV_CORE_MASK_OFFSET) { dummy->gov_core_mask = value; -#endif /* MALI_USE_CSF */ } else if (addr == MMU_CONTROL_REG(MMU_IRQ_MASK)) { hw_error_status.mmu_irq_mask = value; } else if (addr == MMU_CONTROL_REG(MMU_IRQ_CLEAR)) { @@ -1659,6 +1361,9 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) (addr <= MMU_STAGE1_REG(MMU_AS_REG(15, AS_STATUS)))) { u32 mem_addr_space = (addr - MMU_STAGE1_REG(MMU_AS_REG(0, AS_TRANSTAB_LO))) >> MMU_STAGE1_AS_SHIFT; + if (WARN_ON(mem_addr_space >= NUM_MMU_AS)) { + return; + } switch (addr & 0x3F) { case AS_COMMAND: @@ -1737,32 +1442,6 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) } } else { switch (addr) { -#if !MALI_USE_CSF - case PRFCNT_BASE_LO: - performance_counters.prfcnt_base = - HI_MASK(performance_counters.prfcnt_base) | value; - performance_counters.prfcnt_base_cpu = - (u32 *)(uintptr_t)performance_counters.prfcnt_base; - break; - case PRFCNT_BASE_HI: - performance_counters.prfcnt_base = - LO_MASK(performance_counters.prfcnt_base) | (((u64)value) << 32); - performance_counters.prfcnt_base_cpu = - (u32 *)(uintptr_t)performance_counters.prfcnt_base; - break; - case PRFCNT_JM_EN: - performance_counters.prfcnt_en.fe = value; - break; - case PRFCNT_SHADER_EN: - performance_counters.prfcnt_en.shader = value; - break; - case PRFCNT_TILER_EN: - performance_counters.prfcnt_en.tiler = value; - break; - case PRFCNT_MMU_L2_EN: - performance_counters.prfcnt_en.l2 = value; - break; -#endif /* !MALI_USE_CSF */ case TILER_PWRON_LO: dummy->domain_power_on[INDEX_TILER] |= value & DUMMY_IMPLEMENTATION_TILER_PRESENT; @@ -1813,13 +1492,8 @@ void midgard_model_write_reg(void *h, u32 addr, u32 value) case PWR_KEY: case PWR_OVERRIDE0: case PWR_OVERRIDE1: -#if MALI_USE_CSF case SHADER_PWRFEATURES: case CSF_CONFIG: -#else /* !MALI_USE_CSF */ - case JM_CONFIG: - case PRFCNT_CONFIG: -#endif /* MALI_USE_CSF */ case SHADER_CONFIG: case TILER_CONFIG: case L2_MMU_CONFIG: @@ -1847,15 +1521,7 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) spin_lock_irqsave(&hw_error_status.access_lock, flags); *value = 0; /* 0 by default */ -#if !MALI_USE_CSF - if (addr == JOB_CONTROL_REG(JOB_IRQ_JS_STATE)) { - pr_debug("%s", "JS_ACTIVE being read"); - - *value = dummy->job_irq_js_state; - } else if (addr == GET_GPU_CONTROL_REG(GPU_ID)) { -#else /* !MALI_USE_CSF */ if (addr == GET_GPU_CONTROL_REG(GPU_ID)) { -#endif /* !MALI_USE_CSF */ *value = dummy->control_reg_values->gpu_id & U32_MAX; } else if (addr == JOB_CONTROL_REG(JOB_IRQ_RAWSTAT)) { *value = hw_error_status.job_irq_rawstat; @@ -1863,42 +1529,21 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) } else if (addr == JOB_CONTROL_REG(JOB_IRQ_STATUS)) { *value = hw_error_status.job_irq_status; pr_debug("JS_IRQ_STATUS being read %x", *value); -#if !MALI_USE_CSF - } else if (addr == JOB_CONTROL_REG(JOB_IRQ_MASK)) { - int i; - - *value = 0; - for (i = 0; i < NUM_SLOTS; i++) - *value |= dummy->slots[i].job_irq_mask << i; - pr_debug("JS_IRQ_MASK being read %x", *value); -#else /* !MALI_USE_CSF */ } else if (addr == JOB_CONTROL_REG(JOB_IRQ_MASK)) { /* ignore JOB_IRQ_MASK as it is handled by CSFFW */ -#endif /* !MALI_USE_CSF */ } else if (addr == GET_GPU_CONTROL_REG(GPU_IRQ_MASK)) { *value = (dummy->reset_completed_mask << 8) | ((dummy->clean_caches_completed_irq_enabled ? 1u : 0u) << 17) | -#if MALI_USE_CSF ((dummy->flush_pa_range_completed_irq_enabled ? 1u : 0u) << 20) | -#endif (dummy->power_changed_mask << 9) | (1u << 7) | 1u; pr_debug("GPU_IRQ_MASK read %x", *value); } else if (addr == GET_GPU_CONTROL_REG(GPU_IRQ_RAWSTAT)) { *value = ((dummy->clean_caches_completed ? 1u : 0u) << 17) | -#if MALI_USE_CSF ((dummy->flush_pa_range_completed ? 1u : 0u) << 20) | -#else - (dummy->prfcnt_sample_completed ? PRFCNT_SAMPLE_COMPLETED : 0) | -#endif hw_error_status.gpu_error_irq; -#if MALI_USE_CSF if (!dummy->kbdev->pm.backend.has_host_pwr_iface) *value |= (dummy->power_changed << 9) | (dummy->power_changed << 10) | (dummy->reset_completed << 8); -#else - *value |= (dummy->power_changed << 9) | (dummy->power_changed << 10) | - (dummy->reset_completed << 8); -#endif pr_debug("GPU_IRQ_RAWSTAT read %x", *value); } else if (addr == GET_GPU_CONTROL_REG(GPU_IRQ_STATUS)) { @@ -1907,40 +1552,25 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) 1u : 0u) << 17) | -#if MALI_USE_CSF (((dummy->flush_pa_range_completed && dummy->flush_pa_range_completed_irq_enabled) ? 1u : 0u) << 20) | -#else - (dummy->prfcnt_sample_completed ? PRFCNT_SAMPLE_COMPLETED : 0) | -#endif hw_error_status.gpu_error_irq; -#if MALI_USE_CSF if (!dummy->kbdev->pm.backend.has_host_pwr_iface) *value |= ((dummy->power_changed && (dummy->power_changed_mask & 0x1)) << 9) | ((dummy->power_changed && (dummy->power_changed_mask & 0x2)) << 10) | ((dummy->reset_completed & dummy->reset_completed_mask) << 8); -#else - *value |= ((dummy->power_changed && (dummy->power_changed_mask & 0x1)) << 9) | - ((dummy->power_changed && (dummy->power_changed_mask & 0x2)) << 10) | - ((dummy->reset_completed & dummy->reset_completed_mask) << 8); -#endif pr_debug("GPU_IRQ_STAT read %x", *value); } else if (addr == GET_GPU_CONTROL_REG(GPU_STATUS)) { *value = 0; -#if !MALI_USE_CSF - } else if (addr == GET_GPU_CONTROL_REG(LATEST_FLUSH)) { - *value = 0; -#endif } else if (addr == GET_GPU_CONTROL_REG(GPU_FAULTSTATUS)) { *value = hw_error_status.gpu_fault_status; } else if (addr == GET_GPU_CONTROL_REG(L2_CONFIG)) { *value = dummy->l2_config; -#if MALI_USE_CSF } else if ((addr >= GET_GPU_CONTROL_REG(SYSC_ALLOC0)) && (addr < GET_GPU_CONTROL_REG(SYSC_ALLOC(SYSC_ALLOC_COUNT)))) { u32 alloc_reg = (addr - GET_GPU_CONTROL_REG(SYSC_ALLOC0)) >> 2; @@ -2042,8 +1672,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) addr == GET_HOST_POWER_REG(HOST_POWER_NEURAL_PWRTRANS_LO) || addr == GET_HOST_POWER_REG(HOST_POWER_NEURAL_PWRTRANS_HI) || - addr == GET_HOST_POWER_REG(HOST_POWER_L2_PWRACTIVE_LO) || - addr == GET_HOST_POWER_REG(HOST_POWER_L2_PWRACTIVE_HI) || addr == GET_HOST_POWER_REG(HOST_POWER_TILER_PWRACTIVE_LO) || addr == GET_HOST_POWER_REG(HOST_POWER_TILER_PWRACTIVE_HI) || addr == GET_HOST_POWER_REG(HOST_POWER_SHADER_PWRACTIVE_LO) || @@ -2066,7 +1694,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) "Dummy model register access: Reading unknown control reg 0x%x\n", addr); } -#endif } else if ((addr >= GET_GPU_CONTROL_REG(SHADER_PRESENT_LO)) && (addr <= GET_GPU_CONTROL_REG(L2_MMU_CONFIG))) { if (addr == GET_GPU_CONTROL_REG(SHADER_PRESENT_LO) || @@ -2106,8 +1733,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) addr == GET_GPU_CONTROL_REG(SHADER_PWRTRANS_HI) || addr == GET_GPU_CONTROL_REG(STACK_PWRTRANS_LO) || addr == GET_GPU_CONTROL_REG(STACK_PWRTRANS_HI) || - addr == GET_GPU_CONTROL_REG(L2_PWRACTIVE_LO) || - addr == GET_GPU_CONTROL_REG(L2_PWRACTIVE_HI) || addr == GET_GPU_CONTROL_REG(TILER_PWRACTIVE_LO) || addr == GET_GPU_CONTROL_REG(TILER_PWRACTIVE_HI) || addr == GET_GPU_CONTROL_REG(SHADER_PWRACTIVE_LO) || @@ -2131,51 +1756,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) addr); } -#if !MALI_USE_CSF - } else if ((addr >= JOB_CONTROL_REG(JOB_SLOT0)) && - (addr < (JOB_CONTROL_REG(JOB_SLOT15) + 0x80))) { - int slot_idx = (addr >> 7) & 0xf; - int sub_reg = addr & 0x7F; - - KBASE_DEBUG_ASSERT(slot_idx < NUM_SLOTS); - switch (sub_reg) { - case JS_HEAD_NEXT_LO: - *value = (u32)((hw_error_status.current_jc) & 0xFFFFFFFF); - break; - case JS_HEAD_NEXT_HI: - *value = (u32)(hw_error_status.current_jc >> 32); - break; - case JS_STATUS: - if (hw_error_status.js_status[slot_idx]) - *value = hw_error_status.js_status[slot_idx]; - else /* 0x08 means active, 0x00 idle */ - *value = (dummy->slots[slot_idx].job_active) << 3; - break; - case JS_COMMAND_NEXT: - *value = dummy->slots[slot_idx].job_queued; - break; - - /** - * The dummy model does not implement these registers - * avoid printing error messages - */ - case JS_HEAD_HI: - case JS_HEAD_LO: - case JS_TAIL_HI: - case JS_TAIL_LO: - case JS_FLUSH_ID_NEXT: - break; - - default: - model_error_log( - KBASE_CORE, - "Dummy model register access: unknown job slot reg 0x%02X being read\n", - sub_reg); - break; - } - } else if (addr == GET_GPU_CONTROL_REG(JS_PRESENT)) { - *value = 0x7; -#endif /* !MALI_USE_CSF */ } else if (addr == GET_GPU_CONTROL_REG(AS_PRESENT)) { *value = dummy->control_reg_values->as_present; } else if (addr >= GET_GPU_CONTROL_REG(TEXTURE_FEATURES_0) && @@ -2188,27 +1768,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) *value = 0x9f81ffff; else if (addr == GET_GPU_CONTROL_REG(TEXTURE_FEATURES_3)) *value = 0; -#if !MALI_USE_CSF - } else if (addr >= GPU_CONTROL_REG(JS0_FEATURES) && - addr <= GPU_CONTROL_REG(JS15_FEATURES)) { - switch (addr) { - case GPU_CONTROL_REG(JS0_FEATURES): - *value = 0x20e; - break; - - case GPU_CONTROL_REG(JS1_FEATURES): - *value = 0x1fe; - break; - - case GPU_CONTROL_REG(JS2_FEATURES): - *value = 0x7e; - break; - - default: - *value = 0; - break; - } -#endif /* !MALI_USE_CSF */ } else if (addr >= GET_GPU_CONTROL_REG(L2_FEATURES) && addr <= GET_GPU_CONTROL_REG(MMU_FEATURES)) { if (addr == GET_GPU_CONTROL_REG(L2_FEATURES)) @@ -2242,8 +1801,11 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) } else if ((addr >= MMU_STAGE1_REG(MMU_AS_REG(0, AS_TRANSTAB_LO))) && (addr <= MMU_STAGE1_REG(MMU_AS_REG(15, AS_STATUS)))) { - u32 mem_addr_space = (addr - MMU_STAGE1_REG(MMU_AS_REG(0, AS_TRANSTAB_LO))) >> - MMU_STAGE1_AS_SHIFT; + u32 mem_addr_space; + + mem_addr_space = (addr - MMU_STAGE1_REG(MMU_AS_REG(0, AS_TRANSTAB_LO))) >> + MMU_STAGE1_AS_SHIFT; + switch (addr & 0x3F) { case AS_TRANSTAB_LO: *value = (u32)(hw_error_status.as_transtab[mem_addr_space] & 0xffffffff); @@ -2289,7 +1851,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) *value = hw_error_status.mmu_irq_rawstat; } else if (addr == MMU_CONTROL_REG(MMU_IRQ_STATUS)) { *value = hw_error_status.mmu_irq_mask & hw_error_status.mmu_irq_rawstat; -#if MALI_USE_CSF } else if (addr == IPA_CONTROL_REG(STATUS) || addr == IPA_CONTROL_REG(STATUS) + GPU_GOV_IPA_CONTROL_OFFSET) { *value = (ipa_control_timer_enabled << 31); @@ -2382,7 +1943,6 @@ void midgard_model_read_reg(void *h, u32 addr, u32 *const value) *value = gpu_model_get_prfcnt_value(KBASE_IPA_CORE_TYPE_NEURAL, counter_index, is_low_word); -#endif /* MALI_USE_CSF */ } else if (addr == GET_GPU_CONTROL_REG(GPU_FEATURES_LO)) { *value = dummy->control_reg_values->gpu_features_lo; } else if (addr == GET_GPU_CONTROL_REG(GPU_FEATURES_HI)) { @@ -2473,13 +2033,8 @@ int gpu_model_set_dummy_prfcnt_user_sample(u32 __user *data, u32 size) } spin_lock_irqsave(&performance_counters.access_lock, flags); -#if !MALI_USE_CSF - offset = set_user_sample_core_type(performance_counters.jm_counters, user_data, offset, - size, 1); -#else offset = set_user_sample_core_type(performance_counters.cshw_counters, user_data, offset, size, 1); -#endif /* !MALI_USE_CSF */ offset = set_user_sample_core_type(performance_counters.tiler_counters, user_data, offset, size, hweight64(DUMMY_IMPLEMENTATION_TILER_PRESENT)); offset = set_user_sample_core_type(performance_counters.l2_counters, user_data, offset, @@ -2499,13 +2054,8 @@ void gpu_model_set_dummy_prfcnt_kernel_sample(u64 *data, u32 size) u32 offset = 0; spin_lock_irqsave(&performance_counters.access_lock, flags); -#if !MALI_USE_CSF - offset = set_kernel_sample_core_type(performance_counters.jm_counters, data, offset, size, - 1); -#else offset = set_kernel_sample_core_type(performance_counters.cshw_counters, data, offset, size, 1); -#endif /* !MALI_USE_CSF */ offset = set_kernel_sample_core_type(performance_counters.tiler_counters, data, offset, size, hweight64(DUMMY_IMPLEMENTATION_TILER_PRESENT)); offset = set_kernel_sample_core_type(performance_counters.l2_counters, data, offset, size, diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h index 115d31a6f560..c57c3020c51a 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h @@ -202,7 +202,6 @@ void gpu_model_set_dummy_prfcnt_cores(struct kbase_device *kbdev, u64 l2_present /* Clear the counter values array maintained by the dummy model */ void gpu_model_clear_prfcnt_values(void); -#if MALI_USE_CSF /** * gpu_model_prfcnt_dump_request() - Request performance counter sample dump. * @sample_buf: Pointer to KBASE_DUMMY_MODEL_MAX_VALUES_PER_SAMPLE sized array @@ -217,7 +216,6 @@ void gpu_model_prfcnt_dump_request(uint32_t *sample_buf, struct gpu_model_prfcnt * @model: Model pointer returned by midgard_model_create(). */ void gpu_model_glb_request_job_irq(void *model); -#endif /* MALI_USE_CSF */ extern struct error_status_t hw_error_status; diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_always_on.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_always_on.c index 37c35ee9bd32..12bb7448f619 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_always_on.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_always_on.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -67,9 +67,7 @@ const struct kbase_pm_policy kbase_pm_always_on_policy_ops = { always_on_get_core_active, /* get_core_active */ NULL, /* handle_event */ KBASE_PM_POLICY_ID_ALWAYS_ON, /* id */ -#if MALI_USE_CSF ALWAYS_ON_PM_SCHED_FLAGS, /* pm_sched_flags */ -#endif }; KBASE_EXPORT_TEST_API(kbase_pm_always_on_policy_ops); diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_backend.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_backend.c index a61809dd2fda..28665a8f1ee1 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_backend.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_backend.c @@ -29,20 +29,13 @@ #include #include -#if !MALI_USE_CSF -#include -#include -#include -#else #include #include #include #include -#endif /* !MALI_USE_CSF */ #include #include #include -#include #include @@ -99,9 +92,6 @@ void kbase_pm_register_access_enable(struct kbase_device *kbdev) if (callbacks) callbacks->power_on_callback(kbdev); - if (WARN_ON(kbase_io_is_aw_removed(kbdev))) - dev_err(kbdev->dev, "Attempting to power on while GPU lost\n"); - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_GPU_OFF); } @@ -124,6 +114,7 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) KBASE_DEBUG_ASSERT(kbdev != NULL); mutex_init(&kbdev->pm.lock); + kbdev->pm.runtime_suspend_result = 0; kbdev->pm.backend.gpu_poweroff_wait_wq = alloc_workqueue("kbase_pm_poweroff_wait", WQ_HIGHPRI | WQ_UNBOUND, 1); @@ -133,22 +124,17 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) INIT_WORK(&kbdev->pm.backend.gpu_poweroff_wait_work, kbase_pm_gpu_poweroff_wait_wq); kbdev->pm.backend.ca_cores_enabled = ~0ull; - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + kbdev->pm.backend.ca_gov_cores_enabled = ~0ull; + init_waitqueue_head(&kbdev->pm.backend.gpu_in_desired_state_wait); -#if !MALI_USE_CSF - /* Initialise the metrics subsystem */ - ret = kbasep_pm_metrics_init(kbdev); - if (ret) - return ret; -#else mutex_init(&kbdev->pm.backend.policy_change_lock); kbdev->pm.backend.policy_change_clamp_state_to_off = false; /* Due to dependency on kbase_ipa_control, the metrics subsystem can't * be initialized here. */ CSTD_UNUSED(ret); -#endif init_waitqueue_head(&kbdev->pm.backend.reset_done_wait); kbdev->pm.backend.reset_done = false; @@ -162,12 +148,10 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) init_waitqueue_head(&kbdev->pm.backend.poweroff_wait); -#if MALI_USE_CSF /* Select the power interface that the GPU is using. */ kbdev->pm.backend.has_host_pwr_iface = kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_POWER_CONTROL); kbdev->pm.backend.pwr_cntl_delegated = false; -#endif if (kbase_pm_ca_init(kbdev) != 0) goto workq_fail; @@ -181,24 +165,27 @@ int kbase_hwaccess_pm_init(struct kbase_device *kbdev) INIT_WORK(&kbdev->pm.backend.hwcnt_disable_work, kbase_pm_hwcnt_disable_worker); kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - kbdev->pm.backend.gpu_sleep_allowed = 0; - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GPU_SLEEP) && - !kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TURSEHW_1997) && - kbdev->pm.backend.callback_power_runtime_gpu_active && - kbdev->pm.backend.callback_power_runtime_gpu_idle) - set_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed); + if (IS_ENABLED(CONFIG_PM)) { + kbdev->pm.backend.gpu_sleep_allowed = 0; + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GPU_SLEEP) && + !kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TURSEHW_1997) && + kbdev->pm.backend.callback_power_runtime_gpu_active && + kbdev->pm.backend.callback_power_runtime_gpu_idle) + set_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed); - kbdev->pm.backend.apply_hw_issue_TITANHW_2938_wa = - kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TITANHW_2938) && - test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed); + kbdev->pm.backend.apply_hw_issue_TITANHW_2938_wa = + kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TITANHW_2938) && + test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, + &kbdev->pm.backend.gpu_sleep_allowed); - /* FW Sleep-on-Idle is only available in certain architecture revisions */ - if ((kbdev->gpu_props.gpu_id.arch_major > 11) || - ((kbdev->gpu_props.gpu_id.arch_major == 11) && - (kbdev->gpu_props.gpu_id.arch_minor >= 8) && (kbdev->gpu_props.gpu_id.arch_rev >= 10))) - set_bit(KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE, &kbdev->pm.backend.gpu_sleep_allowed); -#endif + /* FW Sleep-on-Idle is only available in certain architecture revisions */ + if ((kbdev->gpu_props.gpu_id.arch_major > 11) || + ((kbdev->gpu_props.gpu_id.arch_major == 11) && + (kbdev->gpu_props.gpu_id.arch_minor >= 8) && + (kbdev->gpu_props.gpu_id.arch_rev >= 10))) + set_bit(KBASE_GPU_SUPPORTS_FW_SLEEP_ON_IDLE, + &kbdev->pm.backend.gpu_sleep_allowed); + } if (IS_ENABLED(CONFIG_MALI_VALHALL_HW_ERRATA_1485982_NOT_AFFECTED)) return 0; @@ -225,9 +212,6 @@ pm_state_machine_fail: kbase_pm_policy_term(kbdev); kbase_pm_ca_term(kbdev); workq_fail: -#if !MALI_USE_CSF - kbasep_pm_metrics_term(kbdev); -#endif return -EINVAL; } @@ -259,7 +243,6 @@ void kbase_pm_do_poweron(struct kbase_device *kbdev, bool is_resume) */ } -#if MALI_USE_CSF static bool wait_cond_mmu_fault_handling_in_gpu_poweroff_wait_wq(struct kbase_device *kbdev, int faults_pending) { @@ -272,7 +255,6 @@ static bool wait_cond_mmu_fault_handling_in_gpu_poweroff_wait_wq(struct kbase_de return cond; } -#endif /** * wait_for_mmu_fault_handling_in_gpu_poweroff_wait() - Wait for pending MMU @@ -288,7 +270,6 @@ static bool wait_cond_mmu_fault_handling_in_gpu_poweroff_wait_wq(struct kbase_de */ static void wait_for_mmu_fault_handling_in_gpu_poweroff_wait(struct kbase_device *kbdev) { -#if MALI_USE_CSF bool reset_triggered = false; int ret = 0; @@ -318,19 +299,12 @@ static void wait_for_mmu_fault_handling_in_gpu_poweroff_wait(struct kbase_device } } while (ret); kbdev->pm.backend.waiting_for_mmu_fault_handling = false; -#else - kbase_pm_unlock(kbdev); - kbase_flush_mmu_wqs(kbdev); - kbase_pm_lock(kbdev); -#endif } static void pm_handle_power_off(struct kbase_device *kbdev) { struct kbase_pm_backend_data *backend = &kbdev->pm.backend; -#if MALI_USE_CSF enum kbase_mcu_state mcu_state; -#endif unsigned long flags; lockdep_assert_held(&kbdev->pm.lock); @@ -339,28 +313,24 @@ static void pm_handle_power_off(struct kbase_device *kbdev) return; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - if (kbdev->pm.backend.gpu_wakeup_override) { + + if (IS_ENABLED(CONFIG_PM) && kbdev->pm.backend.gpu_wakeup_override) { spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); return; } -#endif + WARN_ON(backend->shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF || backend->l2_state != KBASE_L2_OFF); -#if MALI_USE_CSF mcu_state = backend->mcu_state; WARN_ON(!kbase_pm_is_mcu_inactive(kbdev, mcu_state)); -#endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - if (backend->callback_power_runtime_gpu_idle) { + if (IS_ENABLED(CONFIG_PM) && backend->callback_power_runtime_gpu_idle) { WARN_ON(backend->gpu_idled); backend->callback_power_runtime_gpu_idle(kbdev); backend->gpu_idled = true; return; } -#endif /* Disable interrupts and turn the clock off */ if (unlikely(!kbase_pm_clock_off(kbdev))) { @@ -398,21 +368,12 @@ void kbase_pm_handle_gpu_poweroff_wait_work(struct kbase_device *kbdev) KBASE_KTRACE_ADD(kbdev, PM_POWEROFF_WAIT_WQ, NULL, 0); -#if !MALI_USE_CSF - /* Wait for power transitions to complete. We do this with no locks held - * so that we don't deadlock with any pending workqueues. - */ - kbase_pm_wait_for_desired_state(kbdev); -#endif - kbase_pm_lock(kbdev); -#if MALI_USE_CSF spin_lock_irqsave(&kbdev->hwaccess_lock, flags); if (pm->backend.invoke_poweroff_wait_wq_when_l2_off || !pm->backend.poweroff_wait_in_progress) goto wakeup_exit; spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#endif pm_handle_power_off(kbdev); @@ -421,18 +382,11 @@ void kbase_pm_handle_gpu_poweroff_wait_work(struct kbase_device *kbdev) if (backend->poweron_required) { backend->poweron_required = false; kbdev->pm.backend.l2_desired = true; -#if MALI_USE_CSF kbdev->pm.backend.mcu_desired = true; -#endif kbase_pm_update_state(kbdev); kbase_pm_update_cores_state_nolock(kbdev); -#if !MALI_USE_CSF - kbase_backend_slot_update(kbdev); -#endif /* !MALI_USE_CSF */ } -#if MALI_USE_CSF wakeup_exit: -#endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); kbase_pm_unlock(kbdev); wake_up(&kbdev->pm.backend.poweroff_wait); @@ -589,28 +543,20 @@ static void kbase_pm_hwcnt_disable_worker(struct work_struct *data) */ backend->hwcnt_disabled = true; kbase_pm_update_state(kbdev); -#if !MALI_USE_CSF - kbase_backend_slot_update(kbdev); -#endif /* !MALI_USE_CSF */ } else { /* PM state was updated while we were doing the disable, * so we need to undo the disable we just performed. */ -#if MALI_USE_CSF unsigned long lock_flags; kbase_csf_scheduler_spin_lock(kbdev, &lock_flags); -#endif kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); -#if MALI_USE_CSF kbase_csf_scheduler_spin_unlock(kbdev, lock_flags); -#endif } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) /** * kbase_pm_do_poweroff_sync - Do the synchronous power down of GPU * @@ -679,7 +625,6 @@ out: kbase_pm_unlock(kbdev); return ret; } -#endif void kbase_pm_do_poweroff(struct kbase_device *kbdev) { @@ -695,12 +640,7 @@ void kbase_pm_do_poweroff(struct kbase_device *kbdev) if (kbdev->pm.backend.poweroff_wait_in_progress) goto unlock_hwaccess; -#if MALI_USE_CSF kbdev->pm.backend.mcu_desired = false; -#else - /* Force all cores off */ - kbdev->pm.backend.shaders_desired = false; -#endif kbdev->pm.backend.l2_desired = false; kbdev->pm.backend.poweroff_wait_in_progress = true; @@ -744,7 +684,10 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, unsigned int flags) kbase_pm_unlock(kbdev); return ret; } -#if MALI_USE_CSF + + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + kbdev->pm.sysfs_gov_core_mask = kbdev->gpu_props.shader_present; + kbdev->pm.debug_core_mask = kbdev->gpu_props.shader_present; spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); /* Set the initial value for 'shaders_avail'. It would be later @@ -755,25 +698,19 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, unsigned int flags) */ kbdev->pm.backend.shaders_avail = kbase_pm_ca_get_core_mask(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); -#else - kbdev->pm.debug_core_mask_all = kbdev->pm.debug_core_mask[0] = - kbdev->pm.debug_core_mask[1] = kbdev->pm.debug_core_mask[2] = - kbdev->gpu_props.shader_present; -#endif /* Pretend the GPU is active to prevent a power policy turning the GPU * cores off */ kbdev->pm.active_count = 1; -#if MALI_USE_CSF && KBASE_PM_RUNTIME - if (kbdev->pm.backend.callback_power_runtime_gpu_active) { + + if (IS_ENABLED(CONFIG_PM) && kbdev->pm.backend.callback_power_runtime_gpu_active) { /* Take the RPM reference count to match with the internal * PM reference count */ kbdev->pm.backend.callback_power_runtime_gpu_active(kbdev); WARN_ON(kbdev->pm.backend.gpu_idled); } -#endif spin_lock_irqsave(&kbdev->pm.backend.gpu_cycle_counter_requests_lock, irq_flags); /* Ensure cycle counter is off */ @@ -790,12 +727,10 @@ int kbase_hwaccess_pm_powerup(struct kbase_device *kbdev, unsigned int flags) kbdev->pm.backend.gpu_ready = true; /* Turn on the GPU and any cores needed by the policy */ -#if MALI_USE_CSF /* Turn on the L2 caches, needed for firmware boot */ spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); kbdev->pm.backend.l2_desired = true; spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); -#endif kbase_pm_do_poweron(kbdev, false); kbase_pm_unlock(kbdev); @@ -806,15 +741,14 @@ void kbase_hwaccess_pm_halt(struct kbase_device *kbdev) { KBASE_DEBUG_ASSERT(kbdev != NULL); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - WARN_ON(kbase_pm_do_poweroff_sync(kbdev)); -#else - mutex_lock(&kbdev->pm.lock); - kbase_pm_do_poweroff(kbdev); - mutex_unlock(&kbdev->pm.lock); - - kbase_pm_wait_for_poweroff_work_complete(kbdev); -#endif + if (IS_ENABLED(CONFIG_PM)) + WARN_ON(kbase_pm_do_poweroff_sync(kbdev)); + else { + mutex_lock(&kbdev->pm.lock); + kbase_pm_do_poweroff(kbdev); + mutex_unlock(&kbdev->pm.lock); + kbase_pm_wait_for_poweroff_work_complete(kbdev); + } } KBASE_EXPORT_TEST_API(kbase_hwaccess_pm_halt); @@ -827,17 +761,12 @@ void kbase_hwaccess_pm_term(struct kbase_device *kbdev) cancel_work_sync(&kbdev->pm.backend.hwcnt_disable_work); - if (kbdev->pm.backend.hwcnt_disabled) { + if (kbdev->pm.backend.hwcnt_disabled && kbdev->csf.firmware_hctl_core_pwr) { unsigned long flags; -#if MALI_USE_CSF + kbase_csf_scheduler_spin_lock(kbdev, &flags); kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); kbase_csf_scheduler_spin_unlock(kbdev, flags); -#else - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#endif } /* Free any resources the policy allocated */ @@ -845,16 +774,11 @@ void kbase_hwaccess_pm_term(struct kbase_device *kbdev) kbase_pm_policy_term(kbdev); kbase_pm_ca_term(kbdev); -#if !MALI_USE_CSF - /* Shut down the metrics subsystem */ - kbasep_pm_metrics_term(kbdev); -#else if (WARN_ON(mutex_is_locked(&kbdev->pm.backend.policy_change_lock))) { mutex_lock(&kbdev->pm.backend.policy_change_lock); mutex_unlock(&kbdev->pm.backend.policy_change_lock); } mutex_destroy(&kbdev->pm.backend.policy_change_lock); -#endif destroy_workqueue(kbdev->pm.backend.gpu_poweroff_wait_wq); } @@ -866,48 +790,23 @@ void kbase_pm_power_changed(struct kbase_device *kbdev) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbase_pm_update_state(kbdev); -#if !MALI_USE_CSF - kbase_backend_slot_update(kbdev); -#endif /* !MALI_USE_CSF */ - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } -#if MALI_USE_CSF void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, u64 new_core_mask) { lockdep_assert_held(&kbdev->hwaccess_lock); lockdep_assert_held(&kbdev->pm.lock); - kbdev->pm.debug_core_mask = new_core_mask; - kbase_pm_update_dynamic_cores_onoff(kbdev); + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + kbdev->pm.sysfs_gov_core_mask = new_core_mask; + kbase_pm_ca_set_gov_core_mask_nolock(kbdev, SYSFS_COREMASK, new_core_mask); + } else { + kbdev->pm.debug_core_mask = new_core_mask; + kbase_pm_update_dynamic_cores_onoff(kbdev); + } } KBASE_EXPORT_TEST_API(kbase_pm_set_debug_core_mask); -#else -void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, u64 *new_core_mask, - size_t new_core_mask_size) -{ - size_t i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - lockdep_assert_held(&kbdev->pm.lock); - - if (kbase_dummy_job_wa_enabled(kbdev)) { - dev_warn_once( - kbdev->dev, - "Change of core mask not supported for slot 0 as dummy job WA is enabled"); - new_core_mask[0] = kbdev->pm.debug_core_mask[0]; - } - - kbdev->pm.debug_core_mask_all = 0; - for (i = 0; i < new_core_mask_size; i++) { - kbdev->pm.debug_core_mask[i] = new_core_mask[i]; - kbdev->pm.debug_core_mask_all |= new_core_mask[i]; - } - - kbase_pm_update_dynamic_cores_onoff(kbdev); -} -#endif /* MALI_USE_CSF */ void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev) { @@ -923,35 +822,23 @@ int kbase_hwaccess_pm_suspend(struct kbase_device *kbdev) { int ret = 0; -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - ret = kbase_pm_do_poweroff_sync(kbdev); - if (ret) - return ret; -#else - /* Force power off the GPU and all cores (regardless of policy), only - * after the PM active count reaches zero (otherwise, we risk turning it - * off prematurely) - */ - kbase_pm_lock(kbdev); + if (IS_ENABLED(CONFIG_PM)) { + ret = kbase_pm_do_poweroff_sync(kbdev); + if (ret) + return ret; + } else { + /* Force power off the GPU and all cores (regardless of policy), only + * after the PM active count reaches zero (otherwise, we risk turning it + * off prematurely) + */ + kbase_pm_lock(kbdev); + kbase_pm_do_poweroff(kbdev); + kbase_pm_unlock(kbdev); - kbase_pm_do_poweroff(kbdev); - -#if !MALI_USE_CSF - kbase_backend_timer_suspend(kbdev); -#endif /* !MALI_USE_CSF */ - - kbase_pm_unlock(kbdev); - - ret = kbase_pm_wait_for_poweroff_work_complete(kbdev); - if (ret) { -#if !MALI_USE_CSF - mutex_lock(&kbdev->js_data.runpool_mutex); - kbase_backend_timer_resume(kbdev); - mutex_unlock(&kbdev->js_data.runpool_mutex); -#endif /* !MALI_USE_CSF */ - return ret; + ret = kbase_pm_wait_for_poweroff_work_complete(kbdev); + if (ret) + return ret; } -#endif WARN_ON(kbase_io_is_gpu_powered(kbdev)); WARN_ON(atomic_read(&kbdev->faults_pending)); @@ -976,10 +863,6 @@ void kbase_hwaccess_pm_resume(struct kbase_device *kbdev) } kbase_pm_do_poweron(kbdev, true); -#if !MALI_USE_CSF - kbase_backend_timer_resume(kbdev); -#endif /* !MALI_USE_CSF */ - kbase_pm_unlock(kbdev); } @@ -995,24 +878,23 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev) return; } -#if MALI_USE_CSF - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - if (kbase_io_is_gpu_powered(kbdev) && !kbase_io_is_aw_removed(kbdev)) { + if (kbase_io_is_aw_removed(kbdev)) { unsigned long flags_sched; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* GPU is no longer mapped to VM. So no interrupts will * be received and Mali registers have been replaced by * dummy RAM */ - WARN(kbase_io_has_gpu(kbdev), "GPU is still available after GPU lost event\n"); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + kbase_csf_scheduler_spin_lock(kbdev, &flags_sched); if (atomic_read(&kbdev->hwaccess.backend.reset_gpu) != KBASE_RESET_GPU_NOT_PENDING) dev_warn(kbdev->dev, "GPU reset pending at the time of GPU lost event"); atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING); kbase_csf_scheduler_spin_unlock(kbdev, flags_sched); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); kbase_synchronize_irqs(kbdev); @@ -1030,60 +912,13 @@ void kbase_pm_handle_gpu_lost(struct kbase_device *kbdev) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbdev->protected_mode = false; kbase_pm_update_state(kbdev); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* Cancel any pending HWC dumps */ kbase_hwcnt_backend_csf_on_unrecoverable_error(&kbdev->hwcnt_gpu_iface); } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#else - /* Releasing the VM state lock here is safe because - * we are guaranteed to be in either STOPPING_IDLE, - * STOPPING_ACTIVE or SUSPEND_PENDING at this point. - * The only transitions that are valid from here are to - * STOPPED, STOPPED_GPU_REQUESTED or SUSPENDED which can - * only happen at the completion of the GPU lost handling. - */ - mutex_unlock(&arb_vm_state->vm_state_lock); - mutex_lock(&kbdev->pm.lock); - mutex_lock(&arb_vm_state->vm_state_lock); - if (kbase_io_is_gpu_powered(kbdev) && !kbase_io_is_aw_removed(kbdev)) { - ktime_t end_timestamp = ktime_get_raw(); - - /* GPU is no longer mapped to VM. So no interrupts will - * be received and Mali registers have been replaced by - * dummy RAM - */ - WARN(kbase_io_has_gpu(kbdev), "GPU is still available after GPU lost event\n"); - - /* Full GPU reset will have been done by hypervisor, so cancel */ - atomic_set(&kbdev->hwaccess.backend.reset_gpu, KBASE_RESET_GPU_NOT_PENDING); - hrtimer_cancel(&kbdev->hwaccess.backend.reset_timer); - - kbase_synchronize_irqs(kbdev); - - /* Clear all jobs running on the GPU */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbdev->protected_mode = false; - kbase_backend_reset(kbdev, &end_timestamp); - kbase_pm_metrics_update(kbdev, NULL); - kbase_pm_update_state(kbdev); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* Cancel any pending HWC dumps */ - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - if (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING || - kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_FAULT) { - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_FAULT; - kbdev->hwcnt.backend.triggered = 1; - wake_up(&kbdev->hwcnt.backend.wait); - } - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - } - mutex_unlock(&kbdev->pm.lock); -#endif /* MALI_USE_CSF */ } -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) int kbase_pm_force_mcu_wakeup_after_sleep(struct kbase_device *kbdev) { unsigned long flags; @@ -1108,17 +943,15 @@ static int pm_handle_mcu_sleep_on_runtime_suspend(struct kbase_device *kbdev) lockdep_assert_held(&kbdev->csf.scheduler.lock); lockdep_assert_held(&kbdev->pm.lock); -#ifdef CONFIG_MALI_VALHALL_DEBUG /* In case of no active CSG on slot, powering up L2 could be skipped and * proceed directly to suspend GPU. * ToDo: firmware has to be reloaded after wake-up as no halt command * has been sent when GPU was put to sleep mode. */ - if (!kbase_csf_scheduler_get_nr_active_csgs(kbdev)) + if (IS_ENABLED(CONFIG_MALI_VALHALL_DEBUG) && !kbase_csf_scheduler_get_nr_active_csgs(kbdev)) dev_info( kbdev->dev, "No active CSGs. Can skip the power up of L2 and go for suspension directly"); -#endif ret = kbase_pm_force_mcu_wakeup_after_sleep(kbdev); if (ret) { @@ -1300,5 +1133,3 @@ out: return ret; } - -#endif diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.c index 32c51152cbbd..27ab4162c325 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2013-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2013-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -27,19 +27,37 @@ #include #include #include -#include -int kbase_pm_ca_init(struct kbase_device *kbdev) -{ #ifdef CONFIG_MALI_VALHALL_DEVFREQ +static void pm_init_cores_enabled_mask(struct kbase_device *kbdev) +{ struct kbase_pm_backend_data *pm_backend = &kbdev->pm.backend; if (kbdev->current_core_mask) pm_backend->ca_cores_enabled = kbdev->current_core_mask; else pm_backend->ca_cores_enabled = kbdev->gpu_props.shader_present; +} + +static void pm_init_gov_cores_enabled_mask(struct kbase_device *kbdev) +{ + struct kbase_pm_backend_data *pm_backend = &kbdev->pm.backend; + + if (kbdev->current_core_mask) + pm_backend->ca_gov_cores_enabled = kbdev->current_core_mask; + else + pm_backend->ca_gov_cores_enabled = kbdev->gpu_props.shader_present; +} #endif +int kbase_pm_ca_init(struct kbase_device *kbdev) +{ +#ifdef CONFIG_MALI_VALHALL_DEVFREQ + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + pm_init_gov_cores_enabled_mask(kbdev); + + pm_init_cores_enabled_mask(kbdev); +#endif return 0; } @@ -48,61 +66,119 @@ void kbase_pm_ca_term(struct kbase_device *kbdev) CSTD_UNUSED(kbdev); } -#ifdef CONFIG_MALI_VALHALL_DEVFREQ -void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask) +void kbase_pm_ca_set_gov_core_mask_nolock(struct kbase_device *kbdev, enum mask_type core_mask_type, + u64 core_mask) { struct kbase_pm_backend_data *pm_backend = &kbdev->pm.backend; - unsigned long flags; -#if MALI_USE_CSF - u64 old_core_mask = 0; - bool mmu_sync_needed = false; - if (!IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) && - kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2019_3901)) { - mmu_sync_needed = true; - down_write(&kbdev->csf.mmu_sync_sem); + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + dev_warn( + kbdev->dev, + "This function requires Kbase to have access to GOV_CORE_MASK register, cannot proceed\n"); + return; + } + + lockdep_assert_held(&kbdev->hwaccess_lock); + + /** A value of ZERO means disabling. + * When disabling, store the last used mask for re-enabling + */ + if (core_mask_type == SYSFS_COREMASK) { + if (core_mask != 0) + pm_backend->ca_gov_cores_enabled = core_mask; + else +#ifdef CONFIG_MALI_VALHALL_DEVFREQ + pm_backend->ca_gov_cores_enabled = kbdev->current_core_mask; +#else + pm_backend->ca_gov_cores_enabled = + kbdev->gpu_props.curr_config.shader_present; +#endif + } +#ifdef CONFIG_MALI_VALHALL_DEVFREQ + /* sysfs core mask takes priority over OPP mask when sysfs core mask is set */ + else if (core_mask_type == DEVFREQ_COREMASK) { + if (core_mask == 0) { + dev_warn(kbdev->dev, + "Required core_mask cannot be zero when sysfs usage disabled\n"); + return; + } + /* if sysfs non-zero then no need to re-write value */ + if (kbdev->pm.sysfs_gov_core_mask) + return; + + pm_backend->ca_gov_cores_enabled = core_mask; } #endif - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + /** after all checks, write the to GOV_CORE_MASK register if GPU powered, + * otherwise value will be applied on next reboot. + */ + if (kbase_io_is_gpu_powered(kbdev)) + kbase_reg_write64(kbdev, GPU_GOVERNOR_ENUM(GOV_CORE_MASK), + pm_backend->ca_gov_cores_enabled); +} -#if MALI_USE_CSF - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { - if (kbase_io_is_gpu_powered(kbdev)) { - kbase_reg_write64(kbdev, GPU_GOVERNOR_ENUM(GOV_CORE_MASK), - core_mask & kbdev->pm.debug_core_mask); - } +void kbase_pm_ca_set_gov_core_mask(struct kbase_device *kbdev, enum mask_type core_mask_type, + u64 core_mask) +{ + unsigned long flags; - goto unlock; + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + dev_warn( + kbdev->dev, + "This function requires Kbase to have access to GOV_CORE_MASK register, cannot proceed\n"); + return; } + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_pm_ca_set_gov_core_mask_nolock(kbdev, core_mask_type, core_mask); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); +} + +#ifdef CONFIG_MALI_VALHALL_DEVFREQ + +static int set_core_mask_gov(struct kbase_device *kbdev, u64 core_mask) +{ + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + dev_warn( + kbdev->dev, + "This function requires Kbase to have access to GOV_CORE_MASK register, cannot proceed\n"); + return -EIO; + } + + /* Requires a validity check to ensure we don't try to set cores we do not have */ + if ((core_mask & kbdev->gpu_props.shader_present) != core_mask) { + dev_err(kbdev->dev, + "core_mask (%llu) must be a subset of the shader present (%llu)", core_mask, + kbdev->gpu_props.shader_present); + return -EINVAL; + } + + kbase_pm_ca_set_gov_core_mask(kbdev, DEVFREQ_COREMASK, core_mask); + + return 0; +} + +static int set_core_mask_legacy(struct kbase_device *kbdev, u64 core_mask) +{ + struct kbase_pm_backend_data *pm_backend = &kbdev->pm.backend; + u64 old_core_mask = 0; + unsigned long flags; + + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); if (!(core_mask & kbdev->pm.debug_core_mask)) { dev_err(kbdev->dev, - "OPP core mask 0x%llX does not intersect with debug mask 0x%llX\n", + "OPP core mask 0x%llX does not intersect with sysfs debug mask 0x%llX\n", core_mask, kbdev->pm.debug_core_mask); - goto unlock; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + return -EINVAL; } old_core_mask = pm_backend->ca_cores_enabled; -#else - if (!(core_mask & kbdev->pm.debug_core_mask_all)) { - dev_err(kbdev->dev, - "OPP core mask 0x%llX does not intersect with debug mask 0x%llX\n", - core_mask, kbdev->pm.debug_core_mask_all); - goto unlock; - } - - if (kbase_dummy_job_wa_enabled(kbdev)) { - dev_err_once(kbdev->dev, - "Dynamic core scaling not supported as dummy job WA is enabled"); - goto unlock; - } -#endif /* MALI_USE_CSF */ pm_backend->ca_cores_enabled = core_mask; kbase_pm_update_state(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF /* Check if old_core_mask contained the undesired cores and wait * for those cores to get powered down */ @@ -114,33 +190,51 @@ void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask) } } + return 0; +} + +void kbase_devfreq_set_core_mask(struct kbase_device *kbdev, u64 core_mask) +{ + bool mmu_sync_needed = false; + int err; + + if (!IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) && + kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2019_3901)) { + mmu_sync_needed = true; + down_write(&kbdev->csf.mmu_sync_sem); + } + + err = kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT) ? + set_core_mask_gov(kbdev, core_mask) : + set_core_mask_legacy(kbdev, core_mask); if (mmu_sync_needed) up_write(&kbdev->csf.mmu_sync_sem); -#endif - dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX\n", pm_backend->ca_cores_enabled); - - return; -unlock: - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF - if (mmu_sync_needed) - up_write(&kbdev->csf.mmu_sync_sem); -#endif + if (!err) + dev_dbg(kbdev->dev, "Devfreq policy : new core mask=%llX\n", core_mask); } KBASE_EXPORT_TEST_API(kbase_devfreq_set_core_mask); #endif u64 kbase_pm_ca_get_debug_core_mask(struct kbase_device *kbdev) { -#if MALI_USE_CSF return kbdev->pm.debug_core_mask; -#else - return kbdev->pm.debug_core_mask_all; -#endif } KBASE_EXPORT_TEST_API(kbase_pm_ca_get_debug_core_mask); +u64 kbase_pm_ca_get_sysfs_gov_core_mask(struct kbase_device *kbdev) +{ + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + dev_warn( + kbdev->dev, + "This function requires Kbase to have access to GOV_CORE_MASK register, cannot proceed\n"); + return 0; + } + + return kbdev->pm.sysfs_gov_core_mask; +} +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_sysfs_gov_core_mask); + u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev) { u64 debug_core_mask = kbase_pm_ca_get_debug_core_mask(kbdev); @@ -160,18 +254,23 @@ u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev) return kbdev->gpu_props.curr_config.shader_present & debug_core_mask; #endif } - KBASE_EXPORT_TEST_API(kbase_pm_ca_get_core_mask); +u64 kbase_pm_ca_get_gov_core_mask(struct kbase_device *kbdev) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + return kbdev->pm.backend.ca_gov_cores_enabled; +} +KBASE_EXPORT_TEST_API(kbase_pm_ca_get_gov_core_mask); + u64 kbase_pm_ca_get_instr_core_mask(struct kbase_device *kbdev) { lockdep_assert_held(&kbdev->hwaccess_lock); #if IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) return (((1ull) << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1); -#elif MALI_USE_CSF - return kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); #else - return kbdev->pm.backend.pm_shaders_core_mask; + return kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); #endif } diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.h index 37d1020e28ff..8c55252a1a37 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_ca.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -68,6 +68,26 @@ u64 kbase_pm_ca_get_core_mask(struct kbase_device *kbdev); */ u64 kbase_pm_ca_get_debug_core_mask(struct kbase_device *kbdev); +/** + * kbase_pm_ca_get_sysfs_gov_core_mask - Get the value sysfs has requested to set shader core mask + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This is used only when Kbase has access to the GOV_CORE_MASK register. + * Return: The bit mask of user-selected cores + */ +u64 kbase_pm_ca_get_sysfs_gov_core_mask(struct kbase_device *kbdev); + +/** + * kbase_pm_ca_get_gov_core_mask - Get currently available gov core mask. + * + * @kbdev: The kbase device structure for the device (must be a valid pointer) + * + * This is used only when Kbase has access to the GOV_CORE_MASK register. + * Return: a mask of the currently available shader cores. + */ +u64 kbase_pm_ca_get_gov_core_mask(struct kbase_device *kbdev); + /** * kbase_pm_ca_update_core_status - Update core status * diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_coarse_demand.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_coarse_demand.c index cd2d65b1e4bc..d9e2432b9ef7 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_coarse_demand.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_coarse_demand.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -59,9 +59,7 @@ const struct kbase_pm_policy kbase_pm_coarse_demand_policy_ops = { coarse_demand_get_core_active, /* get_core_active */ NULL, /* handle_event */ KBASE_PM_POLICY_ID_COARSE_DEMAND, /* id */ -#if MALI_USE_CSF COARSE_ON_DEMAND_PM_SCHED_FLAGS, /* pm_sched_flags */ -#endif }; KBASE_EXPORT_TEST_API(kbase_pm_coarse_demand_policy_ops); diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_defs.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_defs.h index 67ce9d48656b..0c9ec908d4b4 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_defs.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_defs.h @@ -31,10 +31,6 @@ #include -#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM) -#define KBASE_PM_RUNTIME 1 -#endif - /* Forward definition - see mali_kbase.h */ struct kbase_device; struct kbase_jd_atom; @@ -61,7 +57,6 @@ struct kbase_jd_atom; * * They specify which type of core should be acted on. */ -#if MALI_USE_CSF enum kbase_pm_core_type { KBASE_PM_CORE_L2 = HOST_POWER_ENUM(L2_PRESENT), KBASE_PM_CORE_SHADER = HOST_POWER_ENUM(SHADER_PRESENT), @@ -76,14 +71,6 @@ enum kbase_pm_core_type { */ KBASE_PM_CORE_BASE = HOST_POWER_ENUM(BASE_PRESENT) }; -#else -enum kbase_pm_core_type { - KBASE_PM_CORE_L2 = GPU_CONTROL_ENUM(L2_PRESENT), - KBASE_PM_CORE_SHADER = GPU_CONTROL_ENUM(SHADER_PRESENT), - KBASE_PM_CORE_TILER = GPU_CONTROL_ENUM(TILER_PRESENT), - KBASE_PM_CORE_STACK = GPU_CONTROL_ENUM(STACK_PRESENT) -}; -#endif /* * enum kbase_l2_core_state - The states used for the L2 cache & tiler power @@ -95,7 +82,6 @@ enum kbase_l2_core_state { #undef KBASEP_L2_STATE }; -#if MALI_USE_CSF /* * enum kbase_mcu_state - The states used for the MCU state machine. */ @@ -104,7 +90,6 @@ enum kbase_mcu_state { #include "mali_kbase_pm_mcu_states.h" #undef KBASEP_MCU_STATE }; -#endif /* * enum kbase_shader_core_state - The states used for the shaders' state machine. @@ -163,22 +148,11 @@ enum kbase_pm_runtime_suspend_abort_reason { * time_period_start timestamp, measured in units of 256ns. * @time_in_protm: The amount of time the GPU has spent in protected mode since * the time_period_start timestamp, measured in units of 256ns. - * @busy_cl: the amount of time the GPU was busy executing CL jobs. Note that - * if two CL jobs were active for 256ns, this value would be updated - * with 2 (2x256ns). - * @busy_gl: the amount of time the GPU was busy executing GL jobs. Note that - * if two GL jobs were active for 256ns, this value would be updated - * with 2 (2x256ns). */ struct kbasep_pm_metrics { u32 time_busy; u32 time_idle; -#if MALI_USE_CSF u32 time_in_protm; -#else - u32 busy_cl[2]; - u32 busy_gl; -#endif }; /** @@ -189,11 +163,6 @@ struct kbasep_pm_metrics { * kbase_ipa_control client * @skip_gpu_active_sanity_check: Decide whether to skip GPU_ACTIVE sanity * check in DVFS utilisation calculation - * @gpu_active: true when the GPU is executing jobs. false when - * not. Updated when the job scheduler informs us a job in submitted - * or removed from a GPU slot. - * @active_cl_ctx: number of CL jobs active on the GPU. Array is per-device. - * @active_gl_ctx: number of GL jobs active on the GPU. Array is per-slot. * @lock: spinlock protecting the kbasep_pm_metrics_state structure * @platform_data: pointer to data controlled by platform specific code * @kbdev: pointer to kbase device for which metrics are collected @@ -209,14 +178,8 @@ struct kbasep_pm_metrics { */ struct kbasep_pm_metrics_state { ktime_t time_period_start; -#if MALI_USE_CSF void *ipa_control_client; bool skip_gpu_active_sanity_check; -#else - bool gpu_active; - u32 active_cl_ctx[2]; - u32 active_gl_ctx[3]; -#endif spinlock_t lock; void *platform_data; @@ -336,6 +299,8 @@ union kbase_pm_policy_data { * called previously. * See &struct kbase_pm_callback_conf. * @ca_cores_enabled: Cores that are currently available + * @ca_gov_cores_enabled: Final value used for setting GOV_CORE_MASK register. + * Depends on sysfs-core-mask and devfreq-core-mask. * @apply_hw_issue_TITANHW_2938_wa: Indicates if the workaround for KBASE_HW_ISSUE_TITANHW_2938 * needs to be applied when unmapping memory from GPU. * @mcu_state: The current state of the micro-control unit, only applicable @@ -421,20 +386,6 @@ union kbase_pm_policy_data { * re-enabled whilst the flag is set. * @in_reset: True if a GPU is resetting and normal power manager operation is * suspended - * @partial_shaderoff: True if we want to partial power off shader cores, - * it indicates a partial shader core off case, - * do some special operation for such case like flush - * L2 cache because of GPU2017-861 - * @protected_entry_transition_override : True if GPU reset is being used - * before entering the protected mode and so - * the reset handling behaviour is being - * overridden. - * @protected_transition_override : True if a protected mode transition is in - * progress and is overriding power manager - * behaviour. - * @protected_l2_override : Non-zero if the L2 cache is required during a - * protected mode transition. Has no effect if not - * transitioning. * @hwcnt_desired: True if we want GPU hardware counters to be enabled. * @hwcnt_disabled: True if GPU hardware counters are not enabled. * @hwcnt_disable_work: Work item to disable GPU hardware counters, used if @@ -456,6 +407,7 @@ union kbase_pm_policy_data { * @gpu_clock_control_work: work item to set GPU clock during L2 power cycle * using gpu_clock_control * @reset_in_progress: Set if reset is ongoing, otherwise set to 0 + * @gpu_lost_pending: Set if GPU_LOST is detected and its handling is pending. * * This structure contains data for the power management framework. There is one * instance of this structure per device in the system. @@ -508,16 +460,14 @@ struct kbase_pm_backend_data { void (*callback_power_runtime_gpu_active)(struct kbase_device *kbdev); u64 ca_cores_enabled; + u64 ca_gov_cores_enabled; -#if MALI_USE_CSF bool apply_hw_issue_TITANHW_2938_wa; enum kbase_mcu_state mcu_state; -#endif enum kbase_l2_core_state l2_state; enum kbase_shader_core_state shaders_state; u64 shaders_avail; u64 shaders_desired_mask; -#if MALI_USE_CSF bool mcu_desired; bool policy_change_clamp_state_to_off; bool waiting_for_mmu_fault_handling; @@ -525,8 +475,6 @@ struct kbase_pm_backend_data { struct mutex policy_change_lock; struct workqueue_struct *core_idle_wq; struct work_struct core_idle_work; - -#ifdef KBASE_PM_RUNTIME unsigned long gpu_sleep_allowed; bool gpu_sleep_mode_active; bool exit_gpu_sleep_mode; @@ -534,7 +482,6 @@ struct kbase_pm_backend_data { bool gpu_wakeup_override; bool db_mirror_interrupt_enabled; enum kbase_pm_runtime_suspend_abort_reason runtime_suspend_abort_reason; -#endif /** * @has_host_pwr_iface: GPU supports the host power control interface. @@ -547,21 +494,12 @@ struct kbase_pm_backend_data { */ bool pwr_cntl_delegated; bool l2_force_off_after_mcu_halt; -#endif bool l2_desired; bool l2_always_on; bool shaders_desired; bool in_reset; -#if !MALI_USE_CSF - bool partial_shaderoff; - - bool protected_entry_transition_override; - bool protected_transition_override; - int protected_l2_override; -#endif - bool hwcnt_desired; bool hwcnt_disabled; struct work_struct hwcnt_disable_work; @@ -573,9 +511,10 @@ struct kbase_pm_backend_data { struct work_struct gpu_clock_control_work; atomic_t reset_in_progress; + + bool gpu_lost_pending; }; -#if MALI_USE_CSF /* CSF PM flag, signaling that the MCU shader Core should be kept on */ #define CSF_DYNAMIC_PM_CORE_KEEP_ON (1 << 0) /* CSF PM flag, signaling no scheduler suspension on idle groups */ @@ -591,7 +530,6 @@ struct kbase_pm_backend_data { #if !MALI_CUSTOMER_RELEASE #define ALWAYS_ON_DEMAND_PM_SCHED_FLAGS (CSF_DYNAMIC_PM_SCHED_IGNORE_IDLE) #endif -#endif /* List of policy IDs */ enum kbase_pm_policy_id { @@ -714,14 +652,12 @@ struct kbase_pm_policy { enum kbase_pm_policy_id id; -#if MALI_USE_CSF /* Policy associated with CSF PM scheduling operational flags. * There are pre-defined required flags exist for each of the * ARM released policies, such as 'always_on', 'coarse_demand' * and etc. */ unsigned int pm_sched_flags; -#endif }; #endif /* _KBASE_PM_HWACCESS_DEFS_H_ */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_driver.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_driver.c index 9547c4ca6b17..018d2699c1ac 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_driver.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_driver.c @@ -32,11 +32,7 @@ #include #include -#if MALI_USE_CSF #include -#else -#include -#endif /* !MALI_USE_CSF */ #include #include @@ -47,12 +43,9 @@ #include #include #include -#include #include -#if MALI_USE_CSF #include -#endif #include @@ -110,7 +103,6 @@ static u64 kbase_pm_get_state(struct kbase_device *kbdev, enum kbase_pm_core_typ static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev); -#if MALI_USE_CSF static bool pwr_status_gpu_reset_allowed(struct kbase_device *kbdev) { @@ -173,107 +165,26 @@ bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev) if (kbase_pm_no_mcu_core_pwroff(kbdev) && kbdev->pm.backend.l2_desired) return true; -#ifdef KBASE_PM_RUNTIME - if (kbdev->pm.backend.gpu_wakeup_override || - kbdev->pm.backend.runtime_suspend_abort_reason != ABORT_REASON_NONE) - return true; -#endif + if (IS_ENABLED(CONFIG_PM)) { + return kbdev->pm.backend.gpu_wakeup_override || + kbdev->pm.backend.runtime_suspend_abort_reason != ABORT_REASON_NONE; + } return false; } -#endif /* MALI_USE_CSF */ bool kbase_pm_is_l2_desired(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - if (kbdev->pm.backend.protected_entry_transition_override) - return false; - - if (kbdev->pm.backend.protected_transition_override && - kbdev->pm.backend.protected_l2_override) - return true; - - if (kbdev->pm.backend.protected_transition_override && !kbdev->pm.backend.shaders_desired) - return false; -#else if (unlikely(kbdev->pm.backend.policy_change_clamp_state_to_off)) return false; /* Power up the L2 cache only when MCU is desired */ if (likely(kbdev->csf.firmware_inited)) return kbase_pm_is_mcu_desired(kbdev); -#endif return kbdev->pm.backend.l2_desired; } -#if !MALI_USE_CSF -void kbase_pm_protected_override_enable(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - kbdev->pm.backend.protected_transition_override = true; -} -void kbase_pm_protected_override_disable(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - kbdev->pm.backend.protected_transition_override = false; -} - -int kbase_pm_protected_entry_override_enable(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - WARN_ON(!kbdev->protected_mode_transition); - - if (kbdev->pm.backend.l2_always_on && (kbdev->system_coherency == COHERENCY_ACE)) { - WARN_ON(kbdev->pm.backend.protected_entry_transition_override); - - /* - * If there is already a GPU reset pending then wait for it to - * complete before initiating a special reset for protected - * mode entry. - */ - if (kbase_reset_gpu_silent(kbdev)) - return -EAGAIN; - - kbdev->pm.backend.protected_entry_transition_override = true; - } - - return 0; -} - -void kbase_pm_protected_entry_override_disable(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - WARN_ON(!kbdev->protected_mode_transition); - - if (kbdev->pm.backend.l2_always_on && (kbdev->system_coherency == COHERENCY_ACE)) { - WARN_ON(!kbdev->pm.backend.protected_entry_transition_override); - - kbdev->pm.backend.protected_entry_transition_override = false; - } -} - -void kbase_pm_protected_l2_override(struct kbase_device *kbdev, bool override) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (override) { - kbdev->pm.backend.protected_l2_override++; - WARN_ON(kbdev->pm.backend.protected_l2_override <= 0); - } else { - kbdev->pm.backend.protected_l2_override--; - WARN_ON(kbdev->pm.backend.protected_l2_override < 0); - } - - kbase_pm_update_state(kbdev); -} -#endif - -#if MALI_USE_CSF #define ACTION_TYPE_TO_REG_HOST_POWER(core_name) \ { \ switch (action) { \ @@ -299,7 +210,6 @@ void kbase_pm_protected_l2_override(struct kbase_device *kbdev, bool override) break; \ } \ } -#endif #define ACTION_TYPE_TO_REG_GPU_CONTROL(core_name) \ { \ @@ -348,7 +258,6 @@ static u32 core_type_to_reg(struct kbase_device *kbdev, enum kbase_pm_core_type { u32 reg = 0x0; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { switch (core_type) { case KBASE_PM_CORE_L2: @@ -392,9 +301,7 @@ static u32 core_type_to_reg(struct kbase_device *kbdev, enum kbase_pm_core_type dev_err(kbdev->dev, "Invalid core type for host power control"); break; } - } else -#endif - { + } else { switch (core_type) { case KBASE_PM_CORE_L2: ACTION_TYPE_TO_REG_GPU_CONTROL(L2); @@ -438,75 +345,6 @@ static u32 core_type_to_reg(struct kbase_device *kbdev, enum kbase_pm_core_type return reg; } -#if !MALI_USE_CSF -/** - * map_core_type_to_tl_pm_state - Map core type to TL_PM_STATE. - * - * @kbdev: The kbase device for the core - * @core_type: The type of core - * - * Given a core_type (defined by kbase_pm_core_type) this function will return - * TL_PM_STATE_*, which is a mapping of core_type to respective core type timeline value. - * - * Return: Core type timeline value. - */ -__pure static u32 map_core_type_to_tl_pm_state(struct kbase_device *kbdev, - enum kbase_pm_core_type core_type) -{ - u32 map = 0; - - switch (core_type) { - case KBASE_PM_CORE_L2: - map = TL_PM_STATE_L2; - break; - case KBASE_PM_CORE_SHADER: - map = TL_PM_STATE_SHADER; - break; - case KBASE_PM_CORE_TILER: - map = TL_PM_STATE_TILER; - break; - case KBASE_PM_CORE_STACK: - if (corestack_driver_control) - map = TL_PM_STATE_STACK; - break; - default: - dev_err(kbdev->dev, "Invalid core type"); - } - - /* Core stack might not change default value */ - WARN_ON(!map); - return map; -} -#endif - -#if IS_ENABLED(CONFIG_ARM64) && !MALI_USE_CSF - -static void mali_cci_flush_l2(struct kbase_device *kbdev) -{ - u32 val; - const u32 mask = CLEAN_CACHES_COMPLETED | RESET_COMPLETED; - const u32 timeout_us = - kbase_get_timeout_ms(kbdev, KBASE_CLEAN_CACHE_TIMEOUT) * USEC_PER_MSEC; - - /* - * Note that we don't take the cache flush mutex here since - * we expect to be the last user of the L2, all other L2 users - * would have dropped their references, to initiate L2 power - * down, L2 power down being the only valid place for this - * to be called from. - */ - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), GPU_COMMAND_CACHE_CLN_INV_L2); - - /* Wait for cache flush to complete before continuing, exit on - * gpu resets or loop expiry. - */ - kbase_reg_poll32_timeout(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_RAWSTAT), val, val & mask, 0, - timeout_us, false); -} -#endif - -#if MALI_USE_CSF /** * pwr_cmd_constructor - Construct an on or off power command for a core type. * @@ -563,7 +401,6 @@ static u64 pwr_cmd_constructor(struct kbase_device *kbdev, enum kbase_pm_core_ty return pwr_cmd; } -#endif /* MALI_USE_CSF */ /** * kbase_pm_invoke - Invokes an action on a core set @@ -585,20 +422,6 @@ static void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type reg = core_type_to_reg(kbdev, core_type, action); -#if !MALI_USE_CSF - if (cores) { - u64 state = kbase_pm_get_state(kbdev, core_type, ACTION_READY); - - if (action == ACTION_PWRON) - state |= cores; - else if (action == ACTION_PWROFF) - state &= ~cores; - - KBASE_TLSTREAM_AUX_PM_STATE(kbdev, map_core_type_to_tl_pm_state(kbdev, core_type), - state); - } - -#endif /* Tracing */ if (cores) { if (action == ACTION_PWRON) @@ -612,11 +435,9 @@ static void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type case KBASE_PM_CORE_L2: KBASE_KTRACE_ADD(kbdev, PM_PWRON_L2, NULL, cores); break; -#if MALI_USE_CSF case KBASE_PM_CORE_NEURAL: KBASE_KTRACE_ADD(kbdev, PM_PWRON_NEURAL, NULL, cores); break; -#endif default: break; } @@ -633,23 +454,15 @@ static void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type /* disable snoops before L2 is turned off */ kbase_pm_cache_snoop_disable(kbdev); break; -#if MALI_USE_CSF case KBASE_PM_CORE_NEURAL: KBASE_KTRACE_ADD(kbdev, PM_PWROFF_NEURAL, NULL, cores); break; -#endif default: break; } } - if (kbase_dummy_job_wa_enabled(kbdev) && action == ACTION_PWRON && - core_type == KBASE_PM_CORE_SHADER && - !(kbdev->dummy_job_wa.flags & KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER)) { - kbase_dummy_job_wa_execute(kbdev, cores); - } -#if MALI_USE_CSF - else if (kbdev->pm.backend.has_host_pwr_iface) { + if (kbdev->pm.backend.has_host_pwr_iface) { kbase_reg_write64(kbdev, reg, cores); if (reg == HOST_POWER_ENUM(PWR_CMDARG)) { @@ -657,9 +470,7 @@ static void kbase_pm_invoke(struct kbase_device *kbdev, enum kbase_pm_core_type kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_COMMAND), pwr_cmd); } - } -#endif /* MALI_USE_CSF */ - else + } else kbase_reg_write64(kbdev, reg, cores); } @@ -707,12 +518,10 @@ u64 kbase_pm_get_present_cores(struct kbase_device *kbdev, enum kbase_pm_core_ty return kbdev->gpu_props.tiler_present; case KBASE_PM_CORE_STACK: return kbdev->gpu_props.stack_present; -#if MALI_USE_CSF case KBASE_PM_CORE_NEURAL: return kbdev->gpu_props.neural_present; case KBASE_PM_CORE_BASE: return kbdev->gpu_props.base_present; -#endif default: break; } @@ -782,11 +591,9 @@ u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type case KBASE_PM_CORE_L2: KBASE_KTRACE_ADD(kbdev, PM_CORES_POWERED_L2, NULL, result); break; -#if MALI_USE_CSF case KBASE_PM_CORE_NEURAL: KBASE_KTRACE_ADD(kbdev, PM_CORES_POWERED_NEURAL, NULL, result); break; -#endif default: break; } @@ -823,13 +630,11 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev) if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_L2_CONFIG)) return; -#if MALI_USE_CSF if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PBHA_HWU)) { val = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG)); kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(L2_CONFIG), L2_CONFIG_PBHA_HWU_SET(val, kbdev->pbha_propagate_bits)); } -#endif /* MALI_USE_CSF */ /* * Skip if size and hash are not given explicitly, @@ -851,7 +656,6 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev) val &= ~L2_CONFIG_HASH_MASK; val |= (kbdev->l2_hash_override << L2_CONFIG_HASH_SHIFT); } else if (kbdev->l2_hash_values_override) { -#if MALI_USE_CSF uint i; WARN_ON(!kbase_hw_has_l2_slice_hash_feature(kbdev)); @@ -869,7 +673,6 @@ static void kbase_pm_l2_config_override(struct kbase_device *kbdev) kbase_reg_write32(kbdev, GPU_L2_SLICE_HASH_OFFSET(i), kbdev->l2_hash_values[i]); } -#endif /* MALI_USE_CSF */ } dev_dbg(kbdev->dev, "Program 0x%x to L2_CONFIG\n", val); @@ -885,7 +688,6 @@ static void kbase_pm_control_gpu_clock(struct kbase_device *kbdev) queue_work(system_wq, &backend->gpu_clock_control_work); } -#if MALI_USE_CSF static const char *kbase_mcu_state_to_string(enum kbase_mcu_state state) { const char *const strings[] = { @@ -951,8 +753,6 @@ bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, enum kbase_mcu_state s return ((state == KBASE_MCU_OFF) || (state == KBASE_MCU_IN_SLEEP)); } -#ifdef KBASE_PM_RUNTIME - void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev) { u32 val = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL)); @@ -1052,7 +852,6 @@ static void wait_mcu_as_inactive(struct kbase_device *kbdev) if (kbase_prepare_to_reset_gpu(kbdev, 0)) kbase_reset_gpu(kbdev); } -#endif /** * kbasep_pm_toggle_power_interrupt - Toggles the IRQ mask for power interrupts @@ -1072,14 +871,12 @@ static void kbasep_pm_toggle_power_interrupt(struct kbase_device *kbdev, bool en lockdep_assert_held(&kbdev->hwaccess_lock); -#if MALI_USE_CSF /* No toggling is needed when Host control power interface is there, as PM actions * done by the firmware for Tiler, shader, neural won't generate the POWER_CHANGED * irq on Host side. */ if (kbdev->pm.backend.has_host_pwr_iface) return; -#endif irq_mask = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)); @@ -1093,7 +890,6 @@ static void kbasep_pm_toggle_power_interrupt(struct kbase_device *kbdev, bool en kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), irq_mask); } -#if MALI_USE_CSF /** * hctl_neural_engines_active - Check the neural engines are active * @@ -1212,9 +1008,7 @@ static bool hctl_base_power_down_done(struct kbase_device *kbdev, u64 shaders_re return (!base_trans && base_ready == shaders_ready); } -#endif /* MALI_USE_CSF */ -#if MALI_USE_CSF /** * hctl_shader_cores_active - Check the shader cores are active * @@ -1334,7 +1128,6 @@ static bool hctl_cores_power_down_done(struct kbase_device *kbdev, u64 cores_rea { return (!cores_trans && (cores_ready == cores_avail)); } -#endif /* MALI_USE_CSF */ static void disable_gpu_idle_timer_no_db(struct kbase_device *kbdev) { @@ -1392,16 +1185,20 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) bases_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_BASE); } /* This check mirrors the check inside kbase_pm_l2_update_state(). */ + if (unlikely(!kbase_io_has_gpu(kbdev))) { - backend->hwcnt_desired = false; - if (!backend->hwcnt_disabled) { - backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE; - KBASE_KTRACE_ADD(kbdev, PM_MCU_ON_HWCNT_DISABLE, NULL, - backend->mcu_state); - kbase_pm_trigger_hwcnt_disable(kbdev); + if (kbdev->csf.firmware_hctl_core_pwr) { + backend->hwcnt_desired = false; + if (!backend->hwcnt_disabled) { + backend->mcu_state = KBASE_MCU_ON_HWCNT_DISABLE; + KBASE_KTRACE_ADD(kbdev, PM_MCU_ON_HWCNT_DISABLE, NULL, + backend->mcu_state); + kbase_pm_trigger_hwcnt_disable(kbdev); + } } - if (backend->hwcnt_disabled && (backend->mcu_state != KBASE_MCU_OFF)) { + if (backend->mcu_state != KBASE_MCU_OFF && + (backend->hwcnt_disabled || !kbdev->csf.firmware_hctl_core_pwr)) { backend->mcu_state = KBASE_MCU_OFF; KBASE_KTRACE_ADD(kbdev, PM_MCU_OFF, NULL, backend->mcu_state); dev_dbg(kbdev->dev, "GPU lost has occurred - MCU off"); @@ -1520,20 +1317,22 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) break; case KBASE_MCU_ON_HWCNT_ENABLE: - backend->hwcnt_desired = true; - if (backend->hwcnt_disabled) { - unsigned long flags; + /* This state is only needed for the case of the shader power control + * under Host. + * HWCNT is left enabled throughout MCU power cycles in the opposite case. + */ + if (kbdev->csf.firmware_hctl_core_pwr) { + backend->hwcnt_desired = true; + if (backend->hwcnt_disabled) { + unsigned long flags; - kbase_csf_scheduler_spin_lock(kbdev, &flags); - kbase_hwcnt_backend_csf_set_hw_availability( - &kbdev->hwcnt_gpu_iface, - kbdev->gpu_props.curr_config.l2_slices, - kbdev->gpu_props.curr_config.shader_present, - kbdev->pm.debug_core_mask); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbase_csf_scheduler_spin_unlock(kbdev, flags); - backend->hwcnt_disabled = false; + kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, flags); + backend->hwcnt_disabled = false; + } } + backend->mcu_state = KBASE_MCU_ON; break; @@ -1547,6 +1346,28 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) backend->hwcnt_desired = false; if (!backend->hwcnt_disabled) kbase_pm_trigger_hwcnt_disable(kbdev); + + /* WA to avoid a double call to + * kbase_hwcnt_backend_csf_on_after_mcu_on. + * If MCU reload hasn't been triggered yet, + * firmware_reloaded will be set to false. This will lead to + * a call to kbase_csf_firmware_reload_completed() on the + * following FW global IRQ. This call should be a no-op. + * However, HWC needs a MCU_OFF notification here to pair up + * with the first MCU_ON call made during initial FW boot. + * + * Note: On NO_MALI, there is no call to + * kbase_hwcnt_backend_csf_on_after_mcu_on during + * firmware init. First call is made on + * kbase_csf_firmware_reload_completed() during the first + * FW global IRQ. Hence, there is no need to pair up the + * MCU power state notifications to HWC. + */ + if (!IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) && + !kbdev->csf.firmware_reloaded) + kbase_hwcnt_backend_csf_on_after_mcu_off( + &kbdev->hwcnt_gpu_iface); + backend->mcu_state = KBASE_MCU_HCTL_MCU_ON_RECHECK; } } else if (kbase_pm_handle_mcu_core_attr_update(kbdev)) @@ -1566,7 +1387,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) case KBASE_MCU_HCTL_MCU_ON_RECHECK: backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev); - + WARN_ON(!kbdev->csf.firmware_hctl_core_pwr); if (!backend->hwcnt_disabled) { /* Wait for being disabled */ ; @@ -1640,17 +1461,16 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; break; } + if (kbdev->csf.firmware_hctl_core_pwr) { + backend->hwcnt_desired = false; + if (!backend->hwcnt_disabled) + kbase_pm_trigger_hwcnt_disable(kbdev); + } - backend->hwcnt_desired = false; - if (!backend->hwcnt_disabled) - kbase_pm_trigger_hwcnt_disable(kbdev); - - if (backend->hwcnt_disabled) { -#ifdef KBASE_PM_RUNTIME - if (backend->gpu_sleep_mode_active) + if (backend->hwcnt_disabled || !kbdev->csf.firmware_hctl_core_pwr) { + if (IS_ENABLED(CONFIG_PM) && backend->gpu_sleep_mode_active) backend->mcu_state = KBASE_MCU_ON_SLEEP_INITIATE; else { -#endif backend->mcu_state = KBASE_MCU_ON_HALT; #if IS_ENABLED(CONFIG_MALI_VALHALL_CORESIGHT) kbase_debug_coresight_csf_state_request( @@ -1706,6 +1526,9 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) if (kbase_csf_firmware_mcu_halt_req_complete(kbdev)) { KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_HALTED, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); + + kbase_hwcnt_backend_csf_on_after_mcu_off(&kbdev->hwcnt_gpu_iface); + if (kbdev->csf.firmware_hctl_core_pwr) backend->mcu_state = KBASE_MCU_HCTL_SHADERS_READY_OFF; else @@ -1766,7 +1589,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) kbasep_pm_toggle_power_interrupt(kbdev, true); backend->mcu_state = KBASE_MCU_OFF; break; -#ifdef KBASE_PM_RUNTIME + case KBASE_MCU_ON_SLEEP_INITIATE: if (!kbase_pm_is_mcu_desired(kbdev)) handle_sleep_initiate_state(kbdev); @@ -1778,6 +1601,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) if (kbase_pm_is_mcu_desired(kbdev)) { /* Assume the transition is complete and prepare to goto ON state */ WARN_ON_ONCE(backend->l2_state != KBASE_L2_ON); + kbase_hwcnt_backend_csf_on_after_mcu_off(&kbdev->hwcnt_gpu_iface); backend->mcu_state = KBASE_MCU_IN_SLEEP; break; } @@ -1787,6 +1611,7 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) if (kbase_csf_firmware_is_mcu_in_sleep(kbdev)) { KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_MCU_SLEEP, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); + kbase_hwcnt_backend_csf_on_after_mcu_off(&kbdev->hwcnt_gpu_iface); backend->mcu_state = KBASE_MCU_IN_SLEEP; kbase_pm_enable_db_mirror_interrupt(kbdev); kbase_csf_scheduler_reval_idleness_post_sleep(kbdev); @@ -1827,15 +1652,20 @@ static int kbase_pm_mcu_update_state(struct kbase_device *kbdev) */ if (!kbdev->csf.firmware_hctl_core_pwr) kbasep_pm_toggle_power_interrupt(kbdev, false); + backend->mcu_state = KBASE_MCU_ON_HWCNT_ENABLE; kbase_csf_ring_doorbell(kbdev, CSF_KERNEL_DOORBELL_NR); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); } break; -#endif /* KBASE_PM_RUNTIME */ + case KBASE_MCU_RESET_WAIT: /* Reset complete */ - if (!backend->in_reset) + if (!backend->in_reset) { + kbase_hwcnt_backend_csf_on_after_mcu_off_reset( + &kbdev->hwcnt_gpu_iface); backend->mcu_state = KBASE_MCU_OFF; + } #if IS_ENABLED(CONFIG_MALI_VALHALL_CORESIGHT) kbdev->csf.coresight.disable_on_pmode_enter = false; @@ -1886,7 +1716,6 @@ static void core_idle_worker(struct work_struct *work) spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } -#endif static const char *kbase_l2_core_state_to_string(enum kbase_l2_core_state state) { @@ -1919,23 +1748,6 @@ static void kbase_ktrace_log_l2_core_state(struct kbase_device *kbdev, #endif } -#if !MALI_USE_CSF -/* On powering on the L2, the tracked kctx becomes stale and can be cleared. - * This enables the backend to spare the START_FLUSH.INV_SHADER_OTHER - * operation on the first submitted katom after the L2 powering on. - */ -static void kbase_pm_l2_clear_backend_slot_submit_kctx(struct kbase_device *kbdev) -{ - int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* Clear the slots' last katom submission kctx */ - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) - kbdev->hwaccess.backend.slot_rb[js].last_kctx_tagged = SLOT_RB_NULL_TAG_VAL; -} -#endif - static bool can_power_down_l2(struct kbase_device *kbdev) { lockdep_assert_held(&kbdev->hwaccess_lock); @@ -1954,18 +1766,12 @@ static bool can_power_up_l2(struct kbase_device *kbdev) static bool need_tiler_control(struct kbase_device *kbdev) { -#if MALI_USE_CSF if (kbase_pm_no_mcu_core_pwroff(kbdev)) return true; else return false; -#else - CSTD_UNUSED(kbdev); - return true; -#endif } -#if MALI_USE_CSF /** * hctl_l2_power_down - Initiate power down of L2 cache * @@ -1994,7 +1800,6 @@ static void hctl_l2_power_down(struct kbase_device *kbdev) kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, kbdev->gpu_props.curr_config.l2_present, ACTION_PWROFF); } -#endif /** * hctl_tiler_power_up_done - Check and/or initiate power up of Tiler @@ -2018,12 +1823,10 @@ static bool hctl_tiler_power_up_done(struct kbase_device *kbdev) return false; if (!tiler_ready) { -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, kbdev->gpu_props.tiler_present, ACTION_PWRON); } -#endif return false; } @@ -2031,8 +1834,11 @@ static bool hctl_tiler_power_up_done(struct kbase_device *kbdev) return true; } -#if MALI_USE_CSF +#if MALI_UNIT_TEST +int delegate_pm_domain_control_to_fw(struct kbase_device *kbdev, u32 pm_domain) +#else static int delegate_pm_domain_control_to_fw(struct kbase_device *kbdev, u32 pm_domain) +#endif { u64 val; int err; @@ -2058,10 +1864,17 @@ static int delegate_pm_domain_control_to_fw(struct kbase_device *kbdev, u32 pm_d if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) kbase_reset_gpu(kbdev); - return -ETIMEDOUT; + return err; } +#if MALI_UNIT_TEST +KBASE_EXPORT_TEST_API(delegate_pm_domain_control_to_fw); +#endif +#if MALI_UNIT_TEST +int retract_pm_domain_control_from_fw(struct kbase_device *kbdev, u32 pm_domain) +#else static int retract_pm_domain_control_from_fw(struct kbase_device *kbdev, u32 pm_domain) +#endif { u64 val; int err; @@ -2085,8 +1898,11 @@ static int retract_pm_domain_control_from_fw(struct kbase_device *kbdev, u32 pm_ if (kbase_prepare_to_reset_gpu(kbdev, RESET_FLAGS_HWC_UNRECOVERABLE_ERROR)) kbase_reset_gpu(kbdev); - return -ETIMEDOUT; + return err; } +#if MALI_UNIT_TEST +KBASE_EXPORT_TEST_API(retract_pm_domain_control_from_fw); +#endif /** * delegate_pm_domains_control_to_fw - Delegate power control for Tiler, Shading engine and @@ -2206,16 +2022,14 @@ int kbase_pm_get_domain_status(struct kbase_device *kbdev, u32 pm_domain, u32 en dev_err(kbdev->dev, "Inspect command for pm domain %u failed", pm_domain); return err; } -#endif /* MALI_USE_CSF */ +KBASE_EXPORT_TEST_API(kbase_pm_get_domain_status); static int kbase_pm_l2_update_state(struct kbase_device *kbdev) { struct kbase_pm_backend_data *backend = &kbdev->pm.backend; u64 l2_present = kbdev->gpu_props.curr_config.l2_present; u64 tiler_present = kbdev->gpu_props.tiler_present; -#if MALI_USE_CSF const bool has_host_pwr_iface = backend->has_host_pwr_iface; -#endif bool l2_power_up_done; enum kbase_l2_core_state prev_state; @@ -2232,22 +2046,25 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) */ if (!kbase_io_has_gpu(kbdev)) { backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF; - backend->hwcnt_desired = false; - if (!backend->hwcnt_disabled) { - /* Don't progress until hw counters are disabled - * This may involve waiting for a worker to complete. - * The HW counters backend disable code checks for the - * GPU removed case and will error out without touching - * the hardware. This step is needed to keep the HW - * counters in a consistent state after a GPU lost. - */ - backend->l2_state = KBASE_L2_ON_HWCNT_DISABLE; - KBASE_KTRACE_ADD(kbdev, PM_L2_ON_HWCNT_DISABLE, NULL, - backend->l2_state); - kbase_pm_trigger_hwcnt_disable(kbdev); + if (kbdev->csf.firmware_hctl_core_pwr) { + backend->hwcnt_desired = false; + if (!backend->hwcnt_disabled) { + /* Don't progress until hw counters are disabled + * This may involve waiting for a worker to complete. + * The HW counters backend disable code checks for the + * GPU removed case and will error out without touching + * the hardware. This step is needed to keep the HW + * counters in a consistent state after a GPU lost. + */ + backend->l2_state = KBASE_L2_ON_HWCNT_DISABLE; + KBASE_KTRACE_ADD(kbdev, PM_L2_ON_HWCNT_DISABLE, NULL, + backend->l2_state); + kbase_pm_trigger_hwcnt_disable(kbdev); + } } - if (backend->hwcnt_disabled && (backend->l2_state != KBASE_L2_OFF)) { + if ((backend->hwcnt_disabled || !kbdev->csf.firmware_hctl_core_pwr) && + (backend->l2_state != KBASE_L2_OFF)) { backend->l2_state = KBASE_L2_OFF; KBASE_KTRACE_ADD(kbdev, PM_L2_OFF, NULL, backend->l2_state); dev_dbg(kbdev->dev, "GPU lost has occurred - L2 off\n"); @@ -2265,14 +2082,14 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) switch (backend->l2_state) { case KBASE_L2_OFF: if (kbase_pm_is_l2_desired(kbdev) && can_power_up_l2(kbdev)) { -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - /* Enable HW timer of IPA control before - * L2 cache is powered-up. - */ - { - kbase_ipa_control_handle_gpu_sleep_exit(kbdev); + if (IS_ENABLED(CONFIG_PM)) { + /* Enable HW timer of IPA control before + * L2 cache is powered-up. + */ + { + kbase_ipa_control_handle_gpu_sleep_exit(kbdev); + } } -#endif /* * Set the desired config for L2 before * powering it on @@ -2287,7 +2104,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) * L2 cache. */ if (need_tiler_control(kbdev)) { -#if MALI_USE_CSF if (backend->pwr_cntl_delegated) { retract_pm_domains_control_from_fw(kbdev); backend->pwr_cntl_delegated = false; @@ -2300,30 +2116,17 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present, ACTION_PWRON); } else -#endif kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, tiler_present, ACTION_PWRON); } else { -#if MALI_USE_CSF if (has_host_pwr_iface && !backend->pwr_cntl_delegated) { delegate_pm_domains_control_to_fw(kbdev); backend->pwr_cntl_delegated = true; } -#endif kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present, ACTION_PWRON); } -#if !MALI_USE_CSF - /* If we have more than one L2 cache then we - * must power them on explicitly. - */ - if (l2_present != 1) - kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present & ~1ULL, - ACTION_PWRON); - /* Clear backend slot submission kctx */ - kbase_pm_l2_clear_backend_slot_submit_kctx(kbdev); -#endif backend->l2_state = KBASE_L2_PEND_ON; } break; @@ -2395,30 +2198,15 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) break; case KBASE_L2_ON_HWCNT_ENABLE: -#if !MALI_USE_CSF - backend->hwcnt_desired = true; - if (backend->hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - backend->hwcnt_disabled = false; - } -#endif backend->l2_state = KBASE_L2_ON; break; case KBASE_L2_ON: if (!kbase_pm_is_l2_desired(kbdev)) { -#if !MALI_USE_CSF - /* Do not power off L2 until the shaders and - * core stacks are off. - */ - if (backend->shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF) - break; -#else /* Do not power off L2 until the MCU has been stopped */ if ((backend->mcu_state != KBASE_MCU_OFF) && (backend->mcu_state != KBASE_MCU_IN_SLEEP)) break; -#endif /* We need to make sure hardware counters are * disabled before powering down the L2, to @@ -2435,38 +2223,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) break; case KBASE_L2_ON_HWCNT_DISABLE: -#if !MALI_USE_CSF - /* If the L2 became desired while we were waiting on the - * worker to do the actual hwcnt disable (which might - * happen if some work was submitted immediately after - * the shaders powered off), then we need to early-out - * of this state and re-enable hwcnt. - * - * If we get lucky, the hwcnt disable might not have - * actually started yet, and the logic in the hwcnt - * enable state will prevent the worker from - * performing the disable entirely, preventing loss of - * any hardware counter data. - * - * If the hwcnt disable has started, then we'll lose - * a tiny amount of hardware counter data between the - * disable and the re-enable occurring. - * - * This loss of data is preferable to the alternative, - * which is to block the shader cores from doing any - * work until we're sure hwcnt has been re-enabled. - */ - if (kbase_pm_is_l2_desired(kbdev)) { - backend->l2_state = KBASE_L2_ON_HWCNT_ENABLE; - break; - } - - backend->hwcnt_desired = false; - if (!backend->hwcnt_disabled) - kbase_pm_trigger_hwcnt_disable(kbdev); -#endif - - if (backend->hwcnt_disabled) { + if (backend->hwcnt_disabled || !kbdev->csf.firmware_hctl_core_pwr) { if (kbdev->pm.backend.gpu_clock_slow_down_wa) backend->l2_state = KBASE_L2_SLOW_DOWN_CLOCKS; else @@ -2503,7 +2260,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) backend->l2_state = KBASE_L2_PEND_ON; else if (can_power_down_l2(kbdev)) { if (!backend->l2_always_on) { -#if MALI_USE_CSF if (need_tiler_control(kbdev) && has_host_pwr_iface) { /* If using host power control, * the tiler must be explicitly turned off @@ -2512,7 +2268,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) kbase_pm_invoke(kbdev, KBASE_PM_CORE_TILER, tiler_present, ACTION_PWROFF); } else -#endif /* Powering off the L2 will also power off the tiler. */ kbase_pm_invoke(kbdev, KBASE_PM_CORE_L2, l2_present, ACTION_PWROFF); @@ -2524,36 +2279,31 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) */ kbase_gpu_start_cache_clean_nolock( kbdev, GPU_COMMAND_CACHE_CLN_INV_L2); -#if !MALI_USE_CSF - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_TILER, NULL, 0u); -#else KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE_L2, NULL, 0u); -#endif backend->l2_state = KBASE_L2_PEND_OFF; } break; case KBASE_L2_PEND_OFF: if (likely(!backend->l2_always_on)) { -#if MALI_USE_CSF if (need_tiler_control(kbdev) && l2_ready) { hctl_l2_power_down(kbdev); break; } -#endif if (l2_trans || l2_ready) break; } else if (kbdev->cache_clean_in_progress) break; -#if MALI_USE_CSF -#if defined(KBASE_PM_RUNTIME) + + if (IS_ENABLED(CONFIG_PM)) { /* Allow clock gating within the GPU and prevent it - * from being seen as active during sleep. - */ - { - kbase_ipa_control_handle_gpu_sleep_enter(kbdev); + * from being seen as active during sleep. + */ + { + kbase_ipa_control_handle_gpu_sleep_enter(kbdev); + } } -#endif + /* Disabling MCU after L2 cache power down is to address * KBASE_HW_ISSUE_TITANHW_2922 hardware issue. */ @@ -2562,7 +2312,6 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) WARN_ON_ONCE(backend->mcu_state != KBASE_MCU_OFF); backend->l2_force_off_after_mcu_halt = false; } -#endif /* L2 is now powered off */ backend->l2_state = KBASE_L2_OFF; @@ -2571,9 +2320,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) case KBASE_L2_RESET_WAIT: /* Reset complete */ if (!backend->in_reset) { -#if MALI_USE_CSF backend->l2_force_off_after_mcu_halt = false; -#endif backend->l2_state = KBASE_L2_OFF; } @@ -2597,12 +2344,7 @@ static int kbase_pm_l2_update_state(struct kbase_device *kbdev) if (kbdev->pm.backend.invoke_poweroff_wait_wq_when_l2_off && backend->l2_state == KBASE_L2_OFF) { kbdev->pm.backend.invoke_poweroff_wait_wq_when_l2_off = false; -#if MALI_USE_CSF kbase_csf_scheduler_enqueue_power_off_work(kbdev); -#else /* !MALI_USE_CSF */ - queue_work(kbdev->pm.backend.gpu_poweroff_wait_wq, - &kbdev->pm.backend.gpu_poweroff_wait_work); -#endif /* MALI_USE_CSF */ } return 0; @@ -2666,350 +2408,6 @@ static void shader_poweroff_timer_queue_cancel(struct kbase_device *kbdev) } } -#if !MALI_USE_CSF -static const char *kbase_shader_core_state_to_string(enum kbase_shader_core_state state) -{ - const char *const strings[] = { -#define KBASEP_SHADER_STATE(n) #n, -#include "mali_kbase_pm_shader_states.h" -#undef KBASEP_SHADER_STATE - }; - if (WARN_ON((size_t)state >= ARRAY_SIZE(strings))) - return "Bad shader core state"; - else - return strings[state]; -} - -static int kbase_pm_shaders_update_state(struct kbase_device *kbdev) -{ - struct kbase_pm_backend_data *backend = &kbdev->pm.backend; - struct kbasep_pm_tick_timer_state *stt = &kbdev->pm.backend.shader_tick_timer; - enum kbase_shader_core_state prev_state; - u64 stacks_avail = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (corestack_driver_control) - /* Always power on all the corestacks. Disabling certain - * corestacks when their respective shaders are not in the - * available bitmap is not currently supported. - */ - stacks_avail = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_STACK); - - do { - u64 shaders_trans = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_SHADER); - u64 shaders_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); - u64 stacks_trans = 0; - u64 stacks_ready = 0; - - if (corestack_driver_control) { - stacks_trans = kbase_pm_get_trans_cores(kbdev, KBASE_PM_CORE_STACK); - stacks_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_STACK); - } - - /* - * kbase_pm_get_ready_cores and kbase_pm_get_trans_cores - * are vulnerable to corruption if gpu is lost - */ - if (!kbase_io_has_gpu(kbdev)) { - backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF; - dev_dbg(kbdev->dev, "GPU lost has occurred - shaders off\n"); - break; - } - - /* mask off ready from trans in case transitions finished - * between the register reads - */ - shaders_trans &= ~shaders_ready; - stacks_trans &= ~stacks_ready; - - prev_state = backend->shaders_state; - - switch (backend->shaders_state) { - case KBASE_SHADERS_OFF_CORESTACK_OFF: - /* Ignore changes to the shader core availability - * except at certain points where we can handle it, - * i.e. off and SHADERS_ON_CORESTACK_ON. - */ - backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev); - backend->pm_shaders_core_mask = 0; - - if (backend->shaders_desired && backend->l2_state == KBASE_L2_ON) { - if (backend->hwcnt_desired && !backend->hwcnt_disabled) { - /* Trigger a hwcounter dump */ - backend->hwcnt_desired = false; - kbase_pm_trigger_hwcnt_disable(kbdev); - } - - if (backend->hwcnt_disabled) { - if (corestack_driver_control) { - kbase_pm_invoke(kbdev, KBASE_PM_CORE_STACK, - stacks_avail, ACTION_PWRON); - } - backend->shaders_state = - KBASE_SHADERS_OFF_CORESTACK_PEND_ON; - } - } - break; - - case KBASE_SHADERS_OFF_CORESTACK_PEND_ON: - if (!stacks_trans && stacks_ready == stacks_avail) { - backend->shaders_avail = backend->shaders_desired_mask; - kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, backend->shaders_avail, - ACTION_PWRON); - - if (backend->pm_current_policy && - backend->pm_current_policy->handle_event) - backend->pm_current_policy->handle_event( - kbdev, KBASE_PM_POLICY_EVENT_POWER_ON); - - backend->shaders_state = KBASE_SHADERS_PEND_ON_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_PEND_ON_CORESTACK_ON: - if (!shaders_trans && shaders_ready == backend->shaders_avail) { - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, - shaders_ready); - backend->pm_shaders_core_mask = shaders_ready; - backend->hwcnt_desired = true; - if (backend->hwcnt_disabled) { -#if MALI_USE_CSF - unsigned long flags; - - kbase_csf_scheduler_spin_lock(kbdev, &flags); -#endif - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); -#if MALI_USE_CSF - kbase_csf_scheduler_spin_unlock(kbdev, flags); -#endif - backend->hwcnt_disabled = false; - } - - backend->shaders_state = KBASE_SHADERS_ON_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_ON_CORESTACK_ON: - backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev); - - /* If shaders to change state, trigger a counter dump */ - if (!backend->shaders_desired || - (backend->shaders_desired_mask != shaders_ready)) { - backend->hwcnt_desired = false; - if (!backend->hwcnt_disabled) - kbase_pm_trigger_hwcnt_disable(kbdev); - backend->shaders_state = KBASE_SHADERS_ON_CORESTACK_ON_RECHECK; - } - break; - - case KBASE_SHADERS_ON_CORESTACK_ON_RECHECK: - backend->shaders_desired_mask = kbase_pm_ca_get_core_mask(kbdev); - - if (!backend->hwcnt_disabled) { - /* Wait for being disabled */ - ; - } else if (!backend->shaders_desired) { - if (backend->pm_current_policy && - backend->pm_current_policy->handle_event) - backend->pm_current_policy->handle_event( - kbdev, KBASE_PM_POLICY_EVENT_IDLE); - - if (kbdev->pm.backend.protected_transition_override || - (kbase_has_arbiter(kbdev) && (kbase_pm_is_suspending(kbdev) || - kbase_io_is_aw_removed(kbdev))) || - !stt->configured_ticks || WARN_ON(stt->cancel_queued)) { - backend->shaders_state = - KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON; - } else { - stt->remaining_ticks = stt->configured_ticks; - stt->needed = true; - - /* The shader hysteresis timer is not - * done the obvious way, which would be - * to start an hrtimer when the shader - * power off is requested. Instead, - * use a 'tick' timer, and set the - * remaining number of ticks on a power - * off request. This avoids the - * latency of starting, then - * immediately cancelling an hrtimer - * when the shaders are re-requested - * before the timeout expires. - */ - if (!hrtimer_active(&stt->timer)) - hrtimer_start(&stt->timer, stt->configured_interval, - HRTIMER_MODE_REL); - - backend->shaders_state = - KBASE_SHADERS_WAIT_OFF_CORESTACK_ON; - } - } else if (backend->shaders_desired_mask & ~shaders_ready) { - /* set cores ready but not available to - * meet KBASE_SHADERS_PEND_ON_CORESTACK_ON - * check pass - */ - backend->shaders_avail = - (backend->shaders_desired_mask | shaders_ready); - - kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, - backend->shaders_avail & ~shaders_ready, - ACTION_PWRON); - backend->shaders_state = KBASE_SHADERS_PEND_ON_CORESTACK_ON; - } else if (shaders_ready & ~backend->shaders_desired_mask) { - backend->shaders_state = KBASE_SHADERS_WAIT_GPU_IDLE; - } else { - backend->shaders_state = KBASE_SHADERS_PEND_ON_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_WAIT_OFF_CORESTACK_ON: - if (WARN_ON(!hrtimer_active(&stt->timer))) { - stt->remaining_ticks = 0; - backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON; - } - - if (backend->shaders_desired) { - if (backend->pm_current_policy && - backend->pm_current_policy->handle_event) - backend->pm_current_policy->handle_event( - kbdev, KBASE_PM_POLICY_EVENT_TIMER_HIT); - - stt->remaining_ticks = 0; - backend->shaders_state = KBASE_SHADERS_ON_CORESTACK_ON_RECHECK; - } else if (stt->remaining_ticks == 0) { - if (backend->pm_current_policy && - backend->pm_current_policy->handle_event) - backend->pm_current_policy->handle_event( - kbdev, KBASE_PM_POLICY_EVENT_TIMER_MISS); - - backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON; - } else if (kbase_has_arbiter(kbdev) && (kbase_pm_is_suspending(kbdev) || - kbase_io_is_aw_removed(kbdev))) { - backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_WAIT_GPU_IDLE: - /* If partial shader core off need to wait the job in - * running and next register finished then flush L2 - * or it might hit GPU2017-861 - */ - if (!kbase_gpu_atoms_submitted_any(kbdev)) { - backend->partial_shaderoff = true; - backend->shaders_state = KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_WAIT_FINISHED_CORESTACK_ON: - if (!backend->partial_shaderoff) - shader_poweroff_timer_queue_cancel(kbdev); - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_921)) { - kbase_gpu_start_cache_clean_nolock(kbdev, - GPU_COMMAND_CACHE_CLN_INV_L2); - backend->shaders_state = KBASE_SHADERS_L2_FLUSHING_CORESTACK_ON; - } else { - backend->shaders_state = KBASE_SHADERS_READY_OFF_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_L2_FLUSHING_CORESTACK_ON: - if (!kbdev->cache_clean_in_progress) - backend->shaders_state = KBASE_SHADERS_READY_OFF_CORESTACK_ON; - - break; - - case KBASE_SHADERS_READY_OFF_CORESTACK_ON: - if (backend->partial_shaderoff) { - backend->partial_shaderoff = false; - /* remove cores available but not ready to - * meet KBASE_SHADERS_PEND_ON_CORESTACK_ON - * check pass - */ - - /* shaders_desired_mask shall be a subset of - * shaders_ready - */ - WARN_ON(backend->shaders_desired_mask & ~shaders_ready); - WARN_ON(!(backend->shaders_desired_mask & shaders_ready)); - - backend->shaders_avail = backend->shaders_desired_mask; - kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, - shaders_ready & ~backend->shaders_avail, - ACTION_PWROFF); - backend->shaders_state = KBASE_SHADERS_PEND_ON_CORESTACK_ON; - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, - (shaders_ready & ~backend->shaders_avail)); - } else { - kbase_pm_invoke(kbdev, KBASE_PM_CORE_SHADER, shaders_ready, - ACTION_PWROFF); - - KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_AVAILABLE, NULL, 0u); - - backend->shaders_state = KBASE_SHADERS_PEND_OFF_CORESTACK_ON; - } - break; - - case KBASE_SHADERS_PEND_OFF_CORESTACK_ON: - if (!shaders_trans && !shaders_ready) { - if (corestack_driver_control) - kbase_pm_invoke(kbdev, KBASE_PM_CORE_STACK, stacks_avail, - ACTION_PWROFF); - - backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_PEND_OFF; - } - break; - - case KBASE_SHADERS_OFF_CORESTACK_PEND_OFF: - if (!stacks_trans && !stacks_ready) { - /* On powered off, re-enable the hwcnt */ - backend->pm_shaders_core_mask = 0; - backend->hwcnt_desired = true; - if (backend->hwcnt_disabled) { -#if MALI_USE_CSF - unsigned long flags; - - kbase_csf_scheduler_spin_lock(kbdev, &flags); -#endif - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); -#if MALI_USE_CSF - kbase_csf_scheduler_spin_unlock(kbdev, flags); -#endif - backend->hwcnt_disabled = false; - } - backend->shaders_state = - KBASE_SHADERS_OFF_CORESTACK_OFF_TIMER_PEND_OFF; - } - break; - - case KBASE_SHADERS_OFF_CORESTACK_OFF_TIMER_PEND_OFF: - if (!hrtimer_active(&stt->timer) && !stt->cancel_queued) - backend->shaders_state = KBASE_SHADERS_OFF_CORESTACK_OFF; - break; - - case KBASE_SHADERS_RESET_WAIT: - /* Reset complete */ - if (!backend->in_reset) - backend->shaders_state = - KBASE_SHADERS_OFF_CORESTACK_OFF_TIMER_PEND_OFF; - break; - } - - if (backend->shaders_state != prev_state) { - dev_dbg(kbdev->dev, "Shader state transition: %s to %s\n", - kbase_shader_core_state_to_string(prev_state), - kbase_shader_core_state_to_string(backend->shaders_state)); - KBASE_TLSTREAM_TL_KBASE_DEVICE_SHADER_CORE_STATE(kbdev, kbdev->id, - backend->shaders_state); - } - - } while (backend->shaders_state != prev_state); - - return 0; -} -#endif /* !MALI_USE_CSF */ - static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev) { bool in_desired_state = true; @@ -3018,16 +2416,7 @@ static bool kbase_pm_is_in_desired_state_nolock(struct kbase_device *kbdev) in_desired_state = kbase_pm_l2_is_in_desired_state(kbdev); -#if !MALI_USE_CSF - if (kbdev->pm.backend.shaders_desired && - kbdev->pm.backend.shaders_state != KBASE_SHADERS_ON_CORESTACK_ON) - in_desired_state = false; - else if (!kbdev->pm.backend.shaders_desired && - kbdev->pm.backend.shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF) - in_desired_state = false; -#else in_desired_state &= kbase_pm_mcu_is_in_desired_state(kbdev); -#endif return in_desired_state; } @@ -3058,31 +2447,9 @@ static bool kbase_pm_is_in_desired_state_with_l2_powered(struct kbase_device *kb return in_desired_state; } -#if !MALI_USE_CSF -static void kbase_pm_trace_power_state(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - KBASE_TLSTREAM_AUX_PM_STATE(kbdev, TL_PM_STATE_L2, - kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_L2)); - KBASE_TLSTREAM_AUX_PM_STATE(kbdev, TL_PM_STATE_SHADER, - kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER)); - KBASE_TLSTREAM_AUX_PM_STATE(kbdev, TL_PM_STATE_TILER, - kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_TILER)); - - if (corestack_driver_control) - KBASE_TLSTREAM_AUX_PM_STATE(kbdev, TL_PM_STATE_STACK, - kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_STACK)); -} -#endif - void kbase_pm_update_state(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - enum kbase_shader_core_state prev_shaders_state = kbdev->pm.backend.shaders_state; -#else enum kbase_mcu_state prev_mcu_state = kbdev->pm.backend.mcu_state; -#endif lockdep_assert_held(&kbdev->hwaccess_lock); @@ -3092,20 +2459,6 @@ void kbase_pm_update_state(struct kbase_device *kbdev) if (kbase_pm_l2_update_state(kbdev)) return; -#if !MALI_USE_CSF - if (kbase_pm_shaders_update_state(kbdev)) - return; - - /* If the shaders just turned off, re-invoke the L2 state machine, in - * case it was waiting for the shaders to turn off before powering down - * the L2. - */ - if (prev_shaders_state != KBASE_SHADERS_OFF_CORESTACK_OFF && - kbdev->pm.backend.shaders_state == KBASE_SHADERS_OFF_CORESTACK_OFF) { - if (kbase_pm_l2_update_state(kbdev)) - return; - } -#else if (kbase_pm_mcu_update_state(kbdev)) return; @@ -3114,15 +2467,10 @@ void kbase_pm_update_state(struct kbase_device *kbdev) if (kbase_pm_l2_update_state(kbdev)) return; } -#endif if (kbase_pm_is_in_desired_state_nolock(kbdev)) { KBASE_KTRACE_ADD(kbdev, PM_DESIRED_REACHED, NULL, kbdev->pm.backend.shaders_avail); -#if !MALI_USE_CSF - kbase_pm_trace_power_state(kbdev); -#endif - KBASE_KTRACE_ADD(kbdev, PM_WAKE_WAITERS, NULL, 0); wake_up(&kbdev->pm.backend.gpu_in_desired_state_wait); } @@ -3177,7 +2525,6 @@ int kbase_pm_state_machine_init(struct kbase_device *kbdev) stt->default_ticks = DEFAULT_PM_POWEROFF_TICK_SHADER; stt->configured_ticks = stt->default_ticks; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { const u64 neural_present = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_NEURAL); const u64 shader_present = kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER); @@ -3216,16 +2563,13 @@ int kbase_pm_state_machine_init(struct kbase_device *kbdev) } INIT_WORK(&kbdev->pm.backend.core_idle_work, core_idle_worker); -#endif return 0; } void kbase_pm_state_machine_term(struct kbase_device *kbdev) { -#if MALI_USE_CSF destroy_workqueue(kbdev->pm.backend.core_idle_wq); -#endif hrtimer_cancel(&kbdev->pm.backend.shader_tick_timer.timer); destroy_workqueue(kbdev->pm.backend.shader_tick_timer.wq); } @@ -3239,23 +2583,19 @@ void kbase_pm_reset_start_locked(struct kbase_device *kbdev) backend->in_reset = true; backend->l2_state = KBASE_L2_RESET_WAIT; KBASE_KTRACE_ADD(kbdev, PM_L2_RESET_WAIT, NULL, backend->l2_state); -#if !MALI_USE_CSF - backend->shaders_state = KBASE_SHADERS_RESET_WAIT; -#else /* MCU state machine is exercised only after the initial load/boot * of the firmware. */ if (likely(kbdev->csf.firmware_inited)) { backend->mcu_state = KBASE_MCU_RESET_WAIT; KBASE_KTRACE_ADD(kbdev, PM_MCU_RESET_WAIT, NULL, backend->mcu_state); -#ifdef KBASE_PM_RUNTIME - backend->exit_gpu_sleep_mode = true; -#endif + if (IS_ENABLED(CONFIG_PM)) + backend->exit_gpu_sleep_mode = true; + kbdev->csf.firmware_reload_needed = true; } else { WARN_ON(backend->mcu_state != KBASE_MCU_OFF); } -#endif /* We're in a reset, so hwcnt will have been synchronously disabled by * this function's caller as part of the reset process. We therefore @@ -3288,42 +2628,39 @@ void kbase_pm_reset_complete(struct kbase_device *kbdev) */ kbase_gpu_cache_clean_wait_complete(kbdev); backend->in_reset = false; -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - backend->gpu_wakeup_override = false; - backend->db_mirror_interrupt_enabled = false; - backend->gpu_sleep_mode_active = false; - backend->exit_gpu_sleep_mode = false; -#endif + if (IS_ENABLED(CONFIG_PM)) { + backend->gpu_wakeup_override = false; + backend->db_mirror_interrupt_enabled = false; + backend->gpu_sleep_mode_active = false; + backend->exit_gpu_sleep_mode = false; + } kbase_pm_update_state(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } -#if !MALI_USE_CSF -/* Timeout in milliseconds for GPU Power Management to reach the desired - * Shader and L2 state. If the time spent waiting has exceeded this threshold - * then there is most likely a hardware issue. - */ -#define PM_TIMEOUT_MS (5000) /* 5s */ -#endif +#if MALI_UNIT_TEST +void kbase_pm_timed_out(struct kbase_device *kbdev, const char *timeout_msg); +void kbase_pm_timed_out(struct kbase_device *kbdev, const char *timeout_msg) +#else static void kbase_pm_timed_out(struct kbase_device *kbdev, const char *timeout_msg) +#endif { unsigned long flags; dev_err(kbdev->dev, "%s", timeout_msg); -#if !MALI_USE_CSF - CSTD_UNUSED(flags); - dev_err(kbdev->dev, "Desired state :\n"); - dev_err(kbdev->dev, "\tShader=%016llx\n", - kbdev->pm.backend.shaders_desired ? kbdev->pm.backend.shaders_avail : 0); -#else spin_lock_irqsave(&kbdev->hwaccess_lock, flags); dev_err(kbdev->dev, "\tMCU desired = %d\n", kbase_pm_is_mcu_desired(kbdev)); dev_err(kbdev->dev, "\tMCU sw state = %d\n", kbdev->pm.backend.mcu_state); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#endif dev_err(kbdev->dev, "Current state :\n"); + + if (kbase_io_is_aw_removed(kbdev)) { + dev_err(kbdev->dev, "\tGPU lost"); + return; + } + dev_err(kbdev->dev, "\tStack =%016llx\n", kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(STACK_READY))); dev_err(kbdev->dev, "\tShader=%016llx\n", @@ -3332,10 +2669,8 @@ static void kbase_pm_timed_out(struct kbase_device *kbdev, const char *timeout_m kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(TILER_READY))); dev_err(kbdev->dev, "\tL2 =%016llx\n", kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(L2_READY))); -#if MALI_USE_CSF dev_err(kbdev->dev, "\tMCU status = %d\n", kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(MCU_STATUS))); -#endif dev_err(kbdev->dev, "Cores transitioning :\n"); dev_err(kbdev->dev, "\tStack =%016llx\n", kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(STACK_PWRTRANS))); @@ -3351,6 +2686,9 @@ static void kbase_pm_timed_out(struct kbase_device *kbdev, const char *timeout_m kbase_reset_gpu(kbdev); } } +#if MALI_UNIT_TEST +KBASE_EXPORT_TEST_API(kbase_pm_timed_out); +#endif int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev) { @@ -3363,12 +2701,8 @@ int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev) kbase_pm_update_state(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF timeout = (unsigned long)kbase_csf_timeout_in_jiffies( kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); -#else - timeout = msecs_to_jiffies(PM_TIMEOUT_MS); -#endif /* Wait for cores */ #if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE @@ -3396,11 +2730,7 @@ static int pm_wait_for_desired_state(struct kbase_device *kbdev, bool killable_w { unsigned long flags; long remaining; -#if MALI_USE_CSF long timeout = kbase_csf_timeout_in_jiffies(kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT)); -#else - long timeout = (long)msecs_to_jiffies(PM_TIMEOUT_MS); -#endif int err = 0; /* Let the state machine latch the most recent desired state. */ @@ -3412,14 +2742,17 @@ static int pm_wait_for_desired_state(struct kbase_device *kbdev, bool killable_w #if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE if (killable_wait) remaining = wait_event_killable_timeout(kbdev->pm.backend.gpu_in_desired_state_wait, - kbase_pm_is_in_desired_state(kbdev), + kbase_pm_is_in_desired_state(kbdev) || + kbase_io_is_aw_removed(kbdev), timeout); #else killable_wait = false; #endif if (!killable_wait) remaining = wait_event_timeout(kbdev->pm.backend.gpu_in_desired_state_wait, - kbase_pm_is_in_desired_state(kbdev), timeout); + kbase_pm_is_in_desired_state(kbdev) || + kbase_io_is_aw_removed(kbdev), + timeout); if (!remaining) { kbase_pm_timed_out(kbdev, "Wait for power transition timed out"); err = -ETIMEDOUT; @@ -3427,6 +2760,9 @@ static int pm_wait_for_desired_state(struct kbase_device *kbdev, bool killable_w WARN_ON_ONCE(!killable_wait); dev_info(kbdev->dev, "Wait for power transition got interrupted"); err = (int)remaining; + } else if (kbase_io_is_aw_removed(kbdev) && !kbase_pm_is_in_desired_state(kbdev)) { + dev_warn(kbdev->dev, "%s(): aborting, AW is no longer connected", __func__); + err = -ETIMEDOUT; } return err; @@ -3443,7 +2779,6 @@ int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_pm_wait_for_desired_state); -#if MALI_USE_CSF /** * core_mask_update_done - Check if downscaling of shader cores is done * @@ -3497,7 +2832,6 @@ int kbase_pm_wait_for_cores_down_scale(struct kbase_device *kbdev) return err; } -#endif static bool is_poweroff_wait_in_progress(struct kbase_device *kbdev) { @@ -3515,7 +2849,6 @@ static int pm_wait_for_poweroff_work_complete(struct kbase_device *kbdev, bool k { long remaining; /* Indefinite wait needed when arbitration is enabled */ -#if MALI_USE_CSF /* gpu_poweroff_wait_work would be subjected to the kernel scheduling * and so the wait time can't only be the function of GPU frequency. */ @@ -3524,16 +2857,22 @@ static int pm_wait_for_poweroff_work_complete(struct kbase_device *kbdev, bool k kbase_get_timeout_ms(kbdev, CSF_PM_TIMEOUT) + extra_wait_time_ms); const long timeout = kbase_has_arbiter(kbdev) ? MAX_SCHEDULE_TIMEOUT : timeout_extra_wait_time; -#else - const long timeout = kbase_has_arbiter(kbdev) ? MAX_SCHEDULE_TIMEOUT : - (long)msecs_to_jiffies(PM_TIMEOUT_MS); -#endif int err = 0; + unsigned long flags; + + if (kbase_io_is_aw_removed(kbdev)) { + dev_info(kbdev->dev, "%s: AW disconnected, exiting early", __func__); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbdev->pm.backend.poweroff_wait_in_progress = false; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + return err; + } #if KERNEL_VERSION(4, 13, 1) <= LINUX_VERSION_CODE if (killable_wait) remaining = wait_event_killable_timeout(kbdev->pm.backend.poweroff_wait, - !is_poweroff_wait_in_progress(kbdev), + !is_poweroff_wait_in_progress(kbdev) || + kbase_io_is_aw_removed(kbdev), timeout); #else killable_wait = false; @@ -3541,7 +2880,8 @@ static int pm_wait_for_poweroff_work_complete(struct kbase_device *kbdev, bool k if (!killable_wait) remaining = wait_event_timeout(kbdev->pm.backend.poweroff_wait, - !is_poweroff_wait_in_progress(kbdev), timeout); + !is_poweroff_wait_in_progress(kbdev), timeout) || + kbase_io_is_aw_removed(kbdev); if (!remaining) { kbase_pm_timed_out(kbdev, "Wait for poweroff work timed out"); err = -ETIMEDOUT; @@ -3571,11 +2911,7 @@ void kbase_pm_enable_interrupts(struct kbase_device *kbdev) bool is_legacy_gpu_irq_mask; KBASE_DEBUG_ASSERT(kbdev != NULL); -#if MALI_USE_CSF is_legacy_gpu_irq_mask = !kbdev->pm.backend.has_host_pwr_iface; -#else - is_legacy_gpu_irq_mask = true; -#endif /* * Clear all interrupts, @@ -3593,19 +2929,13 @@ void kbase_pm_enable_interrupts(struct kbase_device *kbdev) kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK), 0xFFFFFFFF); kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_CLEAR), 0xFFFFFFFF); -#if MALI_USE_CSF /* Enable only the Page fault bits part */ kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), 0xFFFF); -#else - kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), 0xFFFFFFFF); -#endif -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_CLEAR), PWR_IRQ_REG_ALL); kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_MASK), PWR_IRQ_REG_ALL); } -#endif } KBASE_EXPORT_TEST_API(kbase_pm_enable_interrupts); @@ -3615,11 +2945,7 @@ void kbase_pm_disable_interrupts_nolock(struct kbase_device *kbdev) bool is_legacy_gpu_irq_mask; KBASE_DEBUG_ASSERT(kbdev != NULL); -#if MALI_USE_CSF is_legacy_gpu_irq_mask = !kbdev->pm.backend.has_host_pwr_iface; -#else - is_legacy_gpu_irq_mask = true; -#endif /* * Mask all interrupts, * and clear them all. @@ -3636,12 +2962,10 @@ void kbase_pm_disable_interrupts_nolock(struct kbase_device *kbdev) kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), 0); kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_CLEAR), 0xFFFFFFFF); -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_MASK), 0); kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_IRQ_CLEAR), PWR_IRQ_REG_ALL); } -#endif } void kbase_pm_disable_interrupts(struct kbase_device *kbdev) @@ -3655,7 +2979,6 @@ void kbase_pm_disable_interrupts(struct kbase_device *kbdev) KBASE_EXPORT_TEST_API(kbase_pm_disable_interrupts); -#if MALI_USE_CSF /** * update_user_reg_page_mapping - Update the mapping for USER Register page * @@ -3686,7 +3009,6 @@ static void update_user_reg_page_mapping(struct kbase_device *kbdev) } mutex_unlock(&kbdev->csf.reg_lock); } -#endif /* * pmu layout: @@ -3701,9 +3023,6 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) unsigned long flags; KBASE_DEBUG_ASSERT(kbdev != NULL); -#if !MALI_USE_CSF - lockdep_assert_held(&kbdev->js_data.runpool_mutex); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kbdev->pm.lock); if (WARN_ON(kbase_io_is_aw_removed(kbdev))) { @@ -3712,12 +3031,11 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) } if (kbase_io_is_gpu_powered(kbdev)) { -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) - if (backend->gpu_idled) { + if (IS_ENABLED(CONFIG_PM) && backend->gpu_idled) { backend->callback_power_runtime_gpu_active(kbdev); backend->gpu_idled = false; } -#endif + /* Already turned on */ if (kbdev->poweroff_pending) kbase_pm_enable_interrupts(kbdev); @@ -3741,10 +3059,8 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_GPU_OFF); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF /* GPU has been turned on, can switch to actual register page */ update_user_reg_page_mapping(kbdev); -#endif if (ret == GPU_STATE_IN_RESET) { @@ -3783,13 +3099,6 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); mutex_unlock(&kbdev->mmu_hw_mutex); - if (kbdev->dummy_job_wa.flags & KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER) { - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_dummy_job_wa_execute(kbdev, - kbase_pm_get_present_cores(kbdev, KBASE_PM_CORE_SHADER)); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } - /* Enable the interrupts */ kbase_pm_enable_interrupts(kbdev); @@ -3797,7 +3106,6 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); backend->gpu_ready = true; backend->l2_desired = true; -#if MALI_USE_CSF { if (ret != GPU_STATE_INTACT) { /* GPU reset was done after the power on, so send the post @@ -3809,19 +3117,16 @@ void kbase_pm_clock_on(struct kbase_device *kbdev, bool is_resume) kbase_ipa_control_handle_gpu_power_on(kbdev); } } -#endif kbase_pm_update_state(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) /* GPU is now powered up. Invoke the GPU active callback as GPU idle * callback would have been invoked before the power down. */ - if (backend->gpu_idled) { + if (IS_ENABLED(CONFIG_PM) && backend->gpu_idled) { backend->callback_power_runtime_gpu_active(kbdev); backend->gpu_idled = false; } -#endif } KBASE_EXPORT_TEST_API(kbase_pm_clock_on); @@ -3861,11 +3166,9 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev) } kbase_pm_cache_snoop_disable(kbdev); -#if MALI_USE_CSF { kbase_ipa_control_handle_gpu_power_off(kbdev); } -#endif if (kbase_io_is_aw_removed(kbdev)) { /* Ensure we unblock any threads that are stuck waiting @@ -3881,10 +3184,8 @@ bool kbase_pm_clock_off(struct kbase_device *kbdev) spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF /* GPU is about to be turned off, switch to dummy page */ update_user_reg_page_mapping(kbdev); -#endif kbase_arbiter_pm_vm_event(kbdev, KBASE_VM_GPU_IDLE_EVENT); if (kbdev->pm.backend.callback_power_off) @@ -3940,7 +3241,6 @@ static enum hrtimer_restart kbasep_reset_timeout(struct hrtimer *timer) return HRTIMER_NORESTART; } -#if MALI_USE_CSF /** * kbase_ne_control_apply - Apply DT values to NEURAL_CONTROL register * @@ -3979,37 +3279,11 @@ static int kbase_ne_control_apply(struct kbase_device *kbdev) return 0; } -#endif static int kbase_set_gpu_quirks(struct kbase_device *kbdev) { -#if MALI_USE_CSF if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(CSF_CONFIG))) kbdev->hw_quirks_gpu = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(CSF_CONFIG)); -#else - u32 hw_quirks_gpu = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(JM_CONFIG)); - - if (kbdev->gpu_props.gpu_id.product_model == GPU_ID_PRODUCT_TMIX) { - /* Only for tMIx */ - u32 coherency_features; - - coherency_features = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(COHERENCY_FEATURES)); - - /* (COHERENCY_ACE_LITE | COHERENCY_ACE) was incorrectly - * documented for tMIx so force correct value here. - */ - if (coherency_features == COHERENCY_FEATURE_BIT(COHERENCY_ACE)) { - hw_quirks_gpu |= (COHERENCY_ACE_LITE | COHERENCY_ACE) - << JM_FORCE_COHERENCY_FEATURES_SHIFT; - } - } - - if (!kbase_io_has_gpu(kbdev)) - return -EIO; - - kbdev->hw_quirks_gpu = hw_quirks_gpu; - -#endif /* !MALI_USE_CSF */ if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_IDVS_GROUP_SIZE)) { u32 default_idvs_group_size = 0xF; u32 group_size = 0; @@ -4074,7 +3348,6 @@ static int kbase_set_tiler_quirks(struct kbase_device *kbdev) return 0; } -#if MALI_USE_CSF static int kbase_set_ne_quirks(struct kbase_device *kbdev) { u32 hw_quirks_ne = 0; @@ -4089,7 +3362,6 @@ static int kbase_set_ne_quirks(struct kbase_device *kbdev) return 0; } -#endif static int kbase_pm_hw_issues_detect(struct kbase_device *kbdev) { @@ -4143,7 +3415,6 @@ static int kbase_pm_hw_issues_detect(struct kbase_device *kbdev) error = kbase_set_mmu_quirks(kbdev); } -#if MALI_USE_CSF if (!of_property_read_u32(np, "quirks-ne", &kbdev->hw_quirks_ne)) { dev_info(kbdev->dev, "Found NE quirks = [0x%x] in Devicetree\n", kbdev->hw_quirks_ne); @@ -4152,7 +3423,6 @@ static int kbase_pm_hw_issues_detect(struct kbase_device *kbdev) if (error) return error; } -#endif return error; } @@ -4167,64 +3437,21 @@ static void kbase_pm_hw_issues_apply(struct kbase_device *kbdev) if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(L2_MMU_CONFIG))) kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(L2_MMU_CONFIG), kbdev->hw_quirks_mmu); -#if MALI_USE_CSF if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(CSF_CONFIG))) kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(CSF_CONFIG), kbdev->hw_quirks_gpu); -#else - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(JM_CONFIG), kbdev->hw_quirks_gpu); -#endif -#if MALI_USE_CSF if (kbase_reg_is_valid(kbdev, GPU_CONTROL_ENUM(NEURAL_CONFIG))) kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(NEURAL_CONFIG), kbdev->hw_quirks_ne); -#endif } void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - if ((kbdev->current_gpu_coherency_mode == COHERENCY_ACE) && !kbdev->cci_snoop_enabled) { -#if IS_ENABLED(CONFIG_ARM64) - if (kbdev->snoop_enable_smc != 0) - kbase_invoke_smc_fid(kbdev->snoop_enable_smc, 0, 0, 0); -#endif /* CONFIG_ARM64 */ - dev_dbg(kbdev->dev, "MALI - CCI Snoops - Enabled\n"); - kbdev->cci_snoop_enabled = true; - } -#endif /* !MALI_USE_CSF */ } void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - if (kbdev->cci_snoop_enabled) { -#if IS_ENABLED(CONFIG_ARM64) - if (kbdev->snoop_disable_smc != 0) { - mali_cci_flush_l2(kbdev); - kbase_invoke_smc_fid(kbdev->snoop_disable_smc, 0, 0, 0); - } -#endif /* CONFIG_ARM64 */ - dev_dbg(kbdev->dev, "MALI - CCI Snoops Disabled\n"); - kbdev->cci_snoop_enabled = false; - } -#endif /* !MALI_USE_CSF */ } -#if !MALI_USE_CSF -static void reenable_protected_mode_hwcnt(struct kbase_device *kbdev) -{ - unsigned long irq_flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); - kbdev->protected_mode_hwcnt_desired = true; - if (kbdev->protected_mode_hwcnt_disabled) { - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbdev->protected_mode_hwcnt_disabled = false; - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); -} -#endif - static int kbase_pm_do_reset_soft(struct kbase_device *kbdev) { int ret; @@ -4236,14 +3463,11 @@ static int kbase_pm_do_reset_soft(struct kbase_device *kbdev) else if (ret > 0) return 0; } else { -#if MALI_USE_CSF /* Check if soft reset needs to be issued via PWR_COMMAND */ if (kbdev->pm.backend.has_host_pwr_iface) kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_COMMAND), PWR_COMMAND_COMMAND_RESET_SOFT); - else -#endif - { + else { kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), GPU_COMMAND_SOFT_RESET); } @@ -4272,12 +3496,10 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev) reg_val = RESET_COMPLETED; /* Unmask the reset complete interrupt only */ -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { reg_offset = HOST_POWER_ENUM(PWR_IRQ_MASK); reg_val = PWR_IRQ_RESET_COMPLETED; } -#endif kbase_reg_write32(kbdev, reg_offset, reg_val); } @@ -4286,14 +3508,27 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev) rtdata.timed_out = false; /* Create a timer to use as a timeout on the reset */ +#if KERNEL_VERSION(6, 13, 0) <= LINUX_VERSION_CODE + hrtimer_setup_on_stack(&rtdata.timer, kbasep_reset_timeout, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); +#else hrtimer_init_on_stack(&rtdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); rtdata.timer.function = kbasep_reset_timeout; +#endif hrtimer_start(&rtdata.timer, HR_TIMER_DELAY_MSEC(RESET_TIMEOUT), HRTIMER_MODE_REL); /* Wait for the RESET_COMPLETED interrupt to be raised */ kbase_pm_wait_for_reset(kbdev); + if (kbase_io_is_aw_removed(kbdev)) { + dev_warn(kbdev->dev, "%s: AW removed, exiting early", __func__); + hrtimer_cancel(&rtdata.timer); + destroy_hrtimer_on_stack(&rtdata.timer); + + return -ENODEV; + } + if (!rtdata.timed_out) { /* GPU has been reset */ @@ -4305,12 +3540,10 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev) reg_offset = GPU_CONTROL_ENUM(GPU_IRQ_RAWSTAT); reg_val = RESET_COMPLETED; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { reg_offset = HOST_POWER_ENUM(PWR_IRQ_RAWSTAT); reg_val = PWR_IRQ_RESET_COMPLETED; } -#endif /* No interrupt has been received - check if the RAWSTAT register says * the reset has completed. @@ -4344,13 +3577,10 @@ static int kbase_pm_do_reset(struct kbase_device *kbdev) atomic_set(&kbdev->pm.backend.reset_in_progress, 1); -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) kbase_reg_write32(kbdev, HOST_POWER_ENUM(PWR_COMMAND), PWR_COMMAND_COMMAND_RESET_HARD); - else -#endif - { + else { kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), GPU_COMMAND_HARD_RESET); } @@ -4408,10 +3638,8 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_GPU_OFF); } -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface && !pwr_status_gpu_reset_allowed(kbdev)) return -EINVAL; -#endif /* Ensure interrupts are off to begin with, this also clears any * outstanding interrupts @@ -4434,7 +3662,6 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) err = kbdev->protected_ops->protected_mode_disable(kbdev->protected_dev); spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); -#if MALI_USE_CSF if (kbdev->protected_mode) { unsigned long flags; @@ -4444,14 +3671,12 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) kbase_hwcnt_backend_csf_protm_exited(&kbdev->hwcnt_gpu_iface); kbase_csf_scheduler_spin_unlock(kbdev, flags); } -#endif kbdev->protected_mode = false; spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); if (err) goto exit; -#if MALI_USE_CSF /* Check power status register value after GPU reset */ if (kbdev->pm.backend.has_host_pwr_iface && !pwr_status_value_valid_post_reset(kbdev)) { err = -EINVAL; @@ -4469,7 +3694,6 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) if (err) goto exit; } -#endif if (flags & PM_HW_ISSUES_DETECT) { err = kbase_pm_hw_issues_detect(kbdev); if (err) @@ -4479,10 +3703,8 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) kbase_pm_hw_issues_apply(kbdev); kbase_cache_set_coherency_mode(kbdev, kbdev->system_coherency); kbase_amba_set_shareable_cache_support(kbdev); -#if MALI_USE_CSF kbase_backend_update_gpu_timestamp_offset(kbdev); kbdev->csf.compute_progress_timeout_cc = 0; -#endif /* Sanity check protected mode was left after reset */ WARN_ON(kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_STATUS)) & @@ -4492,14 +3714,6 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags) kbase_pm_enable_interrupts(kbdev); exit: -#if !MALI_USE_CSF - if (!kbdev->pm.backend.protected_entry_transition_override) { - /* Re-enable GPU hardware counters if we're resetting from - * protected mode. - */ - reenable_protected_mode_hwcnt(kbdev); - } -#endif return err; } @@ -4532,13 +3746,6 @@ static void kbase_pm_request_gpu_cycle_counter_do_request(struct kbase_device *k /* This might happen after GPU reset. * Then counter needs to be kicked. */ -#if !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) && !MALI_USE_CSF - if (!(kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_STATUS)) & - GPU_STATUS_CYCLE_COUNT_ACTIVE)) { - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_COMMAND), - GPU_COMMAND_CYCLE_COUNT_START); - } -#endif } spin_unlock_irqrestore(&kbdev->pm.backend.gpu_cycle_counter_requests_lock, flags); diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_internal.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_internal.h index b6e0311308e1..88ae28192851 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_internal.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_internal.h @@ -31,6 +31,19 @@ #include "backend/gpu/mali_kbase_pm_ca.h" #include "mali_kbase_pm_policy.h" +/** + * enum mask_type - used to determine which mask is being updated + * + * @SYSFS_COREMASK: core mask requested via sysfs + * @DEVFREQ_COREMASK: core mask requested via devfreq + */ +enum mask_type { + SYSFS_COREMASK, +#ifdef CONFIG_MALI_VALHALL_DEVFREQ + DEVFREQ_COREMASK +#endif +}; + /** * kbase_pm_dev_idle - The GPU is idle. * @@ -200,7 +213,6 @@ int kbase_pm_init_hw(struct kbase_device *kbdev, unsigned int flags); */ void kbase_pm_reset_done(struct kbase_device *kbdev); -#if MALI_USE_CSF /** * kbase_pm_wait_for_desired_state - Wait for the desired power state to be * reached @@ -222,30 +234,6 @@ void kbase_pm_reset_done(struct kbase_device *kbdev); * Return: 0 on success, or -ETIMEDOUT code on timeout error. */ int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev); -#else -/** - * kbase_pm_wait_for_desired_state - Wait for the desired power state to be - * reached - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * - * Wait for the L2 and shader power state machines to reach the states - * corresponding to the values of 'l2_desired' and 'shaders_desired'. - * - * The usual use-case for this is to ensure cores are 'READY' after performing - * a GPU Reset. - * - * Unlike kbase_pm_update_state(), the caller must not hold hwaccess_lock, - * because this function will take that lock itself. - * - * NOTE: This may not wait until the correct state is reached if there is a - * power off in progress. To correctly wait for the desired state the caller - * must ensure that this is not the case by, for example, calling - * kbase_pm_wait_for_poweroff_work_complete() - * - * Return: 0 on success, or -ETIMEDOUT error code on timeout error. - */ -int kbase_pm_wait_for_desired_state(struct kbase_device *kbdev); -#endif /** * kbase_pm_killable_wait_for_desired_state - Wait for the desired power state to be @@ -279,7 +267,6 @@ int kbase_pm_killable_wait_for_desired_state(struct kbase_device *kbdev); */ int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev); -#if MALI_USE_CSF /** * kbase_pm_wait_for_cores_down_scale - Wait for the downscaling of shader cores * @@ -308,7 +295,6 @@ int kbase_pm_wait_for_l2_powered(struct kbase_device *kbdev); * Return: 0 on success, error code on error or remaining jiffies on timeout. */ int kbase_pm_wait_for_cores_down_scale(struct kbase_device *kbdev); -#endif /** * kbase_pm_update_dynamic_cores_onoff - Update the L2 and shader power state @@ -534,14 +520,11 @@ void kbase_pm_runtime_term(struct kbase_device *kbdev); * @kbdev: The kbase device structure for the device (must be a valid pointer) * * Enables access to the GPU registers before power management has powered up - * the GPU with kbase_pm_powerup(). + * the GPU. * * This results in the power management callbacks provided in the driver * configuration to get called to turn on power and/or clocks to the GPU. See * kbase_pm_callback_conf. - * - * This should only be used before power management is powered up with - * kbase_pm_powerup() */ void kbase_pm_register_access_enable(struct kbase_device *kbdev); @@ -555,9 +538,6 @@ void kbase_pm_register_access_enable(struct kbase_device *kbdev); * This results in the power management callbacks provided in the driver * configuration to get called to turn off power and/or clocks to the GPU. See * kbase_pm_callback_conf - * - * This should only be used before power management is powered up with - * kbase_pm_powerup() */ void kbase_pm_register_access_disable(struct kbase_device *kbdev); @@ -606,7 +586,6 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev, struct kbasep_pm_metr #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF /** * kbase_platform_dvfs_event - Report utilisation to DVFS code for CSF GPU * @@ -620,24 +599,6 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev, struct kbasep_pm_metr * Return: Returns 0 on failure and non zero on success. */ int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation); -#else -/** - * kbase_platform_dvfs_event - Report utilisation to DVFS code for JM GPU - * - * @kbdev: The kbase device structure for the device (must be a - * valid pointer) - * @utilisation: The current calculated utilisation by the metrics system. - * @util_gl_share: The current calculated gl share of utilisation. - * @util_cl_share: The current calculated cl share of utilisation per core - * group. - * Function provided by platform specific code when DVFS is enabled to allow - * the power management metrics system to report utilisation. - * - * Return: Returns 0 on failure and non zero on success. - */ -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]); -#endif #endif /* CONFIG_MALI_VALHALL_DVFS */ @@ -672,6 +633,28 @@ void kbase_pm_cache_snoop_enable(struct kbase_device *kbdev); */ void kbase_pm_cache_snoop_disable(struct kbase_device *kbdev); +/** + * kbase_pm_ca_set_gov_core_mask - Set governor core mask + * @kbdev: Device pointer. + * @core_mask_type: which mask is being used to update register. + * @core_mask: New core mask. + * + * This function is used to change the available core mask as defined via either sysfs or devfreq. + */ +void kbase_pm_ca_set_gov_core_mask(struct kbase_device *kbdev, enum mask_type core_mask_type, + u64 core_mask); + +/** + * kbase_pm_ca_set_gov_core_mask_nolock - Set governor core mask with lock already taken + * @kbdev: Device pointer. + * @core_mask_type: which mask is being used to update register. + * @core_mask: New core mask. + * + * This function is used to change the available core mask as defined via either sysfs or devfreq. + */ +void kbase_pm_ca_set_gov_core_mask_nolock(struct kbase_device *kbdev, enum mask_type core_mask_type, + u64 core_mask); + #ifdef CONFIG_MALI_VALHALL_DEVFREQ /** * kbase_devfreq_set_core_mask - Set devfreq core mask @@ -704,81 +687,6 @@ void kbase_pm_reset_start_locked(struct kbase_device *kbdev); */ void kbase_pm_reset_complete(struct kbase_device *kbdev); -#if !MALI_USE_CSF -/** - * kbase_pm_protected_override_enable - Enable the protected mode override - * @kbdev: Device pointer - * - * When the protected mode override is enabled, all shader cores are requested - * to power down, and the L2 power state can be controlled by - * kbase_pm_protected_l2_override(). - * - * Caller must hold hwaccess_lock. - */ -void kbase_pm_protected_override_enable(struct kbase_device *kbdev); - -/** - * kbase_pm_protected_override_disable - Disable the protected mode override - * @kbdev: Device pointer - * - * Caller must hold hwaccess_lock. - */ -void kbase_pm_protected_override_disable(struct kbase_device *kbdev); - -/** - * kbase_pm_protected_l2_override - Control the protected mode L2 override - * @kbdev: Device pointer - * @override: true to enable the override, false to disable - * - * When the driver is transitioning in or out of protected mode, the L2 cache is - * forced to power off. This can be overridden to force the L2 cache to power - * on. This is required to change coherency settings on some GPUs. - */ -void kbase_pm_protected_l2_override(struct kbase_device *kbdev, bool override); - -/** - * kbase_pm_protected_entry_override_enable - Enable the protected mode entry - * override - * @kbdev: Device pointer - * - * Initiate a GPU reset and enable the protected mode entry override flag if - * l2_always_on WA is enabled and platform is fully coherent. If the GPU - * reset is already ongoing then protected mode entry override flag will not - * be enabled and function will have to be called again. - * - * When protected mode entry override flag is enabled to power down L2 via GPU - * reset, the GPU reset handling behavior gets changed. For example call to - * kbase_backend_reset() is skipped, Hw counters are not re-enabled and L2 - * isn't powered up again post reset. - * This is needed only as a workaround for a Hw issue where explicit power down - * of L2 causes a glitch. For entering protected mode on fully coherent - * platforms L2 needs to be powered down to switch to IO coherency mode, so to - * avoid the glitch GPU reset is used to power down L2. Hence, this function - * does nothing on systems where the glitch issue isn't present. - * - * Caller must hold hwaccess_lock. Should be only called during the transition - * to enter protected mode. - * - * Return: -EAGAIN if a GPU reset was required for the glitch workaround but - * was already ongoing, otherwise 0. - */ -int kbase_pm_protected_entry_override_enable(struct kbase_device *kbdev); - -/** - * kbase_pm_protected_entry_override_disable - Disable the protected mode entry - * override - * @kbdev: Device pointer - * - * This shall be called once L2 has powered down and switch to IO coherency - * mode has been made. As with kbase_pm_protected_entry_override_enable(), - * this function does nothing on systems where the glitch issue isn't present. - * - * Caller must hold hwaccess_lock. Should be only called during the transition - * to enter protected mode. - */ -void kbase_pm_protected_entry_override_disable(struct kbase_device *kbdev); -#endif - /* If true, the driver should explicitly control corestack power management, * instead of relying on the Power Domain Controller. */ @@ -795,7 +703,6 @@ extern bool corestack_driver_control; */ bool kbase_pm_is_l2_desired(struct kbase_device *kbdev); -#if MALI_USE_CSF /** * kbase_pm_is_mcu_desired - Check whether MCU is desired * @@ -821,8 +728,6 @@ bool kbase_pm_is_mcu_desired(struct kbase_device *kbdev); */ bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, enum kbase_mcu_state state); -#ifdef KBASE_PM_RUNTIME - /** * kbase_pm_enable_mcu_db_notification - Enable the Doorbell notification on * MCU side @@ -834,8 +739,6 @@ bool kbase_pm_is_mcu_inactive(struct kbase_device *kbdev, enum kbase_mcu_state s */ void kbase_pm_enable_mcu_db_notification(struct kbase_device *kbdev); -#endif /* KBASE_PM_RUNTIME */ - /** * kbase_pm_idle_groups_sched_suspendable - Check whether the scheduler can be * suspended to low power state when all @@ -907,8 +810,6 @@ static inline bool kbase_pm_mcu_is_in_desired_state(struct kbase_device *kbdev) return in_desired_state; } -#endif - /** * kbase_pm_l2_is_in_desired_state - Check if L2 is in stable ON/OFF state. * @@ -937,9 +838,6 @@ static inline bool kbase_pm_l2_is_in_desired_state(struct kbase_device *kbdev) */ static inline void kbase_pm_lock(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - mutex_lock(&kbdev->js_data.runpool_mutex); -#endif /* !MALI_USE_CSF */ mutex_lock(&kbdev->pm.lock); } @@ -951,12 +849,8 @@ static inline void kbase_pm_lock(struct kbase_device *kbdev) static inline void kbase_pm_unlock(struct kbase_device *kbdev) { mutex_unlock(&kbdev->pm.lock); -#if !MALI_USE_CSF - mutex_unlock(&kbdev->js_data.runpool_mutex); -#endif /* !MALI_USE_CSF */ } -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) /** * kbase_pm_gpu_sleep_allowed - Check if the GPU is allowed to be put in sleep * @@ -978,8 +872,10 @@ static inline bool kbase_pm_gpu_sleep_allowed(struct kbase_device *kbdev) * A high positive value of autosuspend_delay can be used to keep the * GPU in sleep state for a long time. */ +#if IS_ENABLED(CONFIG_PM) if (unlikely(kbdev->dev->power.autosuspend_delay <= 0)) return false; +#endif return test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed); } @@ -997,8 +893,10 @@ static inline bool kbase_pm_gpu_sleep_allowed(struct kbase_device *kbdev) */ static inline bool kbase_pm_fw_sleep_on_idle_allowed(struct kbase_device *kbdev) { +#if IS_ENABLED(CONFIG_PM) if (unlikely(kbdev->dev->power.autosuspend_delay <= 0)) return false; +#endif return kbdev->pm.backend.gpu_sleep_allowed == KBASE_GPU_FW_SLEEP_ON_IDLE_ALLOWED; } @@ -1049,7 +947,6 @@ static inline void kbase_pm_disable_db_mirror_interrupt(struct kbase_device *kbd kbdev->pm.backend.db_mirror_interrupt_enabled = false; } } -#endif /** * kbase_pm_l2_allow_mmu_page_migration - L2 state allows MMU page migration or not @@ -1074,7 +971,12 @@ static inline bool kbase_pm_l2_allow_mmu_page_migration(struct kbase_device *kbd return (backend->l2_state != KBASE_L2_PEND_ON && backend->l2_state != KBASE_L2_PEND_OFF); } -#if MALI_USE_CSF +#if MALI_UNIT_TEST +int delegate_pm_domain_control_to_fw(struct kbase_device *kbdev, u32 pm_domain); + +int retract_pm_domain_control_from_fw(struct kbase_device *kbdev, u32 pm_domain); +#endif + /** * kbase_pm_get_domain_status - get pm domain status for particular endpoint * @@ -1089,6 +991,5 @@ static inline bool kbase_pm_l2_allow_mmu_page_migration(struct kbase_device *kbd */ int kbase_pm_get_domain_status(struct kbase_device *kbdev, u32 pm_domain, u32 endpoint, u32 *domain_status); -#endif /* MALI_USE_CSF */ #endif /* _KBASE_BACKEND_PM_INTERNAL_H_ */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_metrics.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_metrics.c index 4822e64f645f..2966a94efe65 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_metrics.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_metrics.c @@ -28,17 +28,13 @@ #include #include -#if MALI_USE_CSF #include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h" #include -#else -#include -#endif /* !MALI_USE_CSF */ #include #include -#if defined(CONFIG_MALI_VALHALL_DEVFREQ) || defined(CONFIG_MALI_VALHALL_DVFS) || !MALI_USE_CSF +#if defined(CONFIG_MALI_VALHALL_DEVFREQ) || defined(CONFIG_MALI_VALHALL_DVFS) /* Shift used for kbasep_pm_metrics_data.time_busy/idle - units of (1 << 8) ns * This gives a maximum period between samples of 2^(32+8)/100 ns = slightly * under 11s. Exceeding this will cause overflow @@ -46,10 +42,8 @@ #define KBASE_PM_TIME_SHIFT 8 #endif -#if MALI_USE_CSF /* To get the GPU_ACTIVE value in nano seconds unit */ #define GPU_ACTIVE_SCALING_FACTOR ((u64)1E9) -#endif /* * Possible state transitions @@ -101,7 +95,6 @@ static enum hrtimer_restart dvfs_callback(struct hrtimer *timer) int kbasep_pm_metrics_init(struct kbase_device *kbdev) { -#if MALI_USE_CSF struct kbase_ipa_control_perf_counter perf_counter; int err; @@ -129,11 +122,6 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev) dev_err(kbdev->dev, "Failed to register IPA with kbase_ipa_control: err=%d", err); return -1; } -#else - KBASE_DEBUG_ASSERT(kbdev != NULL); - kbdev->pm.backend.metrics.kbdev = kbdev; - kbdev->pm.backend.metrics.time_period_start = ktime_get_raw(); -#endif spin_lock_init(&kbdev->pm.backend.metrics.lock); #ifdef CONFIG_MALI_VALHALL_DVFS @@ -144,13 +132,11 @@ int kbasep_pm_metrics_init(struct kbase_device *kbdev) kbase_pm_metrics_start(kbdev); #endif /* CONFIG_MALI_VALHALL_DVFS */ -#if MALI_USE_CSF /* The sanity check on the GPU_ACTIVE performance counter * is skipped for Juno platforms that have timing problems. */ kbdev->pm.backend.metrics.skip_gpu_active_sanity_check = (kbdev->gpu_props.impl_tech >= THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_FPGA); -#endif return 0; } @@ -167,11 +153,7 @@ void kbasep_pm_metrics_term(struct kbase_device *kbdev) hrtimer_cancel(&kbdev->pm.backend.metrics.timer); #endif /* CONFIG_MALI_VALHALL_DVFS */ -#if MALI_USE_CSF kbase_ipa_control_unregister(kbdev, kbdev->pm.backend.metrics.ipa_control_client); -#else - CSTD_UNUSED(kbdev); -#endif } KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term); @@ -179,7 +161,6 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term); /* caller needs to hold kbdev->pm.backend.metrics.lock before calling this * function */ -#if MALI_USE_CSF #if defined(CONFIG_MALI_VALHALL_DEVFREQ) || defined(CONFIG_MALI_VALHALL_DVFS) static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev) { @@ -284,39 +265,6 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev) kbdev->pm.backend.metrics.time_period_start = now; } #endif /* defined(CONFIG_MALI_VALHALL_DEVFREQ) || defined(CONFIG_MALI_VALHALL_DVFS) */ -#else -static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev, ktime_t now) -{ - ktime_t diff; - - lockdep_assert_held(&kbdev->pm.backend.metrics.lock); - - diff = ktime_sub(now, kbdev->pm.backend.metrics.time_period_start); - if (ktime_to_ns(diff) < 0) - return; - - if (kbdev->pm.backend.metrics.gpu_active) { - u32 ns_time = (u32)(ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); - - kbdev->pm.backend.metrics.values.time_busy += ns_time; - if (kbdev->pm.backend.metrics.active_cl_ctx[0]) - kbdev->pm.backend.metrics.values.busy_cl[0] += ns_time; - if (kbdev->pm.backend.metrics.active_cl_ctx[1]) - kbdev->pm.backend.metrics.values.busy_cl[1] += ns_time; - if (kbdev->pm.backend.metrics.active_gl_ctx[0]) - kbdev->pm.backend.metrics.values.busy_gl += ns_time; - if (kbdev->pm.backend.metrics.active_gl_ctx[1]) - kbdev->pm.backend.metrics.values.busy_gl += ns_time; - if (kbdev->pm.backend.metrics.active_gl_ctx[2]) - kbdev->pm.backend.metrics.values.busy_gl += ns_time; - } else { - kbdev->pm.backend.metrics.values.time_idle += - (u32)(ktime_to_ns(diff) >> KBASE_PM_TIME_SHIFT); - } - - kbdev->pm.backend.metrics.time_period_start = now; -} -#endif /* MALI_USE_CSF */ #if defined(CONFIG_MALI_VALHALL_DEVFREQ) || defined(CONFIG_MALI_VALHALL_DVFS) void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev, struct kbasep_pm_metrics *last, @@ -326,23 +274,13 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev, struct kbasep_pm_metr unsigned long flags; spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); -#if MALI_USE_CSF kbase_pm_get_dvfs_utilisation_calc(kbdev); -#else - kbase_pm_get_dvfs_utilisation_calc(kbdev, ktime_get_raw()); -#endif memset(diff, 0, sizeof(*diff)); diff->time_busy = cur->time_busy - last->time_busy; diff->time_idle = cur->time_idle - last->time_idle; -#if MALI_USE_CSF diff->time_in_protm = cur->time_in_protm - last->time_in_protm; -#else - diff->busy_cl[0] = cur->busy_cl[0] - last->busy_cl[0]; - diff->busy_cl[1] = cur->busy_cl[1] - last->busy_cl[1]; - diff->busy_gl = cur->busy_gl - last->busy_gl; -#endif *last = *cur; @@ -356,11 +294,6 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) { int utilisation; struct kbasep_pm_metrics *diff; -#if !MALI_USE_CSF - int busy; - int util_gl_share; - int util_cl_share[2]; -#endif KBASE_DEBUG_ASSERT(kbdev != NULL); @@ -370,15 +303,6 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) utilisation = (100 * diff->time_busy) / max(diff->time_busy + diff->time_idle, 1u); -#if !MALI_USE_CSF - busy = max(diff->busy_gl + diff->busy_cl[0] + diff->busy_cl[1], 1u); - - util_gl_share = (100 * diff->busy_gl) / busy; - util_cl_share[0] = (100 * diff->busy_cl[0]) / busy; - util_cl_share[1] = (100 * diff->busy_cl[1]) / busy; - - kbase_platform_dvfs_event(kbdev, utilisation, util_gl_share, util_cl_share); -#else /* Note that, at present, we don't pass protected-mode time to the * platform here. It's unlikely to be useful, however, as the platform * probably just cares whether the GPU is busy or not; time in @@ -386,7 +310,6 @@ void kbase_pm_get_dvfs_action(struct kbase_device *kbdev) * so we should be good. */ kbase_platform_dvfs_event(kbdev, utilisation); -#endif } bool kbase_pm_metrics_is_active(struct kbase_device *kbdev) @@ -421,77 +344,3 @@ void kbase_pm_metrics_stop(struct kbase_device *kbdev) } #endif /* CONFIG_MALI_VALHALL_DVFS */ - -#if !MALI_USE_CSF -/** - * kbase_pm_metrics_active_calc - Update PM active counts based on currently - * running atoms - * @kbdev: Device pointer - * - * The caller must hold kbdev->pm.backend.metrics.lock - */ -static void kbase_pm_metrics_active_calc(struct kbase_device *kbdev) -{ - unsigned int js; - - lockdep_assert_held(&kbdev->pm.backend.metrics.lock); - - kbdev->pm.backend.metrics.active_gl_ctx[0] = 0; - kbdev->pm.backend.metrics.active_gl_ctx[1] = 0; - kbdev->pm.backend.metrics.active_gl_ctx[2] = 0; - kbdev->pm.backend.metrics.active_cl_ctx[0] = 0; - kbdev->pm.backend.metrics.active_cl_ctx[1] = 0; - kbdev->pm.backend.metrics.gpu_active = false; - - for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { - struct kbase_jd_atom *katom = kbase_gpu_inspect(kbdev, js, 0); - - /* Head atom may have just completed, so if it isn't running - * then try the next atom - */ - if (katom && katom->gpu_rb_state != KBASE_ATOM_GPU_RB_SUBMITTED) - katom = kbase_gpu_inspect(kbdev, js, 1); - - if (katom && katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) { - if (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { - u32 device_nr = - (katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) ? - katom->device_nr : - 0; - if (!WARN_ON(device_nr >= 2)) - kbdev->pm.backend.metrics.active_cl_ctx[device_nr] = 1; - } else { - kbdev->pm.backend.metrics.active_gl_ctx[js] = 1; - trace_sysgraph(SGR_ACTIVE, 0, js); - } - kbdev->pm.backend.metrics.gpu_active = true; - } else { - trace_sysgraph(SGR_INACTIVE, 0, js); - } - } -} - -/* called when job is submitted to or removed from a GPU slot */ -void kbase_pm_metrics_update(struct kbase_device *kbdev, ktime_t *timestamp) -{ - unsigned long flags; - ktime_t now; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - spin_lock_irqsave(&kbdev->pm.backend.metrics.lock, flags); - - if (!timestamp) { - now = ktime_get_raw(); - timestamp = &now; - } - - /* Track how much of time has been spent busy or idle. For JM GPUs, - * this also evaluates how long CL and/or GL jobs have been busy for. - */ - kbase_pm_get_dvfs_utilisation_calc(kbdev, *timestamp); - - kbase_pm_metrics_active_calc(kbdev); - spin_unlock_irqrestore(&kbdev->pm.backend.metrics.lock, flags); -} -#endif /* !MALI_USE_CSF */ diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_policy.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_policy.c index 4ad6f703ad67..78e3ebef0ecc 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_policy.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_policy.c @@ -30,7 +30,7 @@ #include #include -#if MALI_USE_CSF && defined CONFIG_MALI_VALHALL_DEBUG +#if defined CONFIG_MALI_VALHALL_DEBUG #include #endif @@ -64,7 +64,7 @@ void kbase_pm_policy_init(struct kbase_device *kbdev) } } -#if MALI_USE_CSF && defined(CONFIG_MALI_VALHALL_DEBUG) +#if defined(CONFIG_MALI_VALHALL_DEBUG) /* Use always_on policy if module param fw_debug=1 is * passed, to aid firmware debugging. */ @@ -74,24 +74,19 @@ void kbase_pm_policy_init(struct kbase_device *kbdev) default_policy->init(kbdev); -#if MALI_USE_CSF spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbdev->pm.backend.pm_current_policy = default_policy; kbdev->pm.backend.csf_pm_sched_flags = default_policy->pm_sched_flags; -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_idle_groups_sched_suspendable(kbdev)) - clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); - else - set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); -#endif /* KBASE_PM_RUNTIME */ + if (IS_ENABLED(CONFIG_PM)) { + if (kbase_pm_idle_groups_sched_suspendable(kbdev)) + clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, + &kbdev->pm.backend.gpu_sleep_allowed); + else + set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); + } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - -#else - CSTD_UNUSED(flags); - kbdev->pm.backend.pm_current_policy = default_policy; -#endif } void kbase_pm_policy_term(struct kbase_device *kbdev) @@ -123,7 +118,6 @@ void kbase_pm_update_active(struct kbase_device *kbdev) if (!pm->backend.invoke_poweroff_wait_wq_when_l2_off && pm->backend.poweroff_wait_in_progress) { KBASE_DEBUG_ASSERT(kbase_io_is_gpu_powered(kbdev)); -#if MALI_USE_CSF if (likely(!pm->backend.waiting_for_mmu_fault_handling)) { /* L2 has been powered off. Invoke the state machine to power * up the L2 cache and also effectively cancel the GPU power off @@ -137,7 +131,6 @@ void kbase_pm_update_active(struct kbase_device *kbdev) wake_up(&kbdev->pm.backend.poweroff_wait); return; } -#endif pm->backend.poweron_required = true; spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } else { @@ -151,9 +144,7 @@ void kbase_pm_update_active(struct kbase_device *kbdev) pm->backend.invoke_poweroff_wait_wq_when_l2_off = false; pm->backend.poweroff_wait_in_progress = false; pm->backend.l2_desired = true; -#if MALI_USE_CSF pm->backend.mcu_desired = true; -#endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); kbase_pm_do_poweron(kbdev, false); @@ -190,7 +181,6 @@ void kbase_pm_update_dynamic_cores_onoff(struct kbase_device *kbdev) if (kbdev->pm.backend.poweroff_wait_in_progress) return; -#if MALI_USE_CSF CSTD_UNUSED(shaders_desired); /* Invoke the MCU state machine to send a request to FW for updating * the mask of shader cores that can be used for allocation of @@ -198,18 +188,6 @@ void kbase_pm_update_dynamic_cores_onoff(struct kbase_device *kbdev) */ if (kbase_pm_is_mcu_desired(kbdev)) kbase_pm_update_state(kbdev); -#else - /* In protected transition, don't allow outside shader core request - * affect transition, return directly - */ - if (kbdev->pm.backend.protected_transition_override) - return; - - shaders_desired = kbdev->pm.backend.pm_current_policy->shaders_needed(kbdev); - - if (shaders_desired && kbase_pm_is_l2_desired(kbdev)) - kbase_pm_update_state(kbdev); -#endif } void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev) @@ -223,16 +201,6 @@ void kbase_pm_update_cores_state_nolock(struct kbase_device *kbdev) if (kbdev->pm.backend.poweroff_wait_in_progress) return; -#if !MALI_USE_CSF - if (kbdev->pm.backend.protected_transition_override) - /* We are trying to change in/out of protected mode - force all - * cores off so that the L2 powers down - */ - shaders_desired = false; - else - shaders_desired = kbdev->pm.backend.pm_current_policy->shaders_needed(kbdev); -#endif - if (kbdev->pm.backend.shaders_desired != shaders_desired) { KBASE_KTRACE_ADD(kbdev, PM_CORES_CHANGE_DESIRED, NULL, kbdev->pm.backend.shaders_desired); @@ -274,7 +242,6 @@ const struct kbase_pm_policy *kbase_pm_get_policy(struct kbase_device *kbdev) KBASE_EXPORT_TEST_API(kbase_pm_get_policy); -#if MALI_USE_CSF static int policy_change_wait_for_L2_off(struct kbase_device *kbdev) { long remaining; @@ -308,13 +275,11 @@ static int policy_change_wait_for_L2_off(struct kbase_device *kbdev) return err; } -#endif void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_policy *new_policy) { const struct kbase_pm_policy *old_policy; unsigned long flags; -#if MALI_USE_CSF unsigned int new_policy_csf_pm_sched_flags; bool sched_suspend; bool reset_gpu = false; @@ -322,14 +287,12 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic struct kbase_csf_scheduler *scheduler = NULL; u64 pwroff_ns; bool switching_to_always_on; -#endif KBASE_DEBUG_ASSERT(kbdev != NULL); KBASE_DEBUG_ASSERT(new_policy != NULL); KBASE_KTRACE_ADD(kbdev, PM_SET_POLICY, NULL, new_policy->id); -#if MALI_USE_CSF pwroff_ns = kbase_csf_firmware_get_mcu_core_pwroff_time(kbdev); switching_to_always_on = new_policy == &kbase_pm_always_on_policy_ops; if (pwroff_ns == 0 && !switching_to_always_on) { @@ -392,7 +355,6 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic if (sched_suspend) reset_gpu = policy_change_wait_for_L2_off(kbdev); -#endif kbase_pm_lock(kbdev); @@ -424,19 +386,19 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbdev->pm.backend.pm_current_policy = new_policy; -#if MALI_USE_CSF kbdev->pm.backend.csf_pm_sched_flags = new_policy_csf_pm_sched_flags; /* New policy in place, release the clamping on mcu/L2 off state */ kbdev->pm.backend.policy_change_clamp_state_to_off = false; kbase_pm_update_state(kbdev); -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_idle_groups_sched_suspendable(kbdev)) - clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); - else - set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); -#endif /* KBASE_PM_RUNTIME */ -#endif + if (IS_ENABLED(CONFIG_PM)) { + if (kbase_pm_idle_groups_sched_suspendable(kbdev)) + clear_bit(KBASE_GPU_IGNORE_IDLE_EVENT, + &kbdev->pm.backend.gpu_sleep_allowed); + else + set_bit(KBASE_GPU_IGNORE_IDLE_EVENT, &kbdev->pm.backend.gpu_sleep_allowed); + } + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* If any core power state changes were previously attempted, but @@ -452,7 +414,6 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic kbase_pm_context_idle_locked(kbdev); kbase_pm_unlock(kbdev); -#if MALI_USE_CSF /* Reverse the suspension done */ if (sched_suspend) kbase_csf_scheduler_pm_resume_no_lock(kbdev); @@ -469,7 +430,6 @@ void kbase_pm_set_policy(struct kbase_device *kbdev, const struct kbase_pm_polic } mutex_unlock(&kbdev->pm.backend.policy_change_lock); -#endif } KBASE_EXPORT_TEST_API(kbase_pm_set_policy); diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_shader_states.h b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_shader_states.h index 8622ef78d363..84f1cbbcc95b 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_shader_states.h +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_pm_shader_states.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -42,11 +42,6 @@ * @WAIT_OFF_CORESTACK_ON: The shaders have been requested to power * off, but they remain on for the duration * of the hysteresis timer - * @WAIT_GPU_IDLE: The shaders partial poweroff needs to - * reach a state where jobs on the GPU are - * finished including jobs currently running - * and in the GPU queue because of - * GPU2017-861 * @WAIT_FINISHED_CORESTACK_ON: The hysteresis timer has expired * @L2_FLUSHING_CORESTACK_ON: The core stacks are on and the level 2 * cache is being flushed. @@ -67,9 +62,6 @@ KBASEP_SHADER_STATE(PEND_ON_CORESTACK_ON) KBASEP_SHADER_STATE(ON_CORESTACK_ON) KBASEP_SHADER_STATE(ON_CORESTACK_ON_RECHECK) KBASEP_SHADER_STATE(WAIT_OFF_CORESTACK_ON) -#if !MALI_USE_CSF -KBASEP_SHADER_STATE(WAIT_GPU_IDLE) -#endif /* !MALI_USE_CSF */ KBASEP_SHADER_STATE(WAIT_FINISHED_CORESTACK_ON) KBASEP_SHADER_STATE(L2_FLUSHING_CORESTACK_ON) KBASEP_SHADER_STATE(READY_OFF_CORESTACK_ON) diff --git a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_time.c b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_time.c index 0d00c2e7b5c0..5c7ec2b9c47d 100644 --- a/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_time.c +++ b/drivers/gpu/arm/valhall/backend/gpu/mali_kbase_time.c @@ -310,6 +310,9 @@ KBASE_EXPORT_TEST_API(kbase_get_timeout_ms); u64 kbase_backend_get_cycle_cnt(struct kbase_device *kbdev) { + if (kbase_io_is_aw_removed(kbdev)) + return 0; + return kbase_reg_read64_coherent(kbdev, GPU_CONTROL_ENUM(CYCLE_COUNT)); } @@ -330,6 +333,36 @@ u64 kbase_arch_timer_get_cntfrq(struct kbase_device *kbdev) return freq; } +static int kbase_gpu_timestamp_offset_read(void *data, u64 *val) +{ + struct kbase_device *kbdev = (struct kbase_device *)data; + + if (kbdev->backend_time.gpu_timestamp_offset == GPU_TIMESTAMP_OFFSET_INVALID) + return -EINVAL; + + *val = kbdev->backend_time.gpu_timestamp_offset; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(timestamp_offset_debugfs_fops, kbase_gpu_timestamp_offset_read, NULL, + "%lld\n"); + +void kbase_gpu_timestamp_offset_debugfs_init(struct kbase_device *kbdev) +{ + struct dentry *timestamp_offset_file; + + if (unlikely(!kbdev)) { + pr_warn("%s: kbdev is NULL\n", __func__); + return; + } + + timestamp_offset_file = debugfs_create_file("gpu_timestamp_offset", 0400, + kbdev->mali_debugfs_directory, kbdev, + ×tamp_offset_debugfs_fops); + if (IS_ERR_OR_NULL(timestamp_offset_file)) + dev_warn(kbdev->dev, "Failed to create gpu_timestamp_offset debugfs entry"); +} int kbase_backend_time_init(struct kbase_device *kbdev) { diff --git a/drivers/gpu/arm/valhall/build.bp b/drivers/gpu/arm/valhall/build.bp index 139632595381..5b72e1b17bc6 100644 --- a/drivers/gpu/arm/valhall/build.bp +++ b/drivers/gpu/arm/valhall/build.bp @@ -117,7 +117,6 @@ bob_defaults { "CONFIG_MALI_VALHALL_PLATFORM_NAME={{.mali_platform_name}}", "MALI_CUSTOMER_RELEASE={{.release}}", "MALI_UNIT_TEST={{.unit_test_code}}", - "MALI_USE_CSF={{.gpu_has_csf}}", "MALI_JIT_PRESSURE_LIMIT_BASE={{.jit_pressure_limit_base}}", // Start of CS experimental features definitions. @@ -133,7 +132,6 @@ bob_defaults { // is an umbrella feature that would be open for inappropriate use // (catch-all for experimental CS code without separating it into // different features). - "MALI_BASE_CSF_PERFORMANCE_TESTS={{.base_csf_performance_tests}}", ], } diff --git a/drivers/gpu/arm/valhall/context/Kbuild b/drivers/gpu/arm/valhall/context/Kbuild index 057693c40a30..cfc152edd81a 100644 --- a/drivers/gpu/arm/valhall/context/Kbuild +++ b/drivers/gpu/arm/valhall/context/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2012-2013, 2016-2017, 2020-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2012-2013, 2016-2017, 2020-2021, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -18,10 +18,6 @@ # # -valhall_kbase-y += context/mali_kbase_context.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += context/backend/mali_kbase_context_csf.o -else - valhall_kbase-y += context/backend/mali_kbase_context_jm.o -endif +valhall_kbase-y += \ + context/mali_kbase_context.o \ + context/backend/mali_kbase_context_csf.o diff --git a/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_csf.c b/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_csf.c index fe1dbfaca872..44cf8aba9b8f 100644 --- a/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_csf.c +++ b/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_csf.c @@ -91,6 +91,8 @@ static const struct kbase_context_init context_init[] = { "Common context initialization failed" }, { kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term, "Memory pool group initialization failed" }, + { kbase_context_pgd_mem_pool_init, kbase_context_pgd_mem_pool_term, + "pgd memory pool initialization failed" }, { kbase_mem_evictable_init, kbase_mem_evictable_deinit, "Memory evictable initialization failed" }, { kbase_ctx_sched_init_ctx, NULL, NULL }, @@ -207,6 +209,7 @@ void kbase_destroy_context(struct kbase_context *kctx) wait_event(kbdev->pm.resume_wait, !kbase_pm_is_resuming(kbdev)); kbase_mem_pool_group_mark_dying(&kctx->mem_pools); + kbase_mem_pool_mark_dying(&kctx->pgd_mem_pool); kbase_context_term_partial(kctx, ARRAY_SIZE(context_init)); diff --git a/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_jm.c b/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_jm.c deleted file mode 100644 index ef474f625f63..000000000000 --- a/drivers/gpu/arm/valhall/context/backend/mali_kbase_context_jm.c +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Base kernel context APIs for Job Manager GPUs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if IS_ENABLED(CONFIG_DEBUG_FS) -#include -#include -#include -#include - -void kbase_context_debugfs_init(struct kbase_context *const kctx) -{ - kbase_debug_mem_view_init(kctx); - kbase_debug_mem_zones_init(kctx); - kbase_debug_mem_allocs_init(kctx); - kbase_mem_pool_debugfs_init(kctx->kctx_dentry, kctx); - kbase_jit_debugfs_init(kctx); - kbasep_jd_debugfs_ctx_init(kctx); -} -KBASE_EXPORT_SYMBOL(kbase_context_debugfs_init); - -void kbase_context_debugfs_term(struct kbase_context *const kctx) -{ - debugfs_remove_recursive(kctx->kctx_dentry); -} -KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term); -#else -void kbase_context_debugfs_init(struct kbase_context *const kctx) -{ - CSTD_UNUSED(kctx); -} -KBASE_EXPORT_SYMBOL(kbase_context_debugfs_init); - -void kbase_context_debugfs_term(struct kbase_context *const kctx) -{ - CSTD_UNUSED(kctx); -} -KBASE_EXPORT_SYMBOL(kbase_context_debugfs_term); -#endif /* CONFIG_DEBUG_FS */ - -static int kbase_context_kbase_kinstr_jm_init(struct kbase_context *kctx) -{ - return kbase_kinstr_jm_init(&kctx->kinstr_jm); -} - -static void kbase_context_kbase_kinstr_jm_term(struct kbase_context *kctx) -{ - kbase_kinstr_jm_term(kctx->kinstr_jm); -} - -static int kbase_context_kbase_timer_setup(struct kbase_context *kctx) -{ - kbase_timer_setup(&kctx->soft_job_timeout, kbasep_soft_job_timeout_worker); - - return 0; -} - -static int kbase_context_submit_check(struct kbase_context *kctx) -{ - struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; - unsigned long irq_flags = 0; - - base_context_create_flags const flags = kctx->create_flags; - - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags); - - /* Translate the flags */ - if ((flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0) - kbase_ctx_flag_clear(kctx, KCTX_SUBMIT_DISABLED); - - spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - return 0; -} - -static void kbase_context_flush_jobs(struct kbase_context *kctx) -{ - kbase_jd_zap_context(kctx); - flush_workqueue(kctx->jctx.job_done_wq); -} - -/** - * kbase_context_free - Free kcontext at its destruction - * - * @kctx: kcontext to be freed - */ -static void kbase_context_free(struct kbase_context *kctx) -{ - kbase_timeline_post_kbase_context_destroy(kctx); - - vfree(kctx); -} - -static const struct kbase_context_init context_init[] = { - { NULL, kbase_context_free, NULL }, - { kbase_context_common_init, kbase_context_common_term, - "Common context initialization failed" }, - { kbase_context_mem_pool_group_init, kbase_context_mem_pool_group_term, - "Memory pool group initialization failed" }, - { kbase_mem_evictable_init, kbase_mem_evictable_deinit, - "Memory evictable initialization failed" }, - { kbase_ctx_sched_init_ctx, NULL, NULL }, - { kbase_context_mmu_init, kbase_context_mmu_term, "MMU initialization failed" }, - { kbase_context_mem_alloc_page, kbase_context_mem_pool_free, "Memory alloc page failed" }, - { kbase_region_tracker_init, kbase_region_tracker_term, - "Region tracker initialization failed" }, - { kbase_sticky_resource_init, kbase_context_sticky_resource_term, - "Sticky resource initialization failed" }, - { kbase_jit_init, kbase_jit_term, "JIT initialization failed" }, - { kbase_context_kbase_kinstr_jm_init, kbase_context_kbase_kinstr_jm_term, - "JM instrumentation initialization failed" }, - { kbase_context_kbase_timer_setup, NULL, "Timers initialization failed" }, - { kbase_event_init, kbase_event_cleanup, "Event initialization failed" }, - { kbasep_js_kctx_init, kbasep_js_kctx_term, "JS kctx initialization failed" }, - { kbase_jd_init, kbase_jd_exit, "JD initialization failed" }, - { kbase_context_submit_check, NULL, "Enabling job submission failed" }, -#if IS_ENABLED(CONFIG_DEBUG_FS) - { kbase_debug_job_fault_context_init, kbase_debug_job_fault_context_term, - "Job fault context initialization failed" }, -#endif - { kbasep_platform_context_init, kbasep_platform_context_term, - "Platform callback for kctx initialization failed" }, - { NULL, kbase_context_flush_jobs, NULL }, - { kbase_context_add_to_dev_list, kbase_context_remove_from_dev_list, - "Adding kctx to device failed" }, -}; - -static void kbase_context_term_partial(struct kbase_context *kctx, unsigned int i) -{ - while (i-- > 0) { - if (context_init[i].term) - context_init[i].term(kctx); - } -} - -struct kbase_context *kbase_create_context(struct kbase_device *kbdev, bool is_compat, - base_context_create_flags const flags, - unsigned long const api_version, struct file *const filp) -{ - struct kbase_context *kctx; - unsigned int i = 0; - - if (WARN_ON(!kbdev)) - return NULL; - - /* Validate flags */ - if (WARN_ON(flags != (flags & BASEP_CONTEXT_CREATE_KERNEL_FLAGS))) - return NULL; - - /* zero-inited as lot of code assume it's zero'ed out on create */ - kctx = vzalloc(sizeof(*kctx)); - if (WARN_ON(!kctx)) - return NULL; - - kctx->kbdev = kbdev; - kctx->api_version = api_version; - kctx->filp = filp; - kctx->create_flags = flags; - - if (is_compat) - kbase_ctx_flag_set(kctx, KCTX_COMPAT); -#if defined(CONFIG_64BIT) - else - kbase_ctx_flag_set(kctx, KCTX_FORCE_SAME_VA); -#endif /* defined(CONFIG_64BIT) */ - - for (i = 0; i < ARRAY_SIZE(context_init); i++) { - int err = 0; - - if (context_init[i].init) - err = context_init[i].init(kctx); - - if (err) { - dev_err(kbdev->dev, "%s error = %d\n", context_init[i].err_mes, err); - - /* kctx should be freed by kbase_context_free(). - * Otherwise it will result in memory leak. - */ - WARN_ON(i == 0); - - kbase_context_term_partial(kctx, i); - return NULL; - } - } - - return kctx; -} -KBASE_EXPORT_SYMBOL(kbase_create_context); - -void kbase_destroy_context(struct kbase_context *kctx) -{ - struct kbase_device *kbdev; - - if (WARN_ON(!kctx)) - return; - - kbdev = kctx->kbdev; - if (WARN_ON(!kbdev)) - return; - - /* Context termination could happen whilst the system suspend of - * the GPU device is ongoing or has completed. It has been seen on - * Customer side that a hang could occur if context termination is - * not blocked until the resume of GPU device. - */ - if (kbase_has_arbiter(kbdev)) - atomic_inc(&kbdev->pm.gpu_users_waiting); - while (kbase_pm_context_active_handle_suspend(kbdev, - KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) { - dev_dbg(kbdev->dev, "Suspend in progress when destroying context"); - wait_event(kbdev->pm.resume_wait, !kbase_pm_is_suspending(kbdev)); - } - - /* Have synchronized against the System suspend and incremented the - * pm.active_count. So any subsequent invocation of System suspend - * callback would get blocked. - * If System suspend callback was already in progress then the above loop - * would have waited till the System resume callback has begun. - * So wait for the System resume callback to also complete as we want to - * avoid context termination during System resume also. - */ - wait_event(kbdev->pm.resume_wait, !kbase_pm_is_resuming(kbdev)); - - if (kbase_has_arbiter(kbdev)) - atomic_dec(&kbdev->pm.gpu_users_waiting); - - kbase_mem_pool_group_mark_dying(&kctx->mem_pools); - - kbase_context_term_partial(kctx, ARRAY_SIZE(context_init)); - - kbase_pm_context_idle(kbdev); -} -KBASE_EXPORT_SYMBOL(kbase_destroy_context); diff --git a/drivers/gpu/arm/valhall/context/mali_kbase_context.c b/drivers/gpu/arm/valhall/context/mali_kbase_context.c index 5126f3f6d82a..d0283d2817ce 100644 --- a/drivers/gpu/arm/valhall/context/mali_kbase_context.c +++ b/drivers/gpu/arm/valhall/context/mali_kbase_context.c @@ -72,6 +72,74 @@ static struct kbase_process *find_process_node(struct rb_node *node, pid_t tgid) return kprcs; } +static ssize_t kbase_kctx_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) +{ + struct kobj_attribute *kattr = container_of(attr, struct kobj_attribute, attr); + + if (kattr->show) + return kattr->show(kobj, kattr, buf); + + return -EIO; +} + +static ssize_t kbase_total_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kprcs->total_gpu_pages << PAGE_SHIFT); +} + +static ssize_t kbase_private_gpu_mem_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct kbase_process *kprcs = container_of(kobj, struct kbase_process, kobj); + struct kbase_context *tmp_kctx; + size_t total_pages = 0; + + /* Sum up used_pages from all contexts in the process */ + list_for_each_entry(tmp_kctx, &kprcs->kctx_list, kprcs_link) { + total_pages += atomic_read(&tmp_kctx->used_pages); + } + + return scnprintf(buf, PAGE_SIZE, "%zu\n", total_pages << PAGE_SHIFT); +} + +static struct kobj_attribute kbase_total_gpu_mem_attr = { + .attr = { + .name = "total_gpu_mem", + .mode = 0444, + }, + .show = kbase_total_gpu_mem_show, + .store = NULL, +}; + +static struct kobj_attribute kbase_private_gpu_mem_attr = { + .attr = { + .name = "private_gpu_mem", + .mode = 0444, + }, + .show = kbase_private_gpu_mem_show, + .store = NULL, +}; + +static struct attribute *kbase_kctx_attrs[] = { + &kbase_total_gpu_mem_attr.attr, + &kbase_private_gpu_mem_attr.attr, + NULL, +}; + +static const struct attribute_group kbase_kctx_attr_group = { + .attrs = kbase_kctx_attrs, +}; + +static const struct sysfs_ops kbase_kctx_sysfs_ops = { + .show = kbase_kctx_attr_show, +}; + +static const struct kobj_type kbase_kctx_ktype = { + .sysfs_ops = &kbase_kctx_sysfs_ops, + .default_groups = (const struct attribute_group *[]) { &kbase_kctx_attr_group, NULL }, +}; + /** * kbase_insert_kctx_to_process - Initialise kbase process context. * @@ -100,6 +168,8 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) */ if (!kprcs) { struct rb_node **new = &prcs_root->rb_node, *parent = NULL; + char kctx_name[64]; + int ret = 0; kprcs = kzalloc(sizeof(*kprcs), GFP_KERNEL); if (kprcs == NULL) @@ -109,6 +179,15 @@ static int kbase_insert_kctx_to_process(struct kbase_context *kctx) kprcs->dma_buf_root = RB_ROOT; kprcs->total_gpu_pages = 0; + if (unlikely(!scnprintf(kctx_name, 64, "%d", tgid))) + return -ENOMEM; + + ret = kobject_init_and_add(&kprcs->kobj, &kbase_kctx_ktype, kctx->kbdev->kprcs_kobj, kctx_name); + if (ret) { + dev_err(kctx->kbdev->dev, "Failed to create kctx kobject"); + kobject_put(&kprcs->kobj); + } + while (*new) { struct kbase_process *prcs_node; @@ -203,6 +282,7 @@ int kbase_context_common_init(struct kbase_context *kctx) } } + kctx->offslot_ts = 0; return err; } @@ -260,6 +340,7 @@ static void kbase_remove_kctx_from_process(struct kbase_context *kctx) * we can remove it from the process rb_tree. */ if (list_empty(&kprcs->kctx_list)) { + kobject_put(&kprcs->kobj); rb_erase(&kprcs->kprcs_node, &kctx->kbdev->process_root); /* Add checks, so that the terminating process Should not * hold any gpu_memory. @@ -296,8 +377,11 @@ void kbase_context_common_term(struct kbase_context *kctx) int kbase_context_mem_pool_group_init(struct kbase_context *kctx) { - return kbase_mem_pool_group_init(&kctx->mem_pools, kctx->kbdev, - &kctx->kbdev->mem_pool_defaults, &kctx->kbdev->mem_pools); + size_t const small_max_size = KBASE_MEM_POOL_MAX_SIZE_KCTX; + size_t const large_max_size = small_max_size >> (KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER - + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER); + return kbase_mem_pool_group_init(&kctx->mem_pools, kctx->kbdev, small_max_size, + large_max_size, NULL); } void kbase_context_mem_pool_group_term(struct kbase_context *kctx) @@ -305,6 +389,20 @@ void kbase_context_mem_pool_group_term(struct kbase_context *kctx) kbase_mem_pool_group_term(&kctx->mem_pools); } +int kbase_context_pgd_mem_pool_init(struct kbase_context *kctx) +{ + int err = kbase_mem_pool_init_no_reclaim(&kctx->pgd_mem_pool, + BASE_PGD_MEM_POOL_MAX_SIZE_KBDEV, + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER, 0, + kctx->kbdev); + return err; +} + +void kbase_context_pgd_mem_pool_term(struct kbase_context *kctx) +{ + kbase_mem_pool_term(&kctx->pgd_mem_pool); +} + int kbase_context_mmu_init(struct kbase_context *kctx) { return kbase_mmu_init(kctx->kbdev, &kctx->mmu, kctx, diff --git a/drivers/gpu/arm/valhall/context/mali_kbase_context_internal.h b/drivers/gpu/arm/valhall/context/mali_kbase_context_internal.h index 8d9b39419586..5552aa3e036e 100644 --- a/drivers/gpu/arm/valhall/context/mali_kbase_context_internal.h +++ b/drivers/gpu/arm/valhall/context/mali_kbase_context_internal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -50,6 +50,9 @@ void kbase_context_common_term(struct kbase_context *kctx); int kbase_context_mem_pool_group_init(struct kbase_context *kctx); void kbase_context_mem_pool_group_term(struct kbase_context *kctx); +int kbase_context_pgd_mem_pool_init(struct kbase_context *kctx); +void kbase_context_pgd_mem_pool_term(struct kbase_context *kctx); + int kbase_context_mmu_init(struct kbase_context *kctx); void kbase_context_mmu_term(struct kbase_context *kctx); diff --git a/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.c b/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.c index ecf19001c345..257d64b609c1 100644 --- a/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.c +++ b/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.c @@ -897,7 +897,6 @@ void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_reset_post); -#ifdef KBASE_PM_RUNTIME void kbase_ipa_control_handle_gpu_sleep_enter(struct kbase_device *kbdev) { lockdep_assert_held(&kbdev->hwaccess_lock); @@ -931,7 +930,6 @@ void kbase_ipa_control_handle_gpu_sleep_exit(struct kbase_device *kbdev) } } KBASE_EXPORT_TEST_API(kbase_ipa_control_handle_gpu_sleep_exit); -#endif #if MALI_UNIT_TEST void kbase_ipa_control_rate_change_notify_test(struct kbase_device *kbdev, u32 clk_index, diff --git a/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.h b/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.h index 80aabc1022c5..0d1fe664d9a5 100644 --- a/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.h +++ b/drivers/gpu/arm/valhall/csf/ipa_control/mali_kbase_csf_ipa_control.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -197,7 +197,6 @@ void kbase_ipa_control_handle_gpu_reset_pre(struct kbase_device *kbdev); */ void kbase_ipa_control_handle_gpu_reset_post(struct kbase_device *kbdev); -#ifdef KBASE_PM_RUNTIME /** * kbase_ipa_control_handle_gpu_sleep_enter - Handle the pre GPU Sleep event * @@ -222,7 +221,6 @@ void kbase_ipa_control_handle_gpu_sleep_enter(struct kbase_device *kbdev); * was called previously. */ void kbase_ipa_control_handle_gpu_sleep_exit(struct kbase_device *kbdev); -#endif #if MALI_UNIT_TEST /** diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c index c0231abe8d5f..22214f5b95e7 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -319,10 +319,9 @@ void kbase_csf_free_command_stream_user_pages(struct kbase_context *kctx, struct * This condition is only true when mali_kbase_supports_csg_cs_user_page_allocation() * is disable. */ - if (!mali_kbase_supports_csg_cs_user_page_allocation(kctx->api_version)) { + if (!mali_kbase_supports_csg_cs_user_page_allocation(kctx->api_version)) kernel_free_user_io_pages(kctx, queue->phys, queue->user_io_addr); - queue->user_io_addr = NULL; - } + queue->user_io_addr = NULL; /* The user_io_gpu_va should have been unmapped inside the scheduler */ WARN_ONCE(queue->user_io_gpu_va, "Userio pages appears still have mapping"); @@ -773,6 +772,12 @@ int kbase_csf_queue_bind(struct kbase_context *kctx, union kbase_ioctl_cs_queue_ if (bind->in.csi_index >= max_streams) goto out; + if (queue->user_io_addr != NULL) { + dev_err(kctx->kbdev->dev, "Queue with stale user_io address: %pK", + (void *)queue->user_io_addr); + goto out; + } + if (group->run_state == KBASE_CSF_GROUP_TERMINATED) goto out; @@ -1018,6 +1023,13 @@ static void unbind_stopped_queue(struct kbase_context *kctx, struct kbase_queue queue->group = NULL; kbase_csf_scheduler_spin_unlock(kctx->kbdev, flags); + /* Ensure that the user I/O pages are no longer accessible */ + mutex_lock(&kctx->kbdev->csf.reg_lock); + unmap_mapping_range(kctx->kbdev->csf.db_filp->f_inode->i_mapping, + (loff_t)(queue->db_file_offset << PAGE_SHIFT), + BASEP_QUEUE_NR_MMAP_USER_PAGES * PAGE_SIZE, 1); + mutex_unlock(&kctx->kbdev->csf.reg_lock); + put_user_pages_mmap_handle(kctx, queue); WARN_ON_ONCE(queue->doorbell_nr != KBASEP_USER_DB_NR_INVALID); queue->bind_state = KBASE_CSF_QUEUE_UNBOUND; @@ -1852,8 +1864,6 @@ void kbase_csf_ctx_handle_fault(struct kbase_context *kctx, struct kbase_fault * void kbase_csf_ctx_term(struct kbase_context *kctx) { struct kbase_device *kbdev = kctx->kbdev; - struct kbase_as *as = NULL; - unsigned long flags; u32 i; int err; bool reset_prevented = false; @@ -1922,15 +1932,57 @@ void kbase_csf_ctx_term(struct kbase_context *kctx) flush_work(&kctx->kbdev->csf.glb_fatal_work); /* A work item to handle page_fault/bus_fault/gpu_fault could be - * pending for the outgoing context. Flush the workqueue that will - * execute that work item. + * pending for the outgoing context which we no longer care about. + * Ensure that the context won't be accessed anymore by the fault + * workers. */ - spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags); - if (kctx->as_nr != KBASEP_AS_NR_INVALID) - as = &kctx->kbdev->as[kctx->as_nr]; - spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); - if (as) - flush_workqueue(as->pf_wq); + while (true) { + unsigned long flags; + int refcount; + + mutex_lock(&kbdev->mmu_hw_mutex); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + + refcount = atomic_read(&kctx->refcount); + if ((refcount != 0) && !WARN_ON_ONCE(kctx->as_nr == KBASEP_AS_NR_INVALID)) { + struct kbase_as *as = &kctx->kbdev->as[kctx->as_nr]; + int new_refcount; + + dev_dbg(kbdev->dev, + "Waiting for pending fault worker to complete when terminating context (%d_%d)", + kctx->tgid, kctx->id); + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + flush_workqueue(as->pf_wq); + + new_refcount = atomic_read(&kctx->refcount); + if (refcount != new_refcount) { + /* Fault workers executed and released some references, re-check */ + continue; + } else { + /* Waiting for pending fault workers to execute was not effective, + * we're going to forcefully de-assign the AS from this context + * because nothing else should still be accessing the context at + * this point. + * + * This should never happen and a WARN_ON() would be printed by + * kbase_ctx_sched_remove_ctx() if the refcount is non-zero. + */ + dev_warn( + kbdev->dev, + "No fault workers executed, %d refs remain for terminating context (%d_%d)", + new_refcount, kctx->tgid, kctx->id); + kbase_ctx_sched_remove_ctx(kctx); + } + } else { + kbase_ctx_sched_remove_ctx_nolock(kctx); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); + } + + break; + } mutex_lock(&kctx->csf.lock); @@ -2439,27 +2491,33 @@ static void handle_progress_timer_events(struct kbase_device *const kbdev, unsig u32 max_csg_slots = kbdev->csf.global_iface.group_num; u32 csg_nr; struct kbase_queue_group *group = NULL; + bool aw_removed; kbase_csf_scheduler_spin_lock_assert_held(kbdev); if (likely(bitmap_empty(slot_mask, BASEP_QUEUE_GROUP_MAX))) return; - /* Log each timeout and Update timestamp of compute progress timeout */ - for_each_set_bit(csg_nr, slot_mask, max_csg_slots) { - group = kbdev->csf.scheduler.csg_slots[csg_nr].resident_group; - group->progress_timer_state = kbase_csf_fw_io_group_read(&kbdev->csf.fw_io, csg_nr, - CSG_PROGRESS_TIMER_STATE); + aw_removed = kbase_io_is_aw_removed(kbdev); - dev_info( - kbdev->dev, - "[%llu] Iterator PROGRESS_TIMER timeout notification received for group %u of ctx %d_%d on slot %u with state %x", - kbase_backend_get_cycle_cnt(kbdev), group->handle, group->kctx->tgid, - group->kctx->id, csg_nr, group->progress_timer_state); + if (!aw_removed) + /* Log each timeout and Update timestamp of compute progress timeout */ + for_each_set_bit(csg_nr, slot_mask, max_csg_slots) { + group = kbdev->csf.scheduler.csg_slots[csg_nr].resident_group; + group->progress_timer_state = kbase_csf_fw_io_group_read( + &kbdev->csf.fw_io, csg_nr, CSG_PROGRESS_TIMER_STATE); - if (CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) == - CSG_PROGRESS_TIMER_STATE_COMPUTE) - kbdev->csf.compute_progress_timeout_cc = kbase_backend_get_cycle_cnt(kbdev); - } + dev_info( + kbdev->dev, + "[%llu] Iterator PROGRESS_TIMER timeout notification received for group %u of ctx %d_%d on slot %u with state %x", + kbase_backend_get_cycle_cnt(kbdev), group->handle, + group->kctx->tgid, group->kctx->id, csg_nr, + group->progress_timer_state); + + if (CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) == + CSG_PROGRESS_TIMER_STATE_COMPUTE) + kbdev->csf.compute_progress_timeout_cc = + kbase_backend_get_cycle_cnt(kbdev); + } /* Ignore fragment timeout if it is following a compute timeout. * Otherwise, terminate the command stream group. @@ -2470,8 +2528,8 @@ static void handle_progress_timer_events(struct kbase_device *const kbdev, unsig /* Check if it is a fragment timeout right after another compute timeout. * In such case, kill compute CSG and give fragment CSG a second chance */ - if (CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) == - CSG_PROGRESS_TIMER_STATE_FRAGMENT) { + if (!aw_removed && CSG_PROGRESS_TIMER_STATE_GET(group->progress_timer_state) == + CSG_PROGRESS_TIMER_STATE_FRAGMENT) { u64 cycle_counter = kbase_backend_get_cycle_cnt(kbdev); u64 compute_progress_timeout_cc = kbdev->csf.compute_progress_timeout_cc; @@ -3005,7 +3063,27 @@ static int process_cs_interrupts(struct kbase_queue_group *const group, u32 grou kbase_csf_fw_io_close(fw_io, fw_io_flags); } - /* PROTM_PEND and TILER_OOM can be safely ignored + /* PROTM_PEND request should be handled if the group + * is assigned a CSG slot in the future. We set + * protm_pending_bitmap here in case we skip saving + * the CS slots' state due to the group becoming active + * shortly after the suspension request is made. + */ + if ((cs_req & CS_REQ_PROTM_PEND_MASK) ^ (cs_ack & CS_ACK_PROTM_PEND_MASK)) { + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_PROTM_PEND, group, + queue, cs_req ^ cs_ack); + + dev_dbg(kbdev->dev, + "Protected mode entry request for queue on csi %d bound to group-%d on slot %d", + queue->csi_index, group->handle, group->csg_nr); + + bitmap_set(group->protm_pending_bitmap, i, 1); + KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_SET, group, queue, + group->protm_pending_bitmap[0]); + protm_pend = true; + } + + /* TILER_OOM can be safely ignored * because they will be raised again if the group * is assigned a CSG slot in future. */ @@ -3026,20 +3104,6 @@ static int process_cs_interrupts(struct kbase_queue_group *const group, u32 grou kbase_csf_handle_pending_oom_interrupt(queue, group_id); } - - if ((cs_req & CS_REQ_PROTM_PEND_MASK) ^ (cs_ack & CS_ACK_PROTM_PEND_MASK)) { - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_INTERRUPT_PROTM_PEND, group, - queue, cs_req ^ cs_ack); - - dev_dbg(kbdev->dev, - "Protected mode entry request for queue on csi %d bound to group-%d on slot %d", - queue->csi_index, group->handle, group->csg_nr); - - bitmap_set(group->protm_pending_bitmap, i, 1); - KBASE_KTRACE_ADD_CSF_GRP_Q(kbdev, CSI_PROTM_PEND_SET, group, queue, - group->protm_pending_bitmap[0]); - protm_pend = true; - } } } @@ -3757,7 +3821,7 @@ void kbase_csf_doorbell_mapping_term(struct kbase_device *kbdev) * module unload path, so the page can be left uncleared before returning it * back to kbdev memory pool. */ - kbase_mem_pool_free(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], page, false); + kbase_mem_pool_free(&kbdev->fw_mem_pools.small, page, false); fput(kbdev->csf.db_filp); } @@ -3773,8 +3837,7 @@ int kbase_csf_doorbell_mapping_init(struct kbase_device *kbdev) if (IS_ERR(filp)) return PTR_ERR(filp); - ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys, - false, NULL); + ret = kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, 1, &phys, false, NULL); if (ret <= 0) { fput(filp); @@ -3821,7 +3884,7 @@ void kbase_csf_free_dummy_user_reg_page(struct kbase_device *kbdev) * path, so the page can be left uncleared before returning it back to kbdev * memory pool. */ - kbase_mem_pool_free(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], page, false); + kbase_mem_pool_free(&kbdev->fw_mem_pools.small, page, false); fput(kbdev->csf.user_reg.filp); } } @@ -3841,8 +3904,7 @@ int kbase_csf_setup_dummy_user_reg_page(struct kbase_device *kbdev) return PTR_ERR(filp); } - if (kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, &phys, - false, NULL) <= 0) { + if (kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, 1, &phys, false, NULL) <= 0) { fput(filp); return -ENOMEM; } diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_csg_debugfs.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_csg_debugfs.c index 3d614514e8bd..7a53bb7ad556 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_csg_debugfs.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_csg_debugfs.c @@ -50,10 +50,8 @@ static const char *scheduler_state_to_string(struct kbase_device *kbdev, return "INACTIVE"; case SCHED_SUSPENDED: return "SUSPENDED"; -#ifdef KBASE_PM_RUNTIME case SCHED_SLEEPING: return "SLEEPING"; -#endif default: dev_warn(kbdev->dev, "Unknown Scheduler state %d", sched_state); return NULL; @@ -249,10 +247,8 @@ static ssize_t kbase_csf_debugfs_scheduler_state_set(struct file *file, const ch if (sysfs_streq(buf, "SUSPENDED")) kbase_csf_scheduler_pm_suspend(kbdev); -#ifdef KBASE_PM_RUNTIME - else if (sysfs_streq(buf, "SLEEPING")) + else if (IS_ENABLED(CONFIG_PM) && sysfs_streq(buf, "SLEEPING")) kbase_csf_scheduler_force_sleep(kbdev); -#endif else if (sysfs_streq(buf, "INACTIVE")) kbase_csf_scheduler_force_wakeup(kbdev); else { diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h index 9f62587ba2cc..48569836e320 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h @@ -1043,6 +1043,17 @@ struct kbase_csf_csg_slot { u8 priority; }; +/** + * struct kbase_csf_heap_reclaim_offslot - Setting for reclaiming offslot CSG's heap. + * + * @timeout_ms: Reclaim from CSGs being offslot longer than this. + * @pages: Max number of pages for each reclaim. + */ +struct kbase_csf_heap_reclaim_offslot { + u32 timeout_ms; + u32 pages; +}; + /** * struct kbase_csf_sched_heap_reclaim_mgr - Object for managing tiler heap reclaim * kctx lists inside the CSF device's scheduler. @@ -1052,12 +1063,14 @@ struct kbase_csf_csg_slot { * lists track the kctxs attached to the reclaim manager. * @unused_pages: Estimated number of unused pages from the @ctxlist array. The * number is indicative for use with reclaim shrinker's count method. + * @offslot_setting: Setting for reclaiming offslot CSG's heap. */ struct kbase_csf_sched_heap_reclaim_mgr { DEFINE_KBASE_SHRINKER heap_reclaim; struct list_head ctx_lists[KBASE_QUEUE_GROUP_PRIORITY_COUNT]; atomic_t unused_pages; + struct kbase_csf_heap_reclaim_offslot offslot_setting; }; /** @@ -1177,6 +1190,9 @@ struct kbase_csf_mcu_shared_regions { * perform a scheduling tock. * @pending_gpu_idle_work: Indicates that kbase_csf_scheduler_kthread() should * handle the GPU IDLE event. + * @pending_runtime_suspend_work: Indicates that kbase_csf_scheduler_kthread() + * should proceed to suspend the GPU as part of + * handling the runtime suspend event. * @pending_power_off_work: Indicates that kbase_csf_scheduler_kthread() should * proceed to power off the GPU. * @ping_work: Work item that would ping the firmware at regular @@ -1228,10 +1244,13 @@ struct kbase_csf_mcu_shared_regions { * @mcu_regs_data: Scheduler MCU shared regions data for managing the * shared interface mappings for on-slot queues and * CSG suspend buffers. - * @kthread_signal: Used to wake up the GPU queue submission - * thread when a queue needs attention. - * @kthread_running: Whether the GPU queue submission thread should keep - * executing. + * @kthread_signal: Used to wake up the main CSF scheduler thread + * to handle pending work items. + * @kthread_running: Set to true to indicate that the CSF scheduler + * thread will handle work items. Work items that + * are handled by this thread all require the schduler + * mutex lock, thus are serialised and executed in a + * predefined order. * @gpuq_kthread: Dedicated thread primarily used to handle * latency-sensitive tasks such as GPU queue * submissions. @@ -1272,6 +1291,7 @@ struct kbase_csf_scheduler { atomic_t pending_tick_work; atomic_t pending_tock_work; atomic_t pending_gpu_idle_work; + atomic_t pending_runtime_suspend_work; atomic_t pending_power_off_work; struct delayed_work ping_work; struct kbase_context *top_kctx; @@ -1813,7 +1833,8 @@ struct kbase_csf_user_reg { * @fw_io: Firmware I/O interface. * @compute_progress_timeout_cc: Value of GPU cycle count register when progress * timer timeout is reported for the compute iterator. - * @num_doorbells: Number of doorbells supported by the GPU. + * @neural_allowed_mask: A mask for optionally disabling neural cores across all CSGs + * @num_doorbells: Number of doorbells supported by the GPU. */ struct kbase_csf_device { struct kbase_mmu_table mcu_mmu; @@ -1877,6 +1898,7 @@ struct kbase_csf_device { u32 page_fault_cnt; struct kbase_csf_fw_io fw_io; u64 compute_progress_timeout_cc; + u64 neural_allowed_mask; u32 num_doorbells; }; diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_event.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_event.c index 08faace8ef06..a91d99816a9c 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_event.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_event.c @@ -94,11 +94,11 @@ static void sync_update_notify_gpu(struct kbase_context *kctx) spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags); can_notify_gpu = kbase_io_is_gpu_powered(kctx->kbdev); -#ifdef KBASE_PM_RUNTIME - if (kctx->kbdev->pm.backend.db_mirror_interrupt_enabled || - kctx->kbdev->pm.backend.gpu_sleep_mode_active) - can_notify_gpu = false; -#endif + if (IS_ENABLED(CONFIG_PM)) { + if (kctx->kbdev->pm.backend.db_mirror_interrupt_enabled || + kctx->kbdev->pm.backend.gpu_sleep_mode_active) + can_notify_gpu = false; + } if (can_notify_gpu) { diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.c index d1d53a075cbb..5680d2c21116 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -377,6 +377,15 @@ void kbase_csf_stop_firmware_and_wait(struct kbase_device *kbdev) kbase_csf_firmware_disable_mcu_wait(kbdev); } +static void kbasep_hwcnt_init_on_boot(struct kbase_device *kbdev) +{ + kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(&kbdev->hwcnt_gpu_iface); + kbase_hwcnt_backend_csf_set_hw_availability(&kbdev->hwcnt_gpu_iface, + kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, + kbdev->pm.debug_core_mask); +} + static void wait_for_firmware_boot(struct kbase_device *kbdev) { long wait_timeout; @@ -400,6 +409,8 @@ static void wait_for_firmware_boot(struct kbase_device *kbdev) wait_timeout); if (!remaining) dev_err(kbdev->dev, "Timed out waiting for fw boot completion"); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); + kbdev->csf.interrupt_received = false; } @@ -414,6 +425,8 @@ static void enable_mcu(struct kbase_device *kbdev) static void boot_csf_firmware(struct kbase_device *kbdev) { + kbasep_hwcnt_init_on_boot(kbdev); + enable_mcu(kbdev); wait_for_firmware_boot(kbdev); @@ -440,6 +453,12 @@ static int wait_ready(struct kbase_device *kbdev) if (!err) return 0; + /* Bailout on GPU_LOST without RESET */ + if (err == -ENODEV) { + dev_warn(kbdev->dev, "%s: AW removed, bailing out", __func__); + return 0; + } + dev_err(kbdev->dev, "AS_ACTIVE bit stuck for MCU AS. Might be caused by unstable GPU clk/pwr or faulty system"); @@ -835,10 +854,10 @@ retry_alloc: } } else { if (!reuse_pages) { - ret = kbase_mem_pool_alloc_pages( - kbase_mem_pool_group_select(kbdev, KBASE_MEM_GROUP_CSF_FW, - is_small_page), - num_pages_aligned, phys, false, NULL); + ret = kbase_mem_pool_alloc_pages(is_small_page ? + &kbdev->fw_mem_pools.small : + &kbdev->fw_mem_pools.large, + num_pages_aligned, phys, false, NULL); } } @@ -971,10 +990,9 @@ out: kbase_csf_protected_memory_free(kbdev, pma, num_pages_aligned, is_small_page); } else { - kbase_mem_pool_free_pages( - kbase_mem_pool_group_select(kbdev, KBASE_MEM_GROUP_CSF_FW, - is_small_page), - num_pages_aligned, phys, false, false); + kbase_mem_pool_free_pages(is_small_page ? &kbdev->fw_mem_pools.small : + &kbdev->fw_mem_pools.large, + num_pages_aligned, phys, false, false); } kfree(phys); } @@ -1386,6 +1404,11 @@ static int parse_capabilities(struct kbase_device *kbdev) else iface->instr_features = 0; + if (iface->version >= kbase_csf_interface_version(1, 1, 0)) + iface->prfcnt_features = shared_info[GLB_PRFCNT_FEATURES / 4]; + else + iface->prfcnt_features = 0; + if ((GROUP_CONTROL_0 + (unsigned long)iface->group_num * iface->group_stride) > (interface->num_pages * PAGE_SIZE)) { dev_err(kbdev->dev, @@ -1600,9 +1623,7 @@ static void set_global_request(struct kbase_csf_fw_io *fw_io, u32 const req_mask kbase_csf_fw_io_global_write_mask(fw_io, GLB_REQ, glb_req, req_mask); } -static void enable_endpoints_global(struct kbase_csf_fw_io *fw_io, - - u64 const shader_core_mask) +static void enable_endpoints_global(struct kbase_csf_fw_io *fw_io, u64 const shader_core_mask) { kbase_csf_fw_io_assert_opened(fw_io); @@ -1905,6 +1926,11 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask) kbasep_enable_rtu(kbdev); /* Update shader core allocation enable mask */ + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + if (kbase_io_is_gpu_powered(kbdev)) + kbase_reg_write64(kbdev, GPU_GOVERNOR_ENUM(GOV_CORE_MASK), + kbase_pm_ca_get_gov_core_mask(kbdev)); + enable_endpoints_global(fw_io, core_mask); set_shader_poweroff_timer(fw_io); @@ -1935,6 +1961,13 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask) if (kbdev->pm.backend.has_host_pwr_iface) ack_irq_mask |= GLB_ACK_IRQ_MASK_STATE_MASK; + + /* Do not modify PRFCNT bits of GLB_ACK_IRQ_MASK. */ + ack_irq_mask |= + (kbase_csf_fw_io_global_input_read(&kbdev->csf.fw_io, GLB_ACK_IRQ_MASK) & + (GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK | GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK | + GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK | GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK)); + /* Unmask the interrupts */ kbase_csf_fw_io_global_write(fw_io, GLB_ACK_IRQ_MASK, ack_irq_mask); @@ -1965,14 +1998,32 @@ exit: */ static int global_init_on_boot(struct kbase_device *const kbdev) { - unsigned long flags; + unsigned long flags, scheduler_lock_flags; u64 core_mask; int ret = 0; u32 request_mask = CSF_GLB_REQ_CFG_MASK; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + core_mask = kbase_pm_ca_get_core_mask(kbdev); + kbdev->csf.firmware_hctl_core_pwr = kbase_pm_no_mcu_core_pwroff(kbdev); + + /* Enable the HWC context for the case of MCU controlling the shader core power. + * HWC context will be left enabled throughout the MCU power cycles, unless + * there is a GPU reset. + * + * In case of GPU reset, HWC needs to be disabled to ensure + * the correct HWC backend functionality. The context then gets reenabled during + * the reboot. + */ + if (!kbdev->csf.firmware_hctl_core_pwr) { + kbase_csf_scheduler_spin_lock(kbdev, &scheduler_lock_flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, scheduler_lock_flags); + kbdev->pm.backend.hwcnt_disabled = false; + kbdev->pm.backend.hwcnt_desired = true; + } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); global_init(kbdev, core_mask); @@ -1996,10 +2047,25 @@ static int global_init_on_boot(struct kbase_device *const kbdev) void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev, u64 core_mask) { + unsigned long flags; lockdep_assert_held(&kbdev->hwaccess_lock); kbdev->csf.glb_init_request_pending = true; kbdev->csf.firmware_hctl_core_pwr = kbase_pm_no_mcu_core_pwroff(kbdev); + if (!kbdev->csf.firmware_hctl_core_pwr) { + /* The HWC context reenabling is needed if: + * - shader core power control was previously under host. + * - context was disabled when preparing for a GPU reset. + */ + kbdev->pm.backend.hwcnt_desired = true; + if (kbdev->pm.backend.hwcnt_disabled) { + kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, flags); + kbdev->pm.backend.hwcnt_disabled = false; + } + } + global_init(kbdev, core_mask); } @@ -2020,9 +2086,6 @@ void kbase_csf_firmware_update_core_attr(struct kbase_device *kbdev, bool update struct kbase_csf_fw_io *fw_io = &kbdev->csf.fw_io; unsigned long flags, fw_io_flags; - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) - core_mask = U64_MAX; - lockdep_assert_held(&kbdev->hwaccess_lock); kbase_csf_scheduler_spin_lock(kbdev, &flags); @@ -2083,6 +2146,7 @@ static void kbase_csf_firmware_reload_worker(struct work_struct *work) return; /* Reboot the firmware */ + kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(&kbdev->hwcnt_gpu_iface); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbase_csf_firmware_enable_mcu(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); @@ -2096,9 +2160,13 @@ void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev) if (kbdev->csf.firmware_reload_needed) { kbdev->csf.firmware_reload_needed = false; + /* MCU cold boot requested. */ queue_work(system_wq, &kbdev->csf.firmware_reload_work); } else { - kbase_csf_firmware_enable_mcu(kbdev); + /* MCU shall not boot while reset is in progress */ + if (likely(!kbdev->pm.backend.in_reset)) + /* MCU warm boot requested. */ + kbase_csf_firmware_enable_mcu(kbdev); } } @@ -2129,6 +2197,11 @@ void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev) dev_err(kbdev->dev, "Version check failed in firmware reboot."); KBASE_KTRACE_ADD(kbdev, CSF_FIRMWARE_REBOOT, NULL, 0u); + kbase_hwcnt_backend_csf_set_hw_availability(&kbdev->hwcnt_gpu_iface, + kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, + kbdev->pm.debug_core_mask); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); /* Tell MCU state machine to transit to next state */ kbdev->csf.firmware_reloaded = true; @@ -2419,10 +2492,9 @@ int kbase_csf_firmware_late_init(struct kbase_device *kbdev) kbdev->csf.gpu_idle_hysteresis_ns = FIRMWARE_IDLE_HYSTERESIS_TIME_NS; -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_gpu_sleep_allowed(kbdev)) + if (IS_ENABLED(CONFIG_PM) && kbase_pm_gpu_sleep_allowed(kbdev)) kbdev->csf.gpu_idle_hysteresis_ns /= FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; -#endif + WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ns); kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count(kbdev, kbdev->csf.gpu_idle_hysteresis_ns, &no_modifier); @@ -2751,10 +2823,11 @@ void kbase_csf_firmware_unload_term(struct kbase_device *kbdev) interface->num_pages_aligned, interface->is_small_page); } else { - kbase_mem_pool_free_pages( - kbase_mem_pool_group_select(kbdev, KBASE_MEM_GROUP_CSF_FW, - interface->is_small_page), - interface->num_pages_aligned, interface->phys, true, false); + kbase_mem_pool_free_pages(interface->is_small_page ? + &kbdev->fw_mem_pools.small : + &kbdev->fw_mem_pools.large, + interface->num_pages_aligned, + interface->phys, true, false); } kfree(interface->phys); @@ -3128,7 +3201,6 @@ void kbase_csf_firmware_enable_mcu(struct kbase_device *kbdev) enable_mcu(kbdev); } -#ifdef KBASE_PM_RUNTIME void kbase_csf_firmware_trigger_mcu_sleep(struct kbase_device *kbdev) { struct kbase_csf_fw_io *fw_io = &kbdev->csf.fw_io; @@ -3169,7 +3241,6 @@ bool kbase_csf_firmware_is_mcu_in_sleep(struct kbase_device *kbdev) } KBASE_EXPORT_TEST_API(kbase_csf_firmware_is_mcu_in_sleep); -#endif /* KBASE_PM_RUNTIME */ bool kbase_csf_firmware_mcu_halt_req_complete(struct kbase_device *kbdev) { @@ -3359,8 +3430,7 @@ int kbase_csf_firmware_mcu_shared_mapping_init(struct kbase_device *kbdev, unsig if (!page_list) goto page_list_alloc_error; - ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, - phys, false, NULL); + ret = kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, NULL); if (ret <= 0) goto phys_mem_pool_alloc_error; @@ -3408,8 +3478,7 @@ va_region_add_error: va_region_alloc_error: vunmap(cpu_addr); vmap_error: - kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, phys, - false, false); + kbase_mem_pool_free_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, false); phys_mem_pool_alloc_error: kfree(page_list); @@ -3441,16 +3510,14 @@ void kbase_csf_firmware_mcu_shared_mapping_term(struct kbase_device *kbdev, /* This is on module unload path, so the pages can be left uncleared before * returning them back to kbdev memory pool. */ - kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - csf_mapping->num_pages, csf_mapping->phys, false, false); + kbase_mem_pool_free_pages(&kbdev->fw_mem_pools.small, csf_mapping->num_pages, + csf_mapping->phys, false, false); } vunmap(csf_mapping->cpu_addr); kfree(csf_mapping->phys); } -#ifdef KBASE_PM_RUNTIME - void kbase_csf_firmware_soi_update(struct kbase_device *kbdev) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; @@ -3592,5 +3659,3 @@ int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbd return 0; } - -#endif /* KBASE_PM_RUNTIME */ diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.h index e2c627902097..6762bd22ec3e 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware.h @@ -161,6 +161,7 @@ struct kbase_csf_cmd_stream_group_info { * CSG capability structures. * @prfcnt_size: Performance counters size. * @instr_features: Instrumentation features. (csf >= 1.1.0) + * @prfcnt_features: Performance Counter features. * @groups: Address of an array of CSG capability structures. */ struct kbase_csf_global_iface { @@ -171,6 +172,7 @@ struct kbase_csf_global_iface { u32 group_stride; u32 prfcnt_size; u32 instr_features; + u32 prfcnt_features; struct kbase_csf_cmd_stream_group_info *groups; }; @@ -477,7 +479,6 @@ void kbase_csf_firmware_disable_mcu_wait(struct kbase_device *kbdev); */ void kbase_csf_stop_firmware_and_wait(struct kbase_device *kbdev); -#ifdef KBASE_PM_RUNTIME /** * kbase_csf_firmware_trigger_mcu_sleep - Send the command to put MCU in sleep * state. @@ -496,7 +497,6 @@ void kbase_csf_firmware_trigger_mcu_sleep(struct kbase_device *kbdev); */ bool kbase_csf_firmware_is_mcu_in_sleep(struct kbase_device *kbdev); -#endif /** * kbase_csf_firmware_trigger_reload() - Trigger the reboot of MCU firmware, for @@ -812,8 +812,6 @@ int kbase_csf_trigger_firmware_config_update(struct kbase_device *kbdev); */ int kbase_csf_firmware_req_core_dump(struct kbase_device *const kbdev); -#ifdef KBASE_PM_RUNTIME - /** * kbase_csf_firmware_soi_update - Update FW Sleep-on-Idle config * @@ -842,7 +840,5 @@ void kbase_csf_firmware_glb_idle_timer_update(struct kbase_device *kbdev); */ int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbdev); -#endif /* KBASE_PM_RUNTIME */ - -#endif +#endif /* _KBASE_CSF_FIRMWARE_H_ */ diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware_no_mali.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware_no_mali.c index 0ac6ad394b2d..c8c57862a295 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware_no_mali.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_firmware_no_mali.c @@ -221,6 +221,12 @@ static int invent_capabilities(struct kbase_device *kbdev) iface->group_num = ARRAY_SIZE(interface->csg); iface->group_stride = 0; + iface->prfcnt_features = 0; + + /* Set METATA_SIZE in GLB_PRFCNT_FEATURES. Always equal to one block. */ + WARN_ON((KBASE_DUMMY_MODEL_BLOCK_SIZE >> 8) > 0xf); + iface->prfcnt_features |= ((KBASE_DUMMY_MODEL_BLOCK_SIZE >> 8) & 0xf); + iface->groups = kcalloc(iface->group_num, sizeof(*iface->groups), GFP_KERNEL); if (iface->groups == NULL) return -ENOMEM; @@ -584,11 +590,22 @@ static void global_init(struct kbase_device *const kbdev, u64 core_mask) } /* Update shader core allocation enable mask */ + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + if (kbase_io_is_gpu_powered(kbdev)) + kbase_reg_write64(kbdev, GPU_GOVERNOR_ENUM(GOV_CORE_MASK), + kbase_pm_ca_get_gov_core_mask(kbdev)); + enable_endpoints_global(fw_io, core_mask); set_shader_poweroff_timer(fw_io); set_timeout_global(fw_io, kbase_csf_timeout_get(kbdev)); + /* Do not modify PRFCNT bits of GLB_ACK_IRQ_MASK. */ + ack_irq_mask |= + (kbase_csf_fw_io_global_input_read(&kbdev->csf.fw_io, GLB_ACK_IRQ_MASK) & + (GLB_ACK_IRQ_MASK_PRFCNT_SAMPLE_MASK | GLB_ACK_IRQ_MASK_PRFCNT_THRESHOLD_MASK | + GLB_ACK_IRQ_MASK_PRFCNT_OVERFLOW_MASK | GLB_ACK_IRQ_MASK_PRFCNT_ENABLE_MASK)); + /* Unmask the interrupts */ kbase_csf_fw_io_global_write(fw_io, GLB_ACK_IRQ_MASK, ack_irq_mask); @@ -610,14 +627,32 @@ exit: */ static int global_init_on_boot(struct kbase_device *const kbdev) { - unsigned long flags; + unsigned long flags, scheduler_lock_flags; u64 core_mask; int ret = 0; u32 request_mask = CSF_GLB_REQ_CFG_MASK; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + core_mask = kbase_pm_ca_get_core_mask(kbdev); + kbdev->csf.firmware_hctl_core_pwr = kbase_pm_no_mcu_core_pwroff(kbdev); + + /* Enable the HWC context for the case of MCU controlling the shader core power. + * HWC context will be left enabled throughout the MCU power cycles, unless + * there is a GPU reset. + * + * In case of GPU reset, HWC needs to be disabled to ensure + * the correct HWC backend functionality. The context then gets reenabled during + * the reboot. + */ + if (!kbdev->csf.firmware_hctl_core_pwr) { + kbase_csf_scheduler_spin_lock(kbdev, &scheduler_lock_flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, scheduler_lock_flags); + kbdev->pm.backend.hwcnt_disabled = false; + kbdev->pm.backend.hwcnt_desired = true; + } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); global_init(kbdev, core_mask); @@ -629,10 +664,25 @@ static int global_init_on_boot(struct kbase_device *const kbdev) void kbase_csf_firmware_global_reinit(struct kbase_device *kbdev, u64 core_mask) { + unsigned long flags; + lockdep_assert_held(&kbdev->hwaccess_lock); kbdev->csf.glb_init_request_pending = true; kbdev->csf.firmware_hctl_core_pwr = kbase_pm_no_mcu_core_pwroff(kbdev); + if (!kbdev->csf.firmware_hctl_core_pwr) { + /* The HWC context reenabling is needed if: + * - shader core power control was previously under host. + * - context was disabled when preparing for a GPU reset. + */ + kbdev->pm.backend.hwcnt_desired = true; + if (kbdev->pm.backend.hwcnt_disabled) { + kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, flags); + kbdev->pm.backend.hwcnt_disabled = false; + } + } global_init(kbdev, core_mask); } @@ -653,9 +703,6 @@ void kbase_csf_firmware_update_core_attr(struct kbase_device *kbdev, bool update struct kbase_csf_fw_io *fw_io = &kbdev->csf.fw_io; unsigned long flags, fw_io_flags; - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) - core_mask = U64_MAX; - lockdep_assert_held(&kbdev->hwaccess_lock); kbase_csf_scheduler_spin_lock(kbdev, &flags); @@ -688,10 +735,16 @@ static void kbase_csf_firmware_reload_worker(struct work_struct *work) container_of(work, struct kbase_device, csf.firmware_reload_work); unsigned long flags; + kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(&kbdev->hwcnt_gpu_iface); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); /* Reboot the firmware */ kbase_csf_firmware_enable_mcu(kbdev); + kbase_hwcnt_backend_csf_set_hw_availability(&kbdev->hwcnt_gpu_iface, + kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, + kbdev->pm.debug_core_mask); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); /* Tell MCU state machine to transit to next state */ kbdev->csf.firmware_reloaded = true; kbase_pm_update_state(kbdev); @@ -709,6 +762,10 @@ void kbase_csf_firmware_trigger_reload(struct kbase_device *kbdev) queue_work(system_wq, &kbdev->csf.firmware_reload_work); } else { kbase_csf_firmware_enable_mcu(kbdev); + kbase_hwcnt_backend_csf_set_hw_availability( + &kbdev->hwcnt_gpu_iface, kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, kbdev->pm.debug_core_mask); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); kbdev->csf.firmware_reloaded = true; } } @@ -721,7 +778,11 @@ void kbase_csf_firmware_reload_completed(struct kbase_device *kbdev) if (unlikely(!kbdev->csf.firmware_inited)) return; - + kbase_hwcnt_backend_csf_set_hw_availability(&kbdev->hwcnt_gpu_iface, + kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, + kbdev->pm.debug_core_mask); + kbase_hwcnt_backend_csf_on_after_mcu_on(&kbdev->hwcnt_gpu_iface); /* Tell MCU state machine to transit to next state */ kbdev->csf.firmware_reloaded = true; kbase_pm_update_state(kbdev); @@ -955,6 +1016,15 @@ u32 kbase_csf_firmware_reset_mcu_core_pwroff_time(struct kbase_device *kbdev) return kbase_csf_firmware_set_mcu_core_pwroff_time(kbdev, DEFAULT_GLB_PWROFF_TIMEOUT_NS); } +static void kbasep_hwcnt_init_on_boot(struct kbase_device *kbdev) +{ + kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(&kbdev->hwcnt_gpu_iface); + kbase_hwcnt_backend_csf_set_hw_availability(&kbdev->hwcnt_gpu_iface, + kbdev->gpu_props.curr_config.l2_slices, + kbdev->gpu_props.curr_config.shader_present, + kbdev->pm.debug_core_mask); +} + int kbase_csf_firmware_early_init(struct kbase_device *kbdev) { kbdev->csf.num_doorbells = CSF_NUM_DOORBELL_MAX; @@ -987,10 +1057,9 @@ int kbase_csf_firmware_late_init(struct kbase_device *kbdev) u32 no_modifier = 0; kbdev->csf.gpu_idle_hysteresis_ns = FIRMWARE_IDLE_HYSTERESIS_TIME_NS; -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_gpu_sleep_allowed(kbdev)) + if (IS_ENABLED(CONFIG_PM) && kbase_pm_gpu_sleep_allowed(kbdev)) kbdev->csf.gpu_idle_hysteresis_ns /= FIRMWARE_IDLE_HYSTERESIS_GPU_SLEEP_SCALER; -#endif + WARN_ON(!kbdev->csf.gpu_idle_hysteresis_ns); kbdev->csf.gpu_idle_dur_count = convert_dur_to_idle_count(kbdev, kbdev->csf.gpu_idle_hysteresis_ns, &no_modifier); @@ -1041,6 +1110,8 @@ int kbase_csf_firmware_load_init(struct kbase_device *kbdev) kbase_csf_fw_io_init(&kbdev->csf.fw_io, kbdev); + kbasep_hwcnt_init_on_boot(kbdev); + ret = invent_capabilities(kbdev); if (ret != 0) goto error; @@ -1273,7 +1344,6 @@ void kbase_csf_firmware_enable_mcu(struct kbase_device *kbdev) kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(MCU_CONTROL), MCU_CONTROL_REQ_AUTO); } -#ifdef KBASE_PM_RUNTIME void kbase_csf_firmware_trigger_mcu_sleep(struct kbase_device *kbdev) { struct kbase_csf_fw_io *fw_io = &kbdev->csf.fw_io; @@ -1299,7 +1369,6 @@ bool kbase_csf_firmware_is_mcu_in_sleep(struct kbase_device *kbdev) kbase_csf_firmware_mcu_halted(kbdev)); } -#endif bool kbase_csf_firmware_mcu_halt_req_complete(struct kbase_device *kbdev) { @@ -1467,8 +1536,7 @@ int kbase_csf_firmware_mcu_shared_mapping_init(struct kbase_device *kbdev, unsig if (!page_list) goto page_list_alloc_error; - ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, - phys, false, NULL); + ret = kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, NULL); if (ret <= 0) goto phys_mem_pool_alloc_error; @@ -1516,8 +1584,7 @@ va_region_add_error: va_region_alloc_error: vunmap(cpu_addr); vmap_error: - kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, phys, - false, false); + kbase_mem_pool_free_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, false); phys_mem_pool_alloc_error: kfree(page_list); @@ -1546,16 +1613,14 @@ void kbase_csf_firmware_mcu_shared_mapping_term(struct kbase_device *kbdev, } if (csf_mapping->phys) { - kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], - csf_mapping->num_pages, csf_mapping->phys, false, false); + kbase_mem_pool_free_pages(&kbdev->fw_mem_pools.small, csf_mapping->num_pages, + csf_mapping->phys, false, false); } vunmap(csf_mapping->cpu_addr); kfree(csf_mapping->phys); } -#ifdef KBASE_PM_RUNTIME - void kbase_csf_firmware_soi_update(struct kbase_device *kbdev) { } @@ -1568,5 +1633,3 @@ int kbase_csf_firmware_soi_disable_on_scheduler_suspend(struct kbase_device *kbd { return 0; } - -#endif /* KBASE_PM_RUNTIME */ diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.c index 6e20f9dfe302..a2ece518bd4a 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.c @@ -22,7 +22,6 @@ #include "mali_kbase.h" #include "mali_kbase_csf_fw_io.h" #include -#include "mali_kbase_io.h" #include static inline u32 input_page_read(const u32 *const input, const u32 offset) @@ -89,7 +88,7 @@ static inline void input_page_partial_write64(u64 *const input, const u32 offset void kbase_csf_fw_io_init(struct kbase_csf_fw_io *fw_io, struct kbase_device *kbdev) { spin_lock_init(&fw_io->lock); - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + bitmap_zero(fw_io->status, KBASEP_FW_IO_STATUS_NUM_BITS); fw_io->kbdev = kbdev; } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_init); @@ -358,19 +357,19 @@ KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_read); void kbase_csf_fw_io_set_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - kbase_io_set_status(fw_io->kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + set_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_set_status_gpu_suspended); void kbase_csf_fw_io_clear_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - kbase_io_clear_status(fw_io->kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + clear_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_clear_status_gpu_suspended); bool kbase_csf_fw_io_check_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - return kbase_io_test_status(fw_io->kbdev, KBASE_IO_STATUS_GPU_SUSPENDED); + return test_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_check_status_gpu_suspended); diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.h index a46400484840..ba6b6bcc2800 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io.h @@ -31,6 +31,17 @@ /** The wait completed because the GPU was lost. */ #define KBASE_CSF_FW_IO_WAIT_GPU_LOST 1 +/** + * enum kbasep_csf_fw_io_status_bits - Status bits for firmware I/O interface. + * + * @KBASEP_FW_IO_STATUS_GPU_SUSPENDED: The GPU is suspended. + * @KBASEP_FW_IO_STATUS_NUM_BITS: Number of bits used to encode the status. + */ +enum kbasep_csf_fw_io_status_bits { + KBASEP_FW_IO_STATUS_GPU_SUSPENDED = 0, + KBASEP_FW_IO_STATUS_NUM_BITS, +}; + /** * struct kbasep_csf_fw_io_stream_pages - Addresses to CS I/O pages. * @@ -72,11 +83,13 @@ struct kbasep_csf_fw_io_pages { * struct kbase_csf_fw_io - Manager of firmware input/output interface. * * @lock: Mutex to serialize access to the interface. + * @status: Internal status of the MCU interface. * @pages: Addresses to FW I/O pages * @kbdev: Pointer to the instance of a GPU platform device that implements a CSF interface. */ struct kbase_csf_fw_io { spinlock_t lock; + DECLARE_BITMAP(status, KBASEP_FW_IO_STATUS_NUM_BITS); struct kbasep_csf_fw_io_pages pages; struct kbase_device *kbdev; }; @@ -169,7 +182,8 @@ void kbase_csf_fw_io_pages_term(struct kbase_csf_fw_io *fw_io, u32 group_num); */ static inline int kbase_csf_fw_io_open(struct kbase_csf_fw_io *fw_io, unsigned long *flags) { - if (kbase_io_test_status(fw_io->kbdev, KBASE_IO_STATUS_GPU_SUSPENDED)) + if (test_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status) || + kbase_io_is_aw_removed(fw_io->kbdev)) return -KBASE_CSF_FW_IO_WAIT_GPU_LOST; spin_lock_irqsave(&fw_io->lock, *flags); @@ -410,8 +424,8 @@ bool kbase_csf_fw_io_check_status_gpu_suspended(struct kbase_csf_fw_io *fw_io); /** * kbase_csf_fw_io_wait_event_timeout() - Wait until condition gets true, timeout - * occurs or a GPU_SUSPENDED FW I/O status bit is set. The rest of the functionalities is equal - * to wait_event_timeout(). + * occurs, GPU_SUSPENDED FW I/O status bit is set, or AW was removed. + * The rest of the functionalities is equal to wait_event_timeout(). * * @fw_io: Firmware I/O manager. * @wq_head: The waitqueue to wait on. @@ -420,16 +434,20 @@ bool kbase_csf_fw_io_check_status_gpu_suspended(struct kbase_csf_fw_io *fw_io); * * Return: Remaining jiffies (at least 1) on success, * 0 on timeout, - * negative KBASE_CSF_FW_IO_WAIT_LOST error if GPU_SUSPENDED FW I/O status bit is set. + * negative KBASE_CSF_FW_IO_WAIT_LOST error + * if GPU_SUSPENDED FW I/O status bit is set + * or AW was removed. */ -#define kbase_csf_fw_io_wait_event_timeout(fw_io, wq_head, condition, timeout) \ - ({ \ - int __ret; \ - int __wait_remaining = wait_event_timeout( \ - wq_head, (condition) || kbase_csf_fw_io_check_status_gpu_suspended(fw_io), \ - timeout); \ - __ret = kbasep_csf_fw_io_handle_wait_result(fw_io, __wait_remaining); \ - __ret; \ +#define kbase_csf_fw_io_wait_event_timeout(fw_io, wq_head, condition, timeout) \ + ({ \ + int __ret; \ + int __wait_remaining = wait_event_timeout( \ + wq_head, \ + (condition) || kbase_csf_fw_io_check_status_gpu_suspended(fw_io) || \ + kbase_io_is_aw_removed((fw_io)->kbdev), \ + timeout); \ + __ret = kbasep_csf_fw_io_handle_wait_result(fw_io, __wait_remaining); \ + __ret; \ }) /** @@ -441,13 +459,17 @@ bool kbase_csf_fw_io_check_status_gpu_suspended(struct kbase_csf_fw_io *fw_io); * * Return: Remaining jiffies (at least 1) on success, * 0 on timeout, - * negative KBASE_CSF_FW_IO_WAIT_LOST error if GPU_SUSPENDED FW I/O status bit is set. + * negative KBASE_CSF_FW_IO_WAIT_LOST error + * if GPU_SUSPENDED FW I/O status bit is set + * or AW was removed. */ static inline int kbasep_csf_fw_io_handle_wait_result(struct kbase_csf_fw_io *fw_io, int wait_remaining) { - return kbase_csf_fw_io_check_status_gpu_suspended(fw_io) ? -KBASE_CSF_FW_IO_WAIT_GPU_LOST : - wait_remaining; + return (kbase_csf_fw_io_check_status_gpu_suspended(fw_io) || + kbase_io_is_aw_removed(fw_io->kbdev)) ? + -KBASE_CSF_FW_IO_WAIT_GPU_LOST : + wait_remaining; } #if IS_ENABLED(CONFIG_MALI_VALHALL_DEBUG) || IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io_no_mali.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io_no_mali.c index 9907c151df82..22da5bb78ae8 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io_no_mali.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_fw_io_no_mali.c @@ -87,7 +87,7 @@ static inline void input_page_partial_write64(u64 *const input, const u32 offset void kbase_csf_fw_io_init(struct kbase_csf_fw_io *fw_io, struct kbase_device *kbdev) { spin_lock_init(&fw_io->lock); - kbase_io_clear_status(kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + bitmap_zero(fw_io->status, KBASEP_FW_IO_STATUS_NUM_BITS); fw_io->kbdev = kbdev; } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_init); @@ -393,19 +393,19 @@ KBASE_EXPORT_TEST_API(kbase_csf_fw_io_stream_read); void kbase_csf_fw_io_set_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - kbase_io_set_status(fw_io->kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + set_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_set_status_gpu_suspended); void kbase_csf_fw_io_clear_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - kbase_io_clear_status(fw_io->kbdev->io, KBASE_IO_STATUS_GPU_SUSPENDED); + clear_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_clear_status_gpu_suspended); bool kbase_csf_fw_io_check_status_gpu_suspended(struct kbase_csf_fw_io *fw_io) { - return kbase_io_test_status(fw_io->kbdev, KBASE_IO_STATUS_GPU_SUSPENDED); + return test_bit(KBASEP_FW_IO_STATUS_GPU_SUSPENDED, fw_io->status); } KBASE_EXPORT_TEST_API(kbase_csf_fw_io_check_status_gpu_suspended); diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.c index 65db914b895d..e30fb051a43e 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.c @@ -1664,7 +1664,7 @@ static int kbase_kcpu_fence_force_signal_process(struct kbase_kcpu_command_queue #endif /* dma_fence refcount needs to be decreased to release it. */ - dma_fence_put(fence_info->fence); + kbase_fence_put(fence_info->fence); fence_info->fence = NULL; return ret; @@ -1700,6 +1700,7 @@ static void kcpu_force_signal_fence(struct kbase_kcpu_command_queue *kcpu_queue) /* set ETIMEDOUT error flag before signal the fence*/ dma_fence_set_error_helper(fence, -ETIMEDOUT); + kbase_fence_put(fence); /* force signal fence */ status = @@ -1860,6 +1861,8 @@ static int kbasep_kcpu_fence_signal_init(struct kbase_kcpu_command_queue *kcpu_q goto fd_flags_fail; } + __module_get(THIS_MODULE); + kcpu_fence->module = THIS_MODULE; fence->basep.fd = *fd; current_command->type = BASE_KCPU_COMMAND_TYPE_FENCE_SIGNAL; diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.h index e9aa7b1f4801..625ac06ef9c4 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_kcpu.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2018-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_mcu_shared_reg.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_mcu_shared_reg.c index c22bc1ac396d..1a8c7cedef75 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_mcu_shared_reg.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_mcu_shared_reg.c @@ -850,8 +850,8 @@ int kbase_csf_mcu_shared_regs_data_init(struct kbase_device *kbdev) if (!shared_regs->dummy_phys) return -ENOMEM; - if (kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], 1, - &shared_regs->dummy_phys[0], false, NULL) <= 0) + if (kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, 1, &shared_regs->dummy_phys[0], + false, NULL) <= 0) return -ENOMEM; shared_regs->dummy_phys_allocated = true; @@ -920,7 +920,7 @@ void kbase_csf_mcu_shared_regs_data_term(struct kbase_device *kbdev) if (shared_regs->dummy_phys_allocated) { struct page *page = as_page(shared_regs->dummy_phys[0]); - kbase_mem_pool_free(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], page, false); + kbase_mem_pool_free(&kbdev->fw_mem_pools.small, page, false); } kfree(shared_regs->dummy_phys); diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_registers.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_registers.h index deb1878a0e6b..c08f48f48ec7 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_registers.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_registers.h @@ -204,6 +204,7 @@ #define GLB_GROUP_STRIDE 0x0014 /* () Stride between CSG interfaces */ #define GLB_PRFCNT_SIZE 0x0018 /* () Size of CSF performance counters */ #define GLB_INSTR_FEATURES 0x001C /* () TRACE_POINT instrumentation. (csf >= 1.1.0) */ +#define GLB_PRFCNT_FEATURES 0x0020 /* () Performance counter features */ #define GROUP_CONTROL_0 0x1000 /* () CSG control and capabilities */ #define GROUP_CONTROL(n) (GROUP_CONTROL_0 + (n)*256) #define GROUP_CONTROL_REG(n, r) (GROUP_CONTROL(n) + GROUP_CONTROL_BLOCK_REG(r)) @@ -1982,6 +1983,16 @@ #define GLB_PRFCNT_CONFIG_SET_SELECT_SET(reg_val, value) \ (((reg_val) & ~GLB_PRFCNT_CONFIG_SET_SELECT_MASK) | \ (((value) << GLB_PRFCNT_CONFIG_SET_SELECT_SHIFT) & GLB_PRFCNT_CONFIG_SET_SELECT_MASK)) +#define GLB_PRFCNT_CONFIG_METADATA_ENABLE_SHIFT GPU_U(10) +#define GLB_PRFCNT_CONFIG_METADATA_ENABLE_MASK \ + (GPU_U(0x1) << GLB_PRFCNT_CONFIG_METADATA_ENABLE_SHIFT) +#define GLB_PRFCNT_CONFIG_METADATA_ENABLE_GET(reg_val) \ + (((reg_val)&GLB_PRFCNT_CONFIG_METADATA_ENABLE_MASK) >> \ + GLB_PRFCNT_CONFIG_METADATA_ENABLE_SHIFT) +#define GLB_PRFCNT_CONFIG_METADATA_ENABLE_SET(reg_val, value) \ + (~(~(reg_val) | GLB_PRFCNT_CONFIG_METADATA_ENABLE_MASK) | \ + (((value) << GLB_PRFCNT_CONFIG_METADATA_ENABLE_SHIFT) & \ + GLB_PRFCNT_CONFIG_METADATA_ENABLE_MASK)) /* GLB_PRFCNT_SIZE register */ #define GLB_PRFCNT_SIZE_HARDWARE_SIZE_SET_MOD(value) ((value) >> 8) @@ -2007,6 +2018,16 @@ ((GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SET_MOD(value) << GLB_PRFCNT_SIZE_FIRMWARE_SIZE_SHIFT) & \ GLB_PRFCNT_SIZE_FIRMWARE_SIZE_MASK)) +/* GLB_PRFCNT_FEATURES register */ +#define GLB_PRFCNT_FEATURES_METADATA_SIZE_GET_MOD(value) (value << 8) +#define GLB_PRFCNT_FEATURES_METADATA_SIZE_SHIFT GPU_U(0) +#define GLB_PRFCNT_FEATURES_METADATA_SIZE_MASK \ + (GPU_U(0xF) << GLB_PRFCNT_FEATURES_METADATA_SIZE_SHIFT) +#define GLB_PRFCNT_FEATURES_METADATA_SIZE_GET(reg_val) \ + (GLB_PRFCNT_FEATURES_METADATA_SIZE_GET_MOD( \ + ((reg_val)&GLB_PRFCNT_FEATURES_METADATA_SIZE_MASK) >> \ + GLB_PRFCNT_FEATURES_METADATA_SIZE_SHIFT)) + /* GLB_DEBUG_REQ register */ #define GLB_DEBUG_REQ_DEBUG_RUN_SHIFT GPU_U(23) #define GLB_DEBUG_REQ_DEBUG_RUN_MASK (GPU_U(0x1) << GLB_DEBUG_REQ_DEBUG_RUN_SHIFT) diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_reset_gpu.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_reset_gpu.c index 03fdf60ce1b5..1fa97035a8dd 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_reset_gpu.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_reset_gpu.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -243,7 +243,6 @@ static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev) kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)), kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK)), kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK))); -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { dev_err(kbdev->dev, " PWR_IRQ_RAWSTAT=0x%08x", kbase_reg_read32(kbdev, HOST_POWER_ENUM(PWR_IRQ_RAWSTAT))); @@ -252,7 +251,6 @@ static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev) dev_err(kbdev->dev, " PWR_STATUS=0x%016llx", kbase_reg_read64(kbdev, HOST_POWER_ENUM(PWR_STATUS))); } -#endif if (kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(14, 10, 0)) { dev_err(kbdev->dev, " PWR_OVERRIDE0=0x%08x PWR_OVERRIDE1=0x%08x", kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(PWR_OVERRIDE0)), @@ -264,7 +262,6 @@ static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev) kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(TILER_CONFIG))); } -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { u32 domain_status; @@ -276,7 +273,6 @@ static void kbase_csf_debug_dump_registers(struct kbase_device *kbdev) dev_err(kbdev->dev, " L2_PWR_STATUS=0x%05llx", kbase_reg_read64(kbdev, HOST_POWER_ENUM(PWR_CMDARG))); } -#endif spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } @@ -426,13 +422,17 @@ static int kbase_csf_reset_gpu_now(struct kbase_device *kbdev, bool firmware_ini spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbdev->csf.firmware_reload_needed = false; + /* Prevent MCU enable before FW data is reloaded */ + kbdev->pm.backend.in_reset = true; spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); cancel_work_sync(&kbdev->csf.firmware_reload_work); - dev_dbg(kbdev->dev, "Disable GPU hardware counters.\n"); - /* This call will block until counters are disabled. */ - kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); + { + dev_dbg(kbdev->dev, "Disable GPU hardware counters.\n"); + /* This call will block until counters are disabled. */ + kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); + } ret = kbase_csf_reset_gpu_once(kbdev, firmware_inited, silent); @@ -488,13 +488,12 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); firmware_inited = kbdev->csf.firmware_inited; -#ifdef KBASE_PM_RUNTIME - gpu_sleep_mode_active = kbdev->pm.backend.gpu_sleep_mode_active; -#endif + if (IS_ENABLED(CONFIG_PM)) + gpu_sleep_mode_active = kbdev->pm.backend.gpu_sleep_mode_active; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - if (unlikely(gpu_sleep_mode_active)) { -#ifdef KBASE_PM_RUNTIME + if (unlikely(gpu_sleep_mode_active) && IS_ENABLED(CONFIG_PM)) { /* As prior to GPU reset all on-slot groups are suspended, * need to wake up the MCU from sleep. * No pm active reference is taken here since GPU is in sleep @@ -508,7 +507,6 @@ static void kbase_csf_reset_gpu_worker(struct work_struct *data) kbase_pm_unlock(kbdev); err = kbase_csf_reset_gpu_now(kbdev, firmware_inited, silent); -#endif } else if (!kbase_pm_context_active_handle_suspend( kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { err = kbase_csf_reset_gpu_now(kbdev, firmware_inited, silent); diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.c index bda9bf1ceafa..ca7db6074bab 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.c @@ -277,6 +277,9 @@ static u64 drain_gpu_metrics_trace_buffer(struct kbase_device *kbdev) lockdep_assert_held(&kbdev->csf.scheduler.gpu_metrics_lock); + if (kbase_io_is_aw_removed(kbdev)) + return 0; + kbase_backend_get_gpu_time_norequest(kbdev, NULL, &system_time, NULL); /* CPU time value that was used to derive the parameters for time conversion, * was retrieved from ktime_get_raw_ts64(). But the tracing subsystem would use @@ -503,7 +506,6 @@ static void schedule_actions_trigger_df(struct kbase_device *kbdev, struct kbase #endif } -#ifdef KBASE_PM_RUNTIME /** * wait_for_scheduler_to_exit_sleep() - Wait for Scheduler to exit the * sleeping state. @@ -519,7 +521,11 @@ static void schedule_actions_trigger_df(struct kbase_device *kbdev, struct kbase static int wait_for_scheduler_to_exit_sleep(struct kbase_device *kbdev) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; +#if IS_ENABLED(CONFIG_PM) int autosuspend_delay = kbdev->dev->power.autosuspend_delay; +#else + int autosuspend_delay = 0; +#endif unsigned int sleep_exit_wait_time; long remaining; int ret = 0; @@ -578,7 +584,7 @@ static int force_scheduler_to_exit_sleep(struct kbase_device *kbdev) lockdep_assert_held(&scheduler->lock); WARN_ON(scheduler->state != SCHED_SLEEPING); - WARN_ON(!kbdev->pm.backend.gpu_sleep_mode_active); + WARN_ON(!kbdev->pm.backend.gpu_sleep_mode_active && !kbase_io_is_aw_removed(kbdev)); kbase_pm_lock(kbdev); ret = kbase_pm_force_mcu_wakeup_after_sleep(kbdev); @@ -626,7 +632,6 @@ out: return ret; } -#endif /** * tick_timer_callback() - Callback function for the scheduling tick hrtimer @@ -1061,7 +1066,6 @@ static int scheduler_pm_active_handle_suspend(struct kbase_device *kbdev, return ret; } -#ifdef KBASE_PM_RUNTIME /** * scheduler_pm_active_after_sleep() - Acquire the PM reference count for * Scheduler @@ -1084,7 +1088,6 @@ static int scheduler_pm_active_after_sleep(struct kbase_device *kbdev) return scheduler_pm_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE, true); } -#endif /** * scheduler_pm_idle() - Release the PM reference count held by Scheduler @@ -1102,7 +1105,6 @@ static inline void scheduler_pm_idle(struct kbase_device *kbdev) kbase_pm_context_idle(kbdev); } -#ifdef KBASE_PM_RUNTIME /** * scheduler_pm_idle_before_sleep() - Release the PM reference count and * trigger the transition to sleep state. @@ -1126,7 +1128,6 @@ static void scheduler_pm_idle_before_sleep(struct kbase_device *kbdev) scheduler_pm_idle(kbdev); } -#endif static void scheduler_wakeup(struct kbase_device *kbdev, bool kick) { @@ -1149,11 +1150,9 @@ static void scheduler_wakeup(struct kbase_device *kbdev, bool kick) HRTIMER_MODE_REL_SOFT); } #endif - } else { -#ifdef KBASE_PM_RUNTIME + } else if (IS_ENABLED(CONFIG_PM)) { dev_dbg(kbdev->dev, "Re-activating the Scheduler out of sleep"); ret = scheduler_pm_active_after_sleep(kbdev); -#endif } if (ret) { @@ -1178,19 +1177,21 @@ static int scheduler_suspend(struct kbase_device *kbdev) lockdep_assert_held(&scheduler->lock); if (!WARN_ON(scheduler->state == SCHED_SUSPENDED)) { -#if KBASE_PM_RUNTIME - int ret; + if (IS_ENABLED(CONFIG_PM)) { + int ret; - /* If GPU-level suspend is not supported then all on-slot CSGs - * will be suspended one at a time. Disable Sleep-on-Idle to - * avoid repeated cycles of FW going to sleep and resuming. - * GLB_IDLE timer (and Sleep-on-Idle) would otherwise be - * disabled just before the MCU transitions out of HALT state. - */ - ret = kbase_csf_firmware_soi_disable_on_scheduler_suspend(kbdev); - if (ret) - return ret; -#endif /* KBASE_PM_RUNTIME */ + /* If GPU-level suspend is not supported then all on-slot CSGs + * will be suspended one at a time. Disable Sleep-on-Idle to + * avoid repeated cycles of FW going to sleep and resuming. + * GLB_IDLE timer (and Sleep-on-Idle) would otherwise be + * disabled just before the MCU transitions out of HALT state. + */ + { + ret = kbase_csf_firmware_soi_disable_on_scheduler_suspend(kbdev); + if (ret) + return ret; + } + } dev_dbg(kbdev->dev, "Suspending the Scheduler"); scheduler_pm_idle(kbdev); scheduler->state = SCHED_SUSPENDED; @@ -2321,7 +2322,7 @@ static void process_cs_pending_events(struct kbase_csf_fw_io *fw_io, u32 group_i } /** - * save_slot_cs() - Save the state for blocked GPU command queue. + * save_cs_wait_state() - Save the state for blocked GPU command queue. * * @fw_io: Pointer to FW I/O manager. * @group_id: GPU on-slot CSG index. @@ -2334,7 +2335,8 @@ static void process_cs_pending_events(struct kbase_csf_fw_io *fw_io, u32 group_i * * Return: true if the queue is blocked on a sync wait operation. */ -static bool save_slot_cs(struct kbase_csf_fw_io *fw_io, u32 group_id, struct kbase_queue *queue) +static bool save_cs_wait_state(struct kbase_csf_fw_io *fw_io, u32 group_id, + struct kbase_queue *queue) { u32 stream_id = queue->csi_index; u32 status; @@ -2388,8 +2390,6 @@ static bool save_slot_cs(struct kbase_csf_fw_io *fw_io, u32 group_id, struct kba queue->status_wait = 0; } - process_cs_pending_events(fw_io, group_id, queue); - return is_waiting; } @@ -2792,31 +2792,35 @@ static void save_csg_slot(struct kbase_queue_group *group) for (i = 0; i < max_streams; i++) update_hw_active(group->bound_queues[i], false); #endif /* CONFIG_MALI_VALHALL_NO_MALI */ - for (i = 0; idle && i < max_streams; i++) { + for (i = 0; i < max_streams; i++) { struct kbase_queue *const queue = group->bound_queues[i]; if (!queue || !queue->enabled) continue; - if (save_slot_cs(&kbdev->csf.fw_io, group->csg_nr, queue)) { - /* sync_wait is only true if the queue is blocked on - * a CQS and not a scoreboard. - */ - if (queue->blocked_reason != CS_STATUS_BLOCKED_ON_SB_WAIT) - sync_wait = true; - } else { - /* Need to confirm if ringbuffer of the GPU - * queue is empty or not. A race can arise - * between the flush of GPU queue and suspend - * of CSG. If a queue is flushed after FW has - * set the IDLE bit in CSG_STATUS_STATE, then - * Scheduler will incorrectly consider CSG - * as idle. And there may not be any further - * flush call for the GPU queue, which would - * have de-idled the CSG. - */ - idle = confirm_cmd_buf_empty(queue); + if (idle) { + if (save_cs_wait_state(&kbdev->csf.fw_io, group->csg_nr, queue)) { + /* sync_wait is only true if the queue is blocked on + * a CQS and not a scoreboard. + */ + if (queue->blocked_reason != CS_STATUS_BLOCKED_ON_SB_WAIT) + sync_wait = true; + } else { + /* Need to confirm if ringbuffer of the GPU + * queue is empty or not. A race can arise + * between the flush of GPU queue and suspend + * of CSG. If a queue is flushed after FW has + * set the IDLE bit in CSG_STATUS_STATE, then + * Scheduler will incorrectly consider CSG + * as idle. And there may not be any further + * flush call for the GPU queue, which would + * have de-idled the CSG. + */ + idle = confirm_cmd_buf_empty(queue); + } } + + process_cs_pending_events(&kbdev->csf.fw_io, group->csg_nr, queue); } if (idle) { @@ -3028,7 +3032,8 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, u8 prio) const u64 compute_mask = shader_core_mask & group->compute_mask; const u64 fragment_mask = shader_core_mask & group->fragment_mask; const u64 tiler_mask = tiler_core_mask & group->tiler_mask; - const u64 neural_mask = shader_core_mask & group->neural_mask; + const u64 neural_mask = shader_core_mask & group->neural_mask & + kbdev->csf.neural_allowed_mask; const u8 neural_max = min(kbdev->gpu_props.num_cores, group->neural_max); const u8 comp_pri_threshold = min_t(u8, group->comp_pri_threshold, (u8)COMP_PRI_THRESHOLD_MAX); @@ -3116,6 +3121,13 @@ static void program_csg_slot(struct kbase_queue_group *group, s8 slot, u8 prio) goto skip_fw; } + if (kbdev->csf.neural_allowed_mask != UINT64_MAX) + dev_warn_once( + kbdev->dev, + "neural_allowed_mask module param passed in as 0x%llx. Writing restricted neural_mask 0x%llx to CSG_ALLOW_NEURAL. shader_core_mask 0x%llx group->neural_mask 0x%llx", + kbdev->csf.neural_allowed_mask, neural_mask, shader_core_mask, + group->neural_mask); + /* Endpoint programming for CSG */ kbase_csf_fw_io_group_write(fw_io, slot, CSG_ALLOW_COMPUTE_LO, compute_mask & U32_MAX); kbase_csf_fw_io_group_write(fw_io, slot, CSG_ALLOW_COMPUTE_HI, compute_mask >> 32); @@ -3356,7 +3368,6 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) on_slot = kbasep_csf_scheduler_group_is_on_slot_locked(group); -#ifdef KBASE_PM_RUNTIME /* If the queue group is on slot and Scheduler is in SLEEPING state, * then we need to wake up the Scheduler to exit the sleep state rather * than waiting for the runtime suspend or power down of GPU. @@ -3364,7 +3375,7 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) * thread and it has been seen that certain Apps can destroy groups at * random points and not necessarily when the App is exiting. */ - if (on_slot && (scheduler->state == SCHED_SLEEPING)) { + if (IS_ENABLED(CONFIG_PM) && on_slot && (scheduler->state == SCHED_SLEEPING)) { scheduler_wakeup(kbdev, true); /* Wait for MCU firmware to start running */ @@ -3380,7 +3391,7 @@ void kbase_csf_scheduler_group_deschedule(struct kbase_queue_group *group) wait_for_termination = false; } } -#endif + if (!on_slot) { sched_evict_group(group, false, true); } else { @@ -5144,7 +5155,6 @@ static bool scheduler_idle_suspendable(struct kbase_device *kbdev) return suspend; } -#ifdef KBASE_PM_RUNTIME /** * scheduler_sleep_on_idle - Put the Scheduler in sleeping state on GPU * becoming idle. @@ -5168,7 +5178,6 @@ static void scheduler_sleep_on_idle(struct kbase_device *kbdev) scheduler->state = SCHED_SLEEPING; KBASE_KTRACE_ADD(kbdev, SCHED_SLEEPING, NULL, scheduler->state); } -#endif /** * scheduler_suspend_on_idle - Put the Scheduler in suspended state on GPU @@ -5213,6 +5222,11 @@ static void gpu_idle_worker(struct kbase_device *kbdev) WARN_ON_ONCE(atomic_read(&scheduler->pending_gpu_idle_work) == 0); + if (kbase_io_is_aw_removed(kbdev)) { + dev_info(kbdev->dev, "%s(): aborting as AW is no longer connected", __func__); + goto exit; + } + KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_START, NULL, 0u); #define __ENCODE_KTRACE_INFO(reset, idle, all_suspend) \ @@ -5239,12 +5253,11 @@ static void gpu_idle_worker(struct kbase_device *kbdev) if (scheduler_is_idle_suspendable) { KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_HANDLING_START, NULL, kbase_csf_ktrace_gpu_cycle_cnt(kbdev)); -#ifdef KBASE_PM_RUNTIME - if (kbase_pm_gpu_sleep_allowed(kbdev) && + + if (IS_ENABLED(CONFIG_PM) && kbase_pm_gpu_sleep_allowed(kbdev) && kbase_csf_scheduler_get_nr_active_csgs(kbdev)) scheduler_sleep_on_idle(kbdev); else -#endif all_groups_suspended = scheduler_suspend_on_idle(kbdev); KBASE_KTRACE_ADD(kbdev, SCHEDULER_GPU_IDLE_WORKER_HANDLING_END, NULL, 0u); @@ -5758,8 +5771,16 @@ static bool can_skip_scheduling(struct kbase_device *kbdev) if (scheduler->state == SCHED_SUSPENDED) return true; -#ifdef KBASE_PM_RUNTIME - if (scheduler->state == SCHED_SLEEPING) { + /* + * Schduler should always be in SUSPENDED state when + * AW is removed. + */ + if (kbase_io_is_aw_removed(kbdev)) { + dev_warn(kbdev->dev, "Skipping scheduling as AW is no longer connected"); + return true; + } + + if (IS_ENABLED(CONFIG_PM) && scheduler->state == SCHED_SLEEPING) { unsigned long flags; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); @@ -5780,7 +5801,6 @@ static bool can_skip_scheduling(struct kbase_device *kbdev) spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); return true; } -#endif return false; } @@ -5834,7 +5854,7 @@ exit_no_schedule_unlock: static void schedule_on_tick(struct kbase_device *kbdev) { struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; - + struct kbase_csf_sched_heap_reclaim_mgr *mgr = &kbdev->csf.scheduler.reclaim_mgr; int err = kbase_reset_gpu_try_prevent(kbdev); /* Regardless of whether reset failed or is currently happening, exit * early @@ -5871,6 +5891,8 @@ static void schedule_on_tick(struct kbase_device *kbdev) } scheduler->state = SCHED_INACTIVE; + if (atomic_read(&mgr->unused_pages)) + kbase_csf_tiler_heap_reclaim_unused_pages(kbdev, HEAP_RECLAIM_SCENARIO_SCHEDULER); mutex_unlock(&scheduler->lock); KBASE_KTRACE_ADD(kbdev, SCHED_INACTIVE, NULL, scheduler->state); kbase_reset_gpu_allow(kbdev); @@ -5903,8 +5925,10 @@ static int suspend_active_queue_groups(struct kbase_device *kbdev, unsigned long suspend_queue_group(group); set_bit(slot_num, slot_mask); } - ret = wait_csg_slots_suspend(kbdev, slot_mask); } + + ret = wait_csg_slots_suspend(kbdev, slot_mask); + return ret; } @@ -6083,15 +6107,14 @@ static void scheduler_inner_reset(struct kbase_device *kbdev) scheduler->num_active_address_spaces | (((u64)scheduler->total_runnable_grps) << 32)); -#ifdef KBASE_PM_RUNTIME - if (scheduler->state == SCHED_SLEEPING) { + if (IS_ENABLED(CONFIG_PM) && scheduler->state == SCHED_SLEEPING) { #if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) hrtimer_cancel(&scheduler->gpu_metrics_timer); #endif scheduler->state = SCHED_SUSPENDED; KBASE_KTRACE_ADD(kbdev, SCHED_SUSPENDED, NULL, scheduler->state); } -#endif + mutex_unlock(&scheduler->lock); } @@ -6241,8 +6264,7 @@ int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group, on_slot = kbasep_csf_scheduler_group_is_on_slot_locked(group); -#ifdef KBASE_PM_RUNTIME - if (on_slot && (scheduler->state == SCHED_SLEEPING)) { + if (IS_ENABLED(CONFIG_PM) && on_slot && (scheduler->state == SCHED_SLEEPING)) { if (wait_for_scheduler_to_exit_sleep(kbdev)) { dev_warn( kbdev->dev, @@ -6265,7 +6287,7 @@ int kbase_csf_scheduler_group_copy_suspend_buf(struct kbase_queue_group *group, */ on_slot = kbasep_csf_scheduler_group_is_on_slot_locked(group); } -#endif + if (on_slot) { DECLARE_BITMAP(slot_mask, BASEP_QUEUE_GROUP_MAX) = { 0 }; @@ -6812,7 +6834,6 @@ event_wait_add_failed: void kbase_csf_scheduler_context_term(struct kbase_context *kctx) { - kbase_ctx_sched_remove_ctx(kctx); #if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) gpu_metrics_ctx_term(kctx); #endif /* CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD */ @@ -6984,6 +7005,12 @@ static int kbase_csf_scheduler_kthread(void *data) while (atomic_read(&scheduler->pending_gpu_idle_work) > 0) gpu_idle_worker(kbdev); + /* Drain pending GPU suspend work */ + if (atomic_read(&scheduler->pending_runtime_suspend_work) == true) { + kbdev->pm.runtime_suspend_result = kbase_pm_handle_runtime_suspend(kbdev); + atomic_set(&scheduler->pending_runtime_suspend_work, false); + } + /* Drain pending GPU power off work */ if (atomic_cmpxchg(&scheduler->pending_power_off_work, true, false) == true) kbase_pm_handle_gpu_poweroff_wait_work(kbdev); @@ -7097,6 +7124,7 @@ int kbase_csf_scheduler_early_init(struct kbase_device *kbdev) atomic_set(&scheduler->pending_tick_work, false); atomic_set(&scheduler->pending_tock_work, false); atomic_set(&scheduler->pending_gpu_idle_work, 0); + atomic_set(&scheduler->pending_runtime_suspend_work, false); atomic_set(&scheduler->pending_power_off_work, false); return kbase_csf_tiler_heap_reclaim_mgr_init(kbdev); @@ -7240,11 +7268,22 @@ int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev) return -EBUSY; #endif -#ifdef KBASE_PM_RUNTIME + if (kbase_io_is_aw_removed(kbdev)) { + dev_warn(kbdev->dev, "Suspending scheduler(AW_REMOVED), state: %d", + scheduler->state); + if (scheduler->state != SCHED_SUSPENDED && scheduler->state != SCHED_SLEEPING) + scheduler_pm_idle(kbdev); + scheduler->state = SCHED_SUSPENDED; +#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) + hrtimer_cancel(&scheduler->gpu_metrics_timer); +#endif + return 0; + } + /* If scheduler is in sleeping state, then MCU needs to be activated * to suspend CSGs. */ - if (scheduler->state == SCHED_SLEEPING) { + if (IS_ENABLED(CONFIG_PM) && scheduler->state == SCHED_SLEEPING) { dev_info(kbdev->dev, "Activating MCU out of sleep on system suspend"); result = force_scheduler_to_exit_sleep(kbdev); if (result) { @@ -7252,7 +7291,7 @@ int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev) goto exit; } } -#endif + if (scheduler->state != SCHED_SUSPENDED) { result = suspend_active_groups_on_powerdown(kbdev, true); if (result) { @@ -7267,6 +7306,17 @@ int kbase_csf_scheduler_pm_suspend_no_lock(struct kbase_device *kbdev) } exit: + if (result && kbase_io_is_aw_removed(kbdev)) { + dev_warn(kbdev->dev, "Forcing scheduler suspend(AW_REMOVED), state: %d", + scheduler->state); + if (scheduler->state != SCHED_SUSPENDED && scheduler->state != SCHED_SLEEPING) + scheduler_pm_idle(kbdev); + scheduler->state = SCHED_SUSPENDED; +#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) + hrtimer_cancel(&scheduler->gpu_metrics_timer); +#endif + result = 0; + } return result; } @@ -7361,7 +7411,10 @@ static int scheduler_wait_mcu_active(struct kbase_device *kbdev, bool killable_w err = kbase_pm_wait_for_desired_state(kbdev); if (!err) { spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_ON); + if (kbase_io_is_aw_removed(kbdev)) + err = -ENODEV; + else + WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_ON); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } @@ -7380,7 +7433,6 @@ int kbase_csf_scheduler_wait_mcu_active(struct kbase_device *kbdev) KBASE_EXPORT_TEST_API(kbase_csf_scheduler_wait_mcu_active); -#ifdef KBASE_PM_RUNTIME int kbase_csf_scheduler_handle_runtime_suspend(struct kbase_device *kbdev) { struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; @@ -7532,7 +7584,6 @@ void kbase_csf_scheduler_force_sleep(struct kbase_device *kbdev) scheduler_sleep_on_idle(kbdev); mutex_unlock(&scheduler->lock); } -#endif void kbase_csf_scheduler_force_wakeup(struct kbase_device *kbdev) { diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.h index 50d2f0fbd853..96e9e35b49db 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_scheduler.h @@ -610,7 +610,6 @@ static inline bool kbase_csf_scheduler_queue_has_trace(struct kbase_queue *queue return (queue->trace_buffer_size && queue->trace_buffer_base); } -#ifdef KBASE_PM_RUNTIME /** * kbase_csf_scheduler_reval_idleness_post_sleep() - Check GPU's idleness after * putting MCU to sleep state @@ -645,7 +644,6 @@ void kbase_csf_scheduler_reval_idleness_post_sleep(struct kbase_device *kbdev); * Return: 0 if all the CSGs were suspended, otherwise an error code. */ int kbase_csf_scheduler_handle_runtime_suspend(struct kbase_device *kbdev); -#endif /** * kbase_csf_scheduler_process_gpu_idle_event() - Process GPU idle IRQ @@ -697,7 +695,6 @@ u32 kbase_csf_scheduler_get_nr_active_csgs_locked(struct kbase_device *kbdev); */ void kbase_csf_scheduler_force_wakeup(struct kbase_device *kbdev); -#ifdef KBASE_PM_RUNTIME /** * kbase_csf_scheduler_force_sleep() - Forcefully put the Scheduler to sleeping * state. @@ -710,7 +707,6 @@ void kbase_csf_scheduler_force_wakeup(struct kbase_device *kbdev); * This function is only used for testing purpose. */ void kbase_csf_scheduler_force_sleep(struct kbase_device *kbdev); -#endif #endif /* _KBASE_CSF_SCHEDULER_H_ */ diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.c index ce0ecea13d16..8496d145f6fd 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.c @@ -34,6 +34,13 @@ /* Tiler heap reclaim scan (free) method size for limiting a scan run length */ #define HEAP_RECLAIM_SCAN_BATCH_SIZE (HEAP_SHRINKER_BATCH << 7) +/* + * Default setting for reclaiming offslot CSG's heap. + * Disabling reclaim with pages being 0. + */ +#define HEAP_RECLAIM_OFFSLOT_TIMEOUT_MS (30000) +#define HEAP_RECLAIM_OFFSLOT_PAGES (0) + static u8 get_kctx_highest_csg_priority(struct kbase_context *kctx) { u8 prio; @@ -76,6 +83,9 @@ static void detach_ctx_from_heap_reclaim_mgr(struct kbase_context *kctx) "Reclaim_mgr_detach: ctx_%d_%d, est_pages=0%u, freed_pages=%u", kctx->tgid, kctx->id, info->nr_est_unused_pages, info->nr_freed_pages); } + + /* 0 indicates that the kctx may have CSG on slot */ + kctx->offslot_ts = 0; } static void attach_ctx_to_heap_reclaim_mgr(struct kbase_context *kctx) @@ -98,8 +108,9 @@ static void attach_ctx_to_heap_reclaim_mgr(struct kbase_context *kctx) /* Accumulate the estimated pages to the manager total field */ atomic_add((int)info->nr_est_unused_pages, &scheduler->reclaim_mgr.unused_pages); - dev_dbg(kctx->kbdev->dev, "Reclaim_mgr_attach: ctx_%d_%d, est_count_pages=%u", kctx->tgid, - kctx->id, info->nr_est_unused_pages); + kctx->offslot_ts = ktime_get_raw_ns(); + dev_dbg(kctx->kbdev->dev, "Reclaim_mgr_attach [%llu]: ctx_%d_%d, est_count_pages=%u", + kctx->offslot_ts, kctx->tgid, kctx->id, info->nr_est_unused_pages); } void kbase_csf_tiler_heap_reclaim_sched_notify_grp_active(struct kbase_queue_group *group) @@ -187,15 +198,43 @@ void kbase_csf_tiler_heap_reclaim_sched_notify_grp_suspend(struct kbase_queue_gr } } -static unsigned long reclaim_unused_heap_pages(struct kbase_device *kbdev) +unsigned long kbase_csf_tiler_heap_reclaim_unused_pages(struct kbase_device *kbdev, + enum heap_reclaim_scenario scenario) { struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; struct kbase_csf_sched_heap_reclaim_mgr *const mgr = &scheduler->reclaim_mgr; - unsigned long total_freed_pages = 0; - int prio; + unsigned long total_freed_pages = 0, max_pages; + int prio, min_prio; + u64 now = 0, offslot_ts = 0; lockdep_assert_held(&scheduler->lock); + if (scenario == HEAP_RECLAIM_SCENARIO_SHRINKER) { + /* triggered by shrinker */ + max_pages = HEAP_RECLAIM_SCAN_BATCH_SIZE; + min_prio = KBASE_QUEUE_GROUP_PRIORITY_REALTIME; + } else if (scenario == HEAP_RECLAIM_SCENARIO_SCHEDULER) { + /* triggered by schedule_on_tick + * reclaim heap from CSGs with below conditions: + * 1.being offslot for a period + * 2.limit page numbers for each reclaim + * 3.skip RT kctx + */ + if (mgr->offslot_setting.pages == 0) { + dev_dbg(kbdev->dev, "HEAP_RECLAIM_SCENARIO_SCHEDULER is disabled"); + return 0; + } + max_pages = mgr->offslot_setting.pages; + min_prio = KBASE_QUEUE_GROUP_PRIORITY_HIGH; + now = ktime_get_raw_ns(); + offslot_ts = now > mgr->offslot_setting.timeout_ms * 1000000ULL ? + now - mgr->offslot_setting.timeout_ms * 1000000ULL : + 0; + } else { + dev_err(kbdev->dev, "Unknown heap reclaim scenario %d\n", scenario); + return 0; + } + if (scheduler->state != SCHED_SUSPENDED) { /* Clean and invalidate the L2 cache before reading from the heap contexts, * headers of the individual chunks and buffer descriptors. @@ -219,9 +258,7 @@ static unsigned long reclaim_unused_heap_pages(struct kbase_device *kbdev) } for (prio = KBASE_QUEUE_GROUP_PRIORITY_LOW; - total_freed_pages < HEAP_RECLAIM_SCAN_BATCH_SIZE && - prio >= KBASE_QUEUE_GROUP_PRIORITY_REALTIME; - prio--) { + total_freed_pages < max_pages && prio >= min_prio; prio--) { struct kbase_csf_ctx_heap_reclaim_info *info, *tmp; u32 cnt_ctxs = 0; @@ -229,9 +266,26 @@ static unsigned long reclaim_unused_heap_pages(struct kbase_device *kbdev) mgr_link) { struct kbase_context *kctx = container_of(info, struct kbase_context, csf.sched.heap_info); - u32 freed_pages = kbase_csf_tiler_heap_scan_kctx_unused_pages( + u32 freed_pages; + + if (scenario == HEAP_RECLAIM_SCENARIO_SCHEDULER) { + WARN_ON(kctx->offslot_ts == 0); + if (kctx->offslot_ts > offslot_ts) { + dev_dbg(kbdev->dev, + "Reclaim aborts from ctx %d_%d, prio %d, current time %llu - offslot time %llu = %llu", + kctx->tgid, kctx->id, prio, now, kctx->offslot_ts, + now - kctx->offslot_ts); + /* Skip following ctx as they are attached later */ + break; + } + } + + freed_pages = kbase_csf_tiler_heap_scan_kctx_unused_pages( kctx, info->nr_est_unused_pages); + dev_dbg(kbdev->dev, "Reclaim free heap pages for ctx %d_%d freed pages %u", + kctx->tgid, kctx->id, freed_pages); + if (freed_pages) { /* Remove the freed pages from the manager retained estimate. The * accumulated removals from the kctx should not exceed the kctx @@ -260,7 +314,7 @@ static unsigned long reclaim_unused_heap_pages(struct kbase_device *kbdev) cnt_ctxs++; /* Enough has been freed, break to avoid holding the lock too long */ - if (total_freed_pages >= HEAP_RECLAIM_SCAN_BATCH_SIZE) + if (total_freed_pages >= max_pages) break; } @@ -313,7 +367,8 @@ static unsigned long kbase_csf_tiler_heap_reclaim_scan_free_pages(struct kbase_d avail = (unsigned long)atomic_read(&mgr->unused_pages); if (avail) - freed = reclaim_unused_heap_pages(kbdev); + freed = kbase_csf_tiler_heap_reclaim_unused_pages(kbdev, + HEAP_RECLAIM_SCENARIO_SHRINKER); mutex_unlock(&kbdev->csf.scheduler.lock); @@ -372,6 +427,9 @@ int kbase_csf_tiler_heap_reclaim_mgr_init(struct kbase_device *kbdev) prio++) INIT_LIST_HEAD(&scheduler->reclaim_mgr.ctx_lists[prio]); + scheduler->reclaim_mgr.offslot_setting.timeout_ms = HEAP_RECLAIM_OFFSLOT_TIMEOUT_MS; + scheduler->reclaim_mgr.offslot_setting.pages = HEAP_RECLAIM_OFFSLOT_PAGES; + reclaim->count_objects = kbase_csf_tiler_heap_reclaim_count_objects; reclaim->scan_objects = kbase_csf_tiler_heap_reclaim_scan_objects; reclaim->seeks = HEAP_SHRINKER_SEEKS; diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.h index d41b7baabd02..e74bd4f25926 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_tiler_heap_reclaim.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2022-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2022-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -79,4 +79,26 @@ int kbase_csf_tiler_heap_reclaim_mgr_init(struct kbase_device *kbdev); */ void kbase_csf_tiler_heap_reclaim_mgr_term(struct kbase_device *kbdev); +/** + * enum heap_reclaim_scenario - heap reclaim scenario list. + * + * @HEAP_RECLAIM_SCENARIO_SHRINKER: Reclaim through shrinker. + * @HEAP_RECLAIM_SCENARIO_SCHEDULER: Reclaim through scheduler. + * @HEAP_RECLAIM_SCENARIO_COUNT: The number of reclaim scenarios. + */ +enum heap_reclaim_scenario { + HEAP_RECLAIM_SCENARIO_SHRINKER = 0, + HEAP_RECLAIM_SCENARIO_SCHEDULER, + HEAP_RECLAIM_SCENARIO_COUNT +}; + +/** + * kbase_csf_tiler_heap_reclaim_unused_pages - Reclaim unused heap pages. + * @kbdev: Pointer to the device. + * @scenario: Reclaim scenario. + * + * Return: total freed pages. + */ +unsigned long kbase_csf_tiler_heap_reclaim_unused_pages(struct kbase_device *kbdev, + enum heap_reclaim_scenario scenario); #endif diff --git a/drivers/gpu/arm/valhall/debug/Kbuild b/drivers/gpu/arm/valhall/debug/Kbuild index a27458a51d4d..74b20f5ea3dc 100644 --- a/drivers/gpu/arm/valhall/debug/Kbuild +++ b/drivers/gpu/arm/valhall/debug/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2021-2022, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -18,11 +18,7 @@ # # -valhall_kbase-y += debug/mali_kbase_debug_ktrace.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += debug/backend/mali_kbase_debug_ktrace_csf.o - valhall_kbase-$(CONFIG_MALI_VALHALL_CORESIGHT) += debug/backend/mali_kbase_debug_coresight_csf.o -else - valhall_kbase-y += debug/backend/mali_kbase_debug_ktrace_jm.o -endif +valhall_kbase-y += \ + debug/mali_kbase_debug_ktrace.o \ + debug/backend/mali_kbase_debug_ktrace_csf.o +valhall_kbase-$(CONFIG_MALI_VALHALL_CORESIGHT) += debug/backend/mali_kbase_debug_coresight_csf.o diff --git a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_codes_jm.h b/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_codes_jm.h deleted file mode 100644 index 14dcc265bc90..000000000000 --- a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_codes_jm.h +++ /dev/null @@ -1,203 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * ***** IMPORTANT: THIS IS NOT A NORMAL HEADER FILE ***** - * ***** DO NOT INCLUDE DIRECTLY ***** - * ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** - */ - -/* - * The purpose of this header file is just to contain a list of trace code - * identifiers - * - * When updating this file, also remember to update - * mali_kbase_debug_linux_ktrace_jm.h - * - * IMPORTANT: THIS FILE MUST NOT BE USED FOR ANY OTHER PURPOSE OTHER THAN THAT - * DESCRIBED IN mali_kbase_debug_ktrace_codes.h - */ - -#if 0 /* Dummy section to avoid breaking formatting */ -int dummy_array[] = { -#endif - -/* - * Job Slot management events - */ -/* info_val==irq rawstat at start */ -KBASE_KTRACE_CODE_MAKE_CODE(JM_IRQ), - /* info_val==jobs processed */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_IRQ_END), - /* In the following: - * - * - ctx is set if a corresponding job found (NULL otherwise, e.g. some - * soft-stop cases) - * - uatom==kernel-side mapped uatom address (for correlation with - * user-side) - */ - /* info_val==exit code; gpu_addr==chain gpuaddr */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_JOB_DONE), - /* gpu_addr==JS_HEAD read - * info_val==event code - */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_RETURN_ATOM_TO_JS), - /* gpu_addr==JS_HEAD read - * info_val==event code - */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_MARK_FOR_RETURN_TO_JS), - /* gpu_addr==JS_HEAD_NEXT written, info_val==lower 32 bits of - * affinity - */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_SUBMIT), - /* gpu_addr is as follows: - * - If JS_STATUS active after soft-stop, val==gpu addr written to - * JS_HEAD on submit - * - otherwise gpu_addr==0 - */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_SOFTSTOP), KBASE_KTRACE_CODE_MAKE_CODE(JM_SOFTSTOP_0), - KBASE_KTRACE_CODE_MAKE_CODE(JM_SOFTSTOP_1), - /* gpu_addr==JS_HEAD read */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_HARDSTOP), - /* gpu_addr==JS_HEAD read */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_HARDSTOP_0), - /* gpu_addr==JS_HEAD read */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_HARDSTOP_1), - /* gpu_addr==JS_TAIL read */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_UPDATE_HEAD), - /* gpu_addr is as follows: - * - If JS_STATUS active before soft-stop, val==JS_HEAD - * - otherwise gpu_addr==0 - */ - /* gpu_addr==JS_HEAD read */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_CHECK_HEAD), KBASE_KTRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS), - KBASE_KTRACE_CODE_MAKE_CODE(JM_FLUSH_WORKQS_DONE), - /* info_val == is_scheduled */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_ZAP_NON_SCHEDULED), - /* info_val == is_scheduled */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_ZAP_SCHEDULED), KBASE_KTRACE_CODE_MAKE_CODE(JM_ZAP_DONE), - /* info_val == nr jobs submitted */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_SLOT_SOFT_OR_HARD_STOP), - /* gpu_addr==JS_HEAD_NEXT last written */ - KBASE_KTRACE_CODE_MAKE_CODE(JM_SLOT_EVICT), - KBASE_KTRACE_CODE_MAKE_CODE(JM_SUBMIT_AFTER_RESET), - KBASE_KTRACE_CODE_MAKE_CODE(JM_BEGIN_RESET_WORKER), - KBASE_KTRACE_CODE_MAKE_CODE(JM_END_RESET_WORKER), - /* - * Job dispatch events - */ - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_DONE), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_DONE_WORKER), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_DONE_WORKER_END), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_DONE_TRY_RUN_NEXT_JOB), - /* gpu_addr==0, info_val==0, uatom==0 */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_ZAP_CONTEXT), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_CANCEL), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JD_CANCEL_WORKER), - /* - * Scheduler Core events - */ - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_ADD_JOB), - /* gpu_addr==last value written/would be written to JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_REMOVE_JOB), - /* gpu_addr==value to write into JS_HEAD - * info_val==priority of atom as a KBASE_JS_ATOM_SCHED_PRIO_<...> value - * (0 highest) - */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_PULL_JOB), - /* gpu_addr==value that would be written to JS_HEAD if run again */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_UNPULL_JOB), - KBASE_KTRACE_CODE_MAKE_CODE(JS_TRY_SCHEDULE_HEAD_CTX), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_JOB_DONE_TRY_RUN_NEXT_JOB), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_JOB_DONE_RETRY_NEEDED), - KBASE_KTRACE_CODE_MAKE_CODE(JS_AFFINITY_SUBMIT_TO_BLOCKED), - /* info_val == lower 32 bits of affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_AFFINITY_CURRENT), - /* info_val == lower 32 bits of affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_CORES_FAILED), - /* info_val == lower 32 bits of affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_INUSE_FAILED), - /* info_val == lower 32 bits of rechecked affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED), - /* info_val == lower 32 bits of rechecked affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED), - /* info_val == lower 32 bits of affinity */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CORE_REF_AFFINITY_WOULD_VIOLATE), - /* info_val == the ctx attribute now on ctx */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_CTX), - /* info_val == the ctx attribute now on runpool */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_ON_RUNPOOL), - /* info_val == the ctx attribute now off ctx */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_CTX), - /* info_val == the ctx attribute now off runpool */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_CTX_ATTR_NOW_OFF_RUNPOOL), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_RETURN_WORKER), - /* gpu_addr==value to write into JS_HEAD */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_RETURN_WORKER_END), - /* info_val==priority level blocked (0 highest) */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_SLOT_PRIO_BLOCKED), - /* info_val==priority level unblocked (0 highest) - * note that the priority level may still be blocked on higher levels - */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_SLOT_PRIO_UNBLOCKED), - /* gpu_addr==value to write into JS_HEAD - * info_val==priority level unblocked - priorities at this and higher - * are unblocked (0 highest) - */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_SLOT_PRIO_AND_HIGHER_UNBLOCKED), - /* gpu_addr==value to write into JS_HEAD - * info_val==priority level blocked (0 highest) - */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_SLOT_PRIO_IS_BLOCKED), - /* - * Scheduler Policy events - */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_INIT_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_TERM_CTX), - /* info_val == whether it was evicted */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_TRY_EVICT_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_FOREACH_CTX_JOBS), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_HEAD_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_ADD_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_RUNPOOL_REMOVE_CTX), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_DEQUEUE_JOB_IRQ), - /* gpu_addr==JS_HEAD to write if the job were run */ - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_ENQUEUE_JOB), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_START), - KBASE_KTRACE_CODE_MAKE_CODE(JS_POLICY_TIMER_END), - -#if 0 /* Dummy section to avoid breaking formatting */ -}; -#endif - - /* ***** THE LACK OF HEADER GUARDS IS INTENTIONAL ***** */ diff --git a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_defs_jm.h b/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_defs_jm.h deleted file mode 100644 index 9978e4939d14..000000000000 --- a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_defs_jm.h +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_DEBUG_KTRACE_DEFS_JM_H_ -#define _KBASE_DEBUG_KTRACE_DEFS_JM_H_ - -#if KBASE_KTRACE_TARGET_RBUF -/** - * DOC: KTrace version history, JM variant - * - * 1.0: - * Original version (implicit, header did not carry version information). - * - * 2.0: - * Introduced version information into the header. - * - * Some changes of parameter names in header. - * - * Trace now uses all 64-bits of info_val. - * - * Non-JM specific parts moved to using info_val instead of refcount/gpu_addr. - * - * 2.1: - * kctx field is no longer a pointer, and is now an ID of the format %d_%u as - * used by kctx directories in mali debugfs entries: (tgid creating the kctx), - * (unique kctx id). - * - * ftrace backend now outputs kctx field (as %d_%u format). - * - * 2.2: - * Add tracing codes for pulling, unpulling, and returns atoms to JS for - * diagnosing soft-stop path and preemption problems - */ -#define KBASE_KTRACE_VERSION_MAJOR 2 -#define KBASE_KTRACE_VERSION_MINOR 2 -#endif /* KBASE_KTRACE_TARGET_RBUF */ - -/* - * Note: mali_kbase_debug_ktrace_jm.h needs these value even if the RBUF target - * is disabled (they get discarded with CSTD_UNUSED(), but they're still - * referenced) - */ - -/* indicates if the trace message has a valid refcount member */ -#define KBASE_KTRACE_FLAG_JM_REFCOUNT (((kbase_ktrace_flag_t)1) << 0) -/* indicates if the trace message has a valid jobslot member */ -#define KBASE_KTRACE_FLAG_JM_JOBSLOT (((kbase_ktrace_flag_t)1) << 1) -/* indicates if the trace message has valid atom related info. */ -#define KBASE_KTRACE_FLAG_JM_ATOM (((kbase_ktrace_flag_t)1) << 2) - -#if KBASE_KTRACE_TARGET_RBUF -/* Collect all the flags together for debug checking */ -#define KBASE_KTRACE_FLAG_BACKEND_ALL \ - (KBASE_KTRACE_FLAG_JM_REFCOUNT | KBASE_KTRACE_FLAG_JM_JOBSLOT | KBASE_KTRACE_FLAG_JM_ATOM) - -/** - * union kbase_ktrace_backend - backend specific part of a trace message - * Contains only a struct but is a union such that it is compatible with - * generic JM and CSF KTrace calls. - * - * @gpu: gpu union member - * @gpu.atom_udata: Copy of the user data sent for the atom in base_jd_submit. - * Only valid if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags - * @gpu.gpu_addr: GPU address, usually of the job-chain represented by an - * atom. - * @gpu.atom_number: id of the atom for which trace message was added. Only - * valid if KBASE_KTRACE_FLAG_JM_ATOM is set in @flags - * @gpu.code: Identifies the event, refer to enum kbase_ktrace_code. - * @gpu.flags: indicates information about the trace message itself. Used - * during dumping of the message. - * @gpu.jobslot: job-slot for which trace message was added, valid only for - * job-slot management events. - * @gpu.refcount: reference count for the context, valid for certain events - * related to scheduler core and policy. - */ -union kbase_ktrace_backend { - struct { - /* Place 64 and 32-bit members together */ - u64 atom_udata[2]; /* Only valid for - * KBASE_KTRACE_FLAG_JM_ATOM - */ - u64 gpu_addr; - unsigned int atom_number; /* Only valid for KBASE_KTRACE_FLAG_JM_ATOM */ - /* Pack smaller members together */ - kbase_ktrace_code_t code; - kbase_ktrace_flag_t flags; - u8 jobslot; - u8 refcount; - } gpu; -}; -#endif /* KBASE_KTRACE_TARGET_RBUF */ - -#endif /* _KBASE_DEBUG_KTRACE_DEFS_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.c b/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.c deleted file mode 100644 index 39306e7d45e3..000000000000 --- a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include "debug/mali_kbase_debug_ktrace_internal.h" -#include "debug/backend/mali_kbase_debug_ktrace_jm.h" - -#if KBASE_KTRACE_TARGET_RBUF - -void kbasep_ktrace_backend_format_header(char *buffer, int sz, s32 *written) -{ - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), - "katom,gpu_addr,jobslot,refcount"), - 0); -} - -void kbasep_ktrace_backend_format_msg(struct kbase_ktrace_msg *trace_msg, char *buffer, int sz, - s32 *written) -{ - /* katom */ - if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_ATOM) - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), - "atom %u (ud: 0x%llx 0x%llx)", - trace_msg->backend.gpu.atom_number, - trace_msg->backend.gpu.atom_udata[0], - trace_msg->backend.gpu.atom_udata[1]), - 0); - - /* gpu_addr */ - if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_BACKEND) - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), - ",%.8llx,", trace_msg->backend.gpu.gpu_addr), - 0); - else - *written += - MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), ",,"), 0); - - /* jobslot */ - if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_JOBSLOT) - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), "%d", - trace_msg->backend.gpu.jobslot), - 0); - - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), ","), 0); - - /* refcount */ - if (trace_msg->backend.gpu.flags & KBASE_KTRACE_FLAG_JM_REFCOUNT) - *written += MAX(scnprintf(buffer + *written, (size_t)MAX(sz - *written, 0), "%d", - trace_msg->backend.gpu.refcount), - 0); -} - -void kbasep_ktrace_add_jm(struct kbase_device *kbdev, enum kbase_ktrace_code code, - struct kbase_context *kctx, const struct kbase_jd_atom *katom, - u64 gpu_addr, kbase_ktrace_flag_t flags, int refcount, - unsigned int jobslot, u64 info_val) -{ - unsigned long irqflags; - struct kbase_ktrace_msg *trace_msg; - - if (unlikely(!kbasep_ktrace_initialized(&kbdev->ktrace))) - return; - - spin_lock_irqsave(&kbdev->ktrace.lock, irqflags); - - /* Reserve and update indices */ - trace_msg = kbasep_ktrace_reserve(&kbdev->ktrace); - - /* Fill the common part of the message (including backend.gpu.flags) */ - kbasep_ktrace_msg_init(&kbdev->ktrace, trace_msg, code, kctx, flags, info_val); - - /* Indicate to the common code that backend-specific parts will be - * valid - */ - trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_BACKEND; - - /* Fill the JM-specific parts of the message */ - if (katom) { - trace_msg->backend.gpu.flags |= KBASE_KTRACE_FLAG_JM_ATOM; - - trace_msg->backend.gpu.atom_number = kbase_jd_atom_id(katom->kctx, katom); - trace_msg->backend.gpu.atom_udata[0] = katom->udata.blob[0]; - trace_msg->backend.gpu.atom_udata[1] = katom->udata.blob[1]; - } - - trace_msg->backend.gpu.gpu_addr = gpu_addr; - trace_msg->backend.gpu.jobslot = jobslot; - /* Clamp refcount */ - trace_msg->backend.gpu.refcount = MIN((unsigned int)refcount, 0xFF); - - WARN_ON((trace_msg->backend.gpu.flags & ~KBASE_KTRACE_FLAG_ALL)); - - /* Done */ - spin_unlock_irqrestore(&kbdev->ktrace.lock, irqflags); -} - -#endif /* KBASE_KTRACE_TARGET_RBUF */ diff --git a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.h b/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.h deleted file mode 100644 index 59ad23d7677c..000000000000 --- a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_ktrace_jm.h +++ /dev/null @@ -1,297 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_DEBUG_KTRACE_JM_H_ -#define _KBASE_DEBUG_KTRACE_JM_H_ - -/* - * KTrace target for internal ringbuffer - */ -#if KBASE_KTRACE_TARGET_RBUF -/** - * kbasep_ktrace_add_jm - internal function to add trace about Job Management - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @flags: flags about the message - * @refcount: reference count information to add to the trace - * @jobslot: jobslot information to add to the trace - * @info_val: generic information about @code to add to the trace - * - * PRIVATE: do not use directly. Use KBASE_KTRACE_ADD_JM() instead. - */ -void kbasep_ktrace_add_jm(struct kbase_device *kbdev, enum kbase_ktrace_code code, - struct kbase_context *kctx, const struct kbase_jd_atom *katom, - u64 gpu_addr, kbase_ktrace_flag_t flags, int refcount, - unsigned int jobslot, u64 info_val); - -#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, flags, refcount, jobslot, \ - info_val) \ - kbasep_ktrace_add_jm(kbdev, KBASE_KTRACE_CODE(code), kctx, katom, gpu_addr, flags, \ - refcount, jobslot, info_val) - -#else /* KBASE_KTRACE_TARGET_RBUF */ - -#define KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, gpu_addr, flags, refcount, jobslot, \ - info_val) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(flags); \ - CSTD_UNUSED(refcount); \ - CSTD_UNUSED(jobslot); \ - CSTD_UNUSED(info_val); \ - CSTD_NOP(0); \ - } while (0) -#endif /* KBASE_KTRACE_TARGET_RBUF */ - -/* - * KTrace target for Linux's ftrace - * - * Note: the header file(s) that define the trace_mali_<...> tracepoints are - * included by the parent header file - */ -#if KBASE_KTRACE_TARGET_FTRACE -#define KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, jobslot) \ - trace_mali_##code(kctx, jobslot, 0) - -#define KBASE_KTRACE_FTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, gpu_addr, jobslot, \ - info_val) \ - trace_mali_##code(kctx, jobslot, info_val) - -#define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, gpu_addr, refcount) \ - trace_mali_##code(kctx, refcount, 0) - -#define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, gpu_addr, refcount, \ - info_val) \ - trace_mali_##code(kctx, refcount, info_val) - -#define KBASE_KTRACE_FTRACE_ADD_JM(kbdev, code, kctx, katom, gpu_addr, info_val) \ - trace_mali_##code(kctx, gpu_addr, info_val) -#else /* KBASE_KTRACE_TARGET_FTRACE */ -#define KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, jobslot) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(jobslot); \ - CSTD_NOP(0); \ - } while (0) - -#define KBASE_KTRACE_FTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, gpu_addr, jobslot, \ - info_val) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(jobslot); \ - CSTD_UNUSED(info_val); \ - CSTD_NOP(0); \ - } while (0) - -#define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, gpu_addr, refcount) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(refcount); \ - CSTD_NOP(0); \ - } while (0) - -#define KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, gpu_addr, refcount, \ - info_val) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(info_val); \ - CSTD_NOP(0); \ - } while (0) - -#define KBASE_KTRACE_FTRACE_ADD_JM(kbdev, code, kctx, katom, gpu_addr, info_val) \ - do { \ - CSTD_UNUSED(kbdev); \ - CSTD_NOP(code); \ - CSTD_UNUSED(kctx); \ - CSTD_UNUSED(katom); \ - CSTD_UNUSED(gpu_addr); \ - CSTD_UNUSED(info_val); \ - CSTD_NOP(0); \ - } while (0) -#endif /* KBASE_KTRACE_TARGET_FTRACE */ - -/* - * Master set of macros to route KTrace to any of the targets - */ - -/** - * KBASE_KTRACE_ADD_JM_SLOT - Add trace values about a job-slot - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @jobslot: jobslot information to add to the trace - * - * Note: Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_VALHALL_DEBUG not defined). Therefore, when - * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied - * to this macro must: - * a) be static or static inline, and - * b) just return 0 and have no other statements present in the body. - */ -#define KBASE_KTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, gpu_addr, jobslot) \ - do { \ - /* capture values that could come from non-pure function calls */ \ - u64 __gpu_addr = gpu_addr; \ - unsigned int __jobslot = jobslot; \ - KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \ - KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, __jobslot, 0); \ - KBASE_KTRACE_FTRACE_ADD_JM_SLOT(kbdev, code, kctx, katom, __gpu_addr, __jobslot); \ - } while (0) - -/** - * KBASE_KTRACE_ADD_JM_SLOT_INFO - Add trace values about a job-slot, with info - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @jobslot: jobslot information to add to the trace - * @info_val: generic information about @code to add to the trace - * - * Note: Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_VALHALL_DEBUG not defined). Therefore, when - * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied - * to this macro must: - * a) be static or static inline, and - * b) just return 0 and have no other statements present in the body. - */ -#define KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, gpu_addr, jobslot, info_val) \ - do { \ - /* capture values that could come from non-pure function calls */ \ - u64 __gpu_addr = gpu_addr; \ - unsigned int __jobslot = jobslot; \ - u64 __info_val = info_val; \ - KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \ - KBASE_KTRACE_FLAG_JM_JOBSLOT, 0, __jobslot, __info_val); \ - KBASE_KTRACE_FTRACE_ADD_JM_SLOT_INFO(kbdev, code, kctx, katom, __gpu_addr, \ - __jobslot, __info_val); \ - } while (0) - -/** - * KBASE_KTRACE_ADD_JM_REFCOUNT - Add trace values about a kctx refcount - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @refcount: reference count information to add to the trace - * - * Note: Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_VALHALL_DEBUG not defined). Therefore, when - * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied - * to this macro must: - * a) be static or static inline, and - * b) just return 0 and have no other statements present in the body. - */ -#define KBASE_KTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, gpu_addr, refcount) \ - do { \ - /* capture values that could come from non-pure function calls */ \ - u64 __gpu_addr = gpu_addr; \ - int __refcount = refcount; \ - KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \ - KBASE_KTRACE_FLAG_JM_REFCOUNT, __refcount, 0, 0u); \ - KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, \ - (unsigned int)__refcount); \ - } while (0) - -/** - * KBASE_KTRACE_ADD_JM_REFCOUNT_INFO - Add trace values about a kctx refcount, - * and info - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @refcount: reference count information to add to the trace - * @info_val: generic information about @code to add to the trace - * - * Note: Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_VALHALL_DEBUG not defined). Therefore, when - * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied - * to this macro must: - * a) be static or static inline, and - * b) just return 0 and have no other statements present in the body. - */ -#define KBASE_KTRACE_ADD_JM_REFCOUNT_INFO(kbdev, code, kctx, katom, gpu_addr, refcount, info_val) \ - do { \ - /* capture values that could come from non-pure function calls */ \ - u64 __gpu_addr = gpu_addr; \ - int __refcount = refcount; \ - u64 __info_val = info_val; \ - KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, \ - KBASE_KTRACE_FLAG_JM_REFCOUNT, __refcount, 0, \ - __info_val); \ - KBASE_KTRACE_FTRACE_ADD_JM_REFCOUNT(kbdev, code, kctx, katom, __gpu_addr, \ - (unsigned int)__refcount, __info_val); \ - } while (0) - -/** - * KBASE_KTRACE_ADD_JM - Add trace values (no slot or refcount) - * @kbdev: kbase device - * @code: trace code - * @kctx: kbase context, or NULL if no context - * @katom: kbase atom, or NULL if no atom - * @gpu_addr: GPU address, usually related to @katom - * @info_val: generic information about @code to add to the trace - * - * Note: Any functions called through this macro will still be evaluated in - * Release builds (CONFIG_MALI_VALHALL_DEBUG not defined). Therefore, when - * KBASE_KTRACE_ENABLE == 0 any functions called to get the parameters supplied - * to this macro must: - * a) be static or static inline, and - * b) just return 0 and have no other statements present in the body. - */ -#define KBASE_KTRACE_ADD_JM(kbdev, code, kctx, katom, gpu_addr, info_val) \ - do { \ - /* capture values that could come from non-pure function calls */ \ - u64 __gpu_addr = gpu_addr; \ - u64 __info_val = info_val; \ - KBASE_KTRACE_RBUF_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, 0u, 0, 0, \ - __info_val); \ - KBASE_KTRACE_FTRACE_ADD_JM(kbdev, code, kctx, katom, __gpu_addr, __info_val); \ - } while (0) - -#endif /* _KBASE_DEBUG_KTRACE_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_linux_ktrace_jm.h b/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_linux_ktrace_jm.h deleted file mode 100644 index 3e5b0ec89758..000000000000 --- a/drivers/gpu/arm/valhall/debug/backend/mali_kbase_debug_linux_ktrace_jm.h +++ /dev/null @@ -1,151 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * NOTE: This must **only** be included through mali_linux_trace.h, - * otherwise it will fail to setup tracepoints correctly - */ - -#if !defined(_KBASE_DEBUG_LINUX_KTRACE_JM_H_) || defined(TRACE_HEADER_MULTI_READ) -#define _KBASE_DEBUG_LINUX_KTRACE_JM_H_ - -DECLARE_EVENT_CLASS(mali_jm_slot_template, - TP_PROTO(struct kbase_context *kctx, unsigned int jobslot, u64 info_val), - TP_ARGS(kctx, jobslot, info_val), - TP_STRUCT__entry(__field(pid_t, kctx_tgid) __field(u32, kctx_id) - __field(unsigned int, jobslot) __field(u64, info_val)), - TP_fast_assign(__entry->kctx_id = (kctx) ? kctx->id : 0u; - __entry->kctx_tgid = (kctx) ? kctx->tgid : 0; - __entry->jobslot = jobslot; __entry->info_val = info_val;), - TP_printk("kctx=%d_%u jobslot=%u info=0x%llx", __entry->kctx_tgid, - __entry->kctx_id, __entry->jobslot, __entry->info_val)); - -#define DEFINE_MALI_JM_SLOT_EVENT(name) \ - DEFINE_EVENT(mali_jm_slot_template, mali_##name, \ - TP_PROTO(struct kbase_context *kctx, unsigned int jobslot, u64 info_val), \ - TP_ARGS(kctx, jobslot, info_val)) -DEFINE_MALI_JM_SLOT_EVENT(JM_RETURN_ATOM_TO_JS); -DEFINE_MALI_JM_SLOT_EVENT(JM_MARK_FOR_RETURN_TO_JS); -DEFINE_MALI_JM_SLOT_EVENT(JM_SUBMIT); -DEFINE_MALI_JM_SLOT_EVENT(JM_JOB_DONE); -DEFINE_MALI_JM_SLOT_EVENT(JM_UPDATE_HEAD); -DEFINE_MALI_JM_SLOT_EVENT(JM_CHECK_HEAD); -DEFINE_MALI_JM_SLOT_EVENT(JM_SOFTSTOP); -DEFINE_MALI_JM_SLOT_EVENT(JM_SOFTSTOP_0); -DEFINE_MALI_JM_SLOT_EVENT(JM_SOFTSTOP_1); -DEFINE_MALI_JM_SLOT_EVENT(JM_HARDSTOP); -DEFINE_MALI_JM_SLOT_EVENT(JM_HARDSTOP_0); -DEFINE_MALI_JM_SLOT_EVENT(JM_HARDSTOP_1); -DEFINE_MALI_JM_SLOT_EVENT(JM_SLOT_SOFT_OR_HARD_STOP); -DEFINE_MALI_JM_SLOT_EVENT(JM_SLOT_EVICT); -DEFINE_MALI_JM_SLOT_EVENT(JM_BEGIN_RESET_WORKER); -DEFINE_MALI_JM_SLOT_EVENT(JM_END_RESET_WORKER); -DEFINE_MALI_JM_SLOT_EVENT(JS_CORE_REF_REGISTER_ON_RECHECK_FAILED); -DEFINE_MALI_JM_SLOT_EVENT(JS_AFFINITY_SUBMIT_TO_BLOCKED); -DEFINE_MALI_JM_SLOT_EVENT(JS_AFFINITY_CURRENT); -DEFINE_MALI_JM_SLOT_EVENT(JD_DONE_TRY_RUN_NEXT_JOB); -DEFINE_MALI_JM_SLOT_EVENT(JS_PULL_JOB); -DEFINE_MALI_JM_SLOT_EVENT(JS_CORE_REF_REQUEST_CORES_FAILED); -DEFINE_MALI_JM_SLOT_EVENT(JS_CORE_REF_REGISTER_INUSE_FAILED); -DEFINE_MALI_JM_SLOT_EVENT(JS_CORE_REF_REQUEST_ON_RECHECK_FAILED); -DEFINE_MALI_JM_SLOT_EVENT(JS_CORE_REF_AFFINITY_WOULD_VIOLATE); -DEFINE_MALI_JM_SLOT_EVENT(JS_JOB_DONE_TRY_RUN_NEXT_JOB); -DEFINE_MALI_JM_SLOT_EVENT(JS_JOB_DONE_RETRY_NEEDED); -DEFINE_MALI_JM_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB); -DEFINE_MALI_JM_SLOT_EVENT(JS_POLICY_DEQUEUE_JOB_IRQ); -DEFINE_MALI_JM_SLOT_EVENT(JS_SLOT_PRIO_BLOCKED); -DEFINE_MALI_JM_SLOT_EVENT(JS_SLOT_PRIO_UNBLOCKED); -DEFINE_MALI_JM_SLOT_EVENT(JS_SLOT_PRIO_AND_HIGHER_UNBLOCKED); -DEFINE_MALI_JM_SLOT_EVENT(JS_SLOT_PRIO_IS_BLOCKED); -#undef DEFINE_MALI_JM_SLOT_EVENT - -DECLARE_EVENT_CLASS(mali_jm_refcount_template, - TP_PROTO(struct kbase_context *kctx, unsigned int refcount, u64 info_val), - TP_ARGS(kctx, refcount, info_val), - TP_STRUCT__entry(__field(pid_t, kctx_tgid) __field(u32, kctx_id) - __field(unsigned int, refcount) - __field(u64, info_val)), - TP_fast_assign(__entry->kctx_id = (kctx) ? kctx->id : 0u; - __entry->kctx_tgid = (kctx) ? kctx->tgid : 0; - __entry->refcount = refcount; __entry->info_val = info_val;), - TP_printk("kctx=%d_%u refcount=%u info=0x%llx", __entry->kctx_tgid, - __entry->kctx_id, __entry->refcount, __entry->info_val)); - -#define DEFINE_MALI_JM_REFCOUNT_EVENT(name) \ - DEFINE_EVENT(mali_jm_refcount_template, mali_##name, \ - TP_PROTO(struct kbase_context *kctx, unsigned int refcount, u64 info_val), \ - TP_ARGS(kctx, refcount, info_val)) -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_ADD_JOB); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_REMOVE_JOB); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_TRY_SCHEDULE_HEAD_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_INIT_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_TERM_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_ENQUEUE_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_DEQUEUE_HEAD_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_TRY_EVICT_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_ADD_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_RUNPOOL_REMOVE_CTX); -DEFINE_MALI_JM_REFCOUNT_EVENT(JS_POLICY_FOREACH_CTX_JOBS); -#undef DEFINE_MALI_JM_REFCOUNT_EVENT - -DECLARE_EVENT_CLASS(mali_jm_add_template, - TP_PROTO(struct kbase_context *kctx, u64 gpu_addr, u64 info_val), - TP_ARGS(kctx, gpu_addr, info_val), - TP_STRUCT__entry(__field(pid_t, kctx_tgid) __field(u32, kctx_id) - __field(u64, gpu_addr) __field(u64, info_val)), - TP_fast_assign(__entry->kctx_id = (kctx) ? kctx->id : 0u; - __entry->kctx_tgid = (kctx) ? kctx->tgid : 0; - __entry->gpu_addr = gpu_addr; __entry->info_val = info_val;), - TP_printk("kctx=%d_%u gpu_addr=0x%llx info=0x%llx", __entry->kctx_tgid, - __entry->kctx_id, __entry->gpu_addr, __entry->info_val)); - -#define DEFINE_MALI_JM_ADD_EVENT(name) \ - DEFINE_EVENT(mali_jm_add_template, mali_##name, \ - TP_PROTO(struct kbase_context *kctx, u64 gpu_addr, u64 info_val), \ - TP_ARGS(kctx, gpu_addr, info_val)) -DEFINE_MALI_JM_ADD_EVENT(JD_DONE_WORKER); -DEFINE_MALI_JM_ADD_EVENT(JD_DONE_WORKER_END); -DEFINE_MALI_JM_ADD_EVENT(JD_CANCEL_WORKER); -DEFINE_MALI_JM_ADD_EVENT(JD_DONE); -DEFINE_MALI_JM_ADD_EVENT(JD_CANCEL); -DEFINE_MALI_JM_ADD_EVENT(JD_ZAP_CONTEXT); -DEFINE_MALI_JM_ADD_EVENT(JM_IRQ); -DEFINE_MALI_JM_ADD_EVENT(JM_IRQ_END); -DEFINE_MALI_JM_ADD_EVENT(JM_FLUSH_WORKQS); -DEFINE_MALI_JM_ADD_EVENT(JM_FLUSH_WORKQS_DONE); -DEFINE_MALI_JM_ADD_EVENT(JM_ZAP_NON_SCHEDULED); -DEFINE_MALI_JM_ADD_EVENT(JM_ZAP_SCHEDULED); -DEFINE_MALI_JM_ADD_EVENT(JM_ZAP_DONE); -DEFINE_MALI_JM_ADD_EVENT(JM_SUBMIT_AFTER_RESET); -DEFINE_MALI_JM_ADD_EVENT(JM_JOB_COMPLETE); -DEFINE_MALI_JM_ADD_EVENT(JS_UNPULL_JOB); -DEFINE_MALI_JM_ADD_EVENT(JS_CTX_ATTR_NOW_ON_RUNPOOL); -DEFINE_MALI_JM_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_RUNPOOL); -DEFINE_MALI_JM_ADD_EVENT(JS_CTX_ATTR_NOW_ON_CTX); -DEFINE_MALI_JM_ADD_EVENT(JS_CTX_ATTR_NOW_OFF_CTX); -DEFINE_MALI_JM_ADD_EVENT(JS_RETURN_WORKER); -DEFINE_MALI_JM_ADD_EVENT(JS_RETURN_WORKER_END); -DEFINE_MALI_JM_ADD_EVENT(JS_POLICY_TIMER_END); -DEFINE_MALI_JM_ADD_EVENT(JS_POLICY_TIMER_START); -DEFINE_MALI_JM_ADD_EVENT(JS_POLICY_ENQUEUE_JOB); -#undef DEFINE_MALI_JM_ADD_EVENT - -#endif /* !defined(_KBASE_DEBUG_LINUX_KTRACE_JM_H_) || defined(TRACE_HEADER_MULTI_READ)*/ diff --git a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace.h b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace.h index 9d12a000c5bb..53c1debc840c 100644 --- a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace.h +++ b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -40,11 +40,7 @@ #include "mali_linux_trace.h" #endif -#if MALI_USE_CSF #include "debug/backend/mali_kbase_debug_ktrace_csf.h" -#else -#include "debug/backend/mali_kbase_debug_ktrace_jm.h" -#endif /** * kbase_ktrace_init - initialize kbase ktrace. diff --git a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_codes.h b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_codes.h index f5810d477c83..94c5ae0dd290 100644 --- a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_codes.h +++ b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_codes.h @@ -165,11 +165,7 @@ KBASE_KTRACE_CODE_MAKE_CODE(CORE_CTX_DESTROY), KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_STOPPED), KBASE_KTRACE_CODE_MAKE_CODE(ARB_GPU_REQUESTED), -#if MALI_USE_CSF #include "debug/backend/mali_kbase_debug_ktrace_codes_csf.h" -#else -#include "debug/backend/mali_kbase_debug_ktrace_codes_jm.h" -#endif /* * Unused code just to make it easier to not have a comma at the end. * All other codes MUST come before this diff --git a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_defs.h b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_defs.h index be91473b81ec..9907c74efcc0 100644 --- a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_defs.h +++ b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_ktrace_defs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -91,11 +91,7 @@ union kbase_ktrace_backend; #endif /* KBASE_KTRACE_TARGET_RBUF */ -#if MALI_USE_CSF #include "debug/backend/mali_kbase_debug_ktrace_defs_csf.h" -#else -#include "debug/backend/mali_kbase_debug_ktrace_defs_jm.h" -#endif #if KBASE_KTRACE_TARGET_RBUF /* Indicates if the trace message has backend related info. diff --git a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_linux_ktrace.h b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_linux_ktrace.h index 76ac6a6c429b..224a758d2c2c 100644 --- a/drivers/gpu/arm/valhall/debug/mali_kbase_debug_linux_ktrace.h +++ b/drivers/gpu/arm/valhall/debug/mali_kbase_debug_linux_ktrace.h @@ -111,11 +111,7 @@ DEFINE_MALI_ADD_EVENT(ARB_GPU_STOP_REQUESTED); DEFINE_MALI_ADD_EVENT(ARB_GPU_STOPPED); DEFINE_MALI_ADD_EVENT(ARB_GPU_REQUESTED); -#if MALI_USE_CSF #include "backend/mali_kbase_debug_linux_ktrace_csf.h" -#else -#include "backend/mali_kbase_debug_linux_ktrace_jm.h" -#endif #undef DEFINE_MALI_ADD_EVENT diff --git a/drivers/gpu/arm/valhall/device/Kbuild b/drivers/gpu/arm/valhall/device/Kbuild index 7b4057023574..5a50d974c080 100644 --- a/drivers/gpu/arm/valhall/device/Kbuild +++ b/drivers/gpu/arm/valhall/device/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2021, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -20,14 +20,6 @@ valhall_kbase-y += \ device/mali_kbase_device.o \ - device/mali_kbase_device_hw.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += \ - device/backend/mali_kbase_device_csf.o \ - device/backend/mali_kbase_device_hw_csf.o -else - valhall_kbase-y += \ - device/backend/mali_kbase_device_jm.o \ - device/backend/mali_kbase_device_hw_jm.o -endif + device/mali_kbase_device_hw.o \ + device/backend/mali_kbase_device_csf.o \ + device/backend/mali_kbase_device_hw_csf.o diff --git a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_csf.c b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_csf.c index 4362dd1de561..539590737d90 100644 --- a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_csf.c +++ b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_csf.c @@ -61,6 +61,7 @@ static void kbase_device_firmware_hwcnt_term(struct kbase_device *kbdev) kbase_kinstr_prfcnt_term(kbdev->kinstr_prfcnt_ctx); kbase_hwcnt_virtualizer_term(kbdev->hwcnt_gpu_virt); kbase_hwcnt_backend_csf_metadata_term(&kbdev->hwcnt_gpu_iface); + kbase_hwcnt_backend_csf_ring_buf_term(&kbdev->hwcnt_gpu_iface); kbase_csf_firmware_unload_term(kbdev); } } diff --git a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_csf.c b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_csf.c index 792d2efa7706..e9019425f688 100644 --- a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_csf.c +++ b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_csf.c @@ -82,12 +82,10 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) struct kbase_csf_scheduler *scheduler = &kbdev->csf.scheduler; bool is_legacy_gpu_irq_mask = true; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { power_changed_mask = MCU_STATUS_GPU_IRQ; is_legacy_gpu_irq_mask = false; } -#endif KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, val); @@ -136,15 +134,10 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) val &= ~GPU_PROTECTED_FAULT; } -#if MALI_USE_CSF if (!kbdev->pm.backend.has_host_pwr_iface) { if (val & RESET_COMPLETED) kbase_pm_reset_done(kbdev); } -#else - if (val & RESET_COMPLETED) - kbase_pm_reset_done(kbdev); -#endif /* Defer clearing CLEAN_CACHES_COMPLETED to kbase_clean_caches_done. * We need to acquire hwaccess_lock to avoid a race condition with @@ -153,8 +146,7 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, val & ~CLEAN_CACHES_COMPLETED); kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_CLEAR), val & ~CLEAN_CACHES_COMPLETED); -#ifdef KBASE_PM_RUNTIME - if (val & DOORBELL_MIRROR) { + if (IS_ENABLED(CONFIG_PM) && (val & DOORBELL_MIRROR)) { unsigned long flags; dev_dbg(kbdev->dev, "Doorbell mirror interrupt received"); @@ -213,7 +205,6 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } -#endif /* kbase_pm_check_transitions (called by kbase_pm_power_changed) must * be called after the IRQ has been cleared. This is because it might diff --git a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_jm.c b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_jm.c deleted file mode 100644 index 368ffe257771..000000000000 --- a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_hw_jm.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * kbase_report_gpu_fault - Report a GPU fault. - * @kbdev: Kbase device pointer - * @multiple: Zero if only GPU_FAULT was raised, non-zero if MULTIPLE_GPU_FAULTS - * was also set - * - * This function is called from the interrupt handler when a GPU fault occurs. - * It reports the details of the fault using dev_warn(). - */ -static void kbase_report_gpu_fault(struct kbase_device *kbdev, int multiple) -{ - u32 status = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_FAULTSTATUS)); - uintptr_t phys_addr = kbase_reg_read64(kbdev, GPU_CONTROL_ENUM(GPU_FAULTADDRESS)); - - dev_warn(kbdev->dev, "GPU Fault 0x%08x (%s) at PA 0x%pK", status, - kbase_gpu_exception_name(status & 0xFF), (void *)phys_addr); - if (multiple) - dev_warn(kbdev->dev, - "There were multiple GPU faults - some have not been reported\n"); - -} - -void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val) -{ - KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ, NULL, val); - if (val & GPU_FAULT) - kbase_report_gpu_fault(kbdev, val & MULTIPLE_GPU_FAULTS); - - if (val & RESET_COMPLETED) - kbase_pm_reset_done(kbdev); - - /* Defer clearing CLEAN_CACHES_COMPLETED to kbase_clean_caches_done. - * We need to acquire hwaccess_lock to avoid a race condition with - * kbase_gpu_cache_flush_and_busy_wait - */ - KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_CLEAR, NULL, val & ~CLEAN_CACHES_COMPLETED); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_CLEAR), val & ~CLEAN_CACHES_COMPLETED); - - /* kbase_instr_hwcnt_sample_done frees the HWCNT pipeline to request another - * sample. Therefore this must be called after clearing the IRQ to avoid a - * race between clearing and the next sample raising the IRQ again. - */ - if (val & PRFCNT_SAMPLE_COMPLETED) - kbase_instr_hwcnt_sample_done(kbdev); - - /* kbase_pm_check_transitions (called by kbase_pm_power_changed) must - * be called after the IRQ has been cleared. This is because it might - * trigger further power transitions and we don't want to miss the - * interrupt raised to notify us that these further transitions have - * finished. The same applies to kbase_clean_caches_done() - if another - * clean was queued, it might trigger another clean, which might - * generate another interrupt which shouldn't be missed. - */ - - if (val & CLEAN_CACHES_COMPLETED) - kbase_clean_caches_done(kbdev); - - if (val & POWER_CHANGED_ALL) { - kbase_pm_power_changed(kbdev); - } else if (val & CLEAN_CACHES_COMPLETED) { - /* If cache line evict messages can be lost when shader cores - * power down then we need to flush the L2 cache before powering - * down cores. When the flush completes, the shaders' state - * machine needs to be re-invoked to proceed with powering down - * cores. - */ - if (kbdev->pm.backend.l2_always_on || - kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_921)) - kbase_pm_power_changed(kbdev); - } - - KBASE_KTRACE_ADD(kbdev, CORE_GPU_IRQ_DONE, NULL, val); -} -KBASE_EXPORT_TEST_API(kbase_gpu_interrupt); diff --git a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_jm.c b/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_jm.c deleted file mode 100644 index 0c96b2ba3eba..000000000000 --- a/drivers/gpu/arm/valhall/device/backend/mali_kbase_device_jm.c +++ /dev/null @@ -1,344 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) -#include -#endif - -/** - * kbase_backend_late_init - Perform any backend-specific initialization. - * @kbdev: Device pointer - * - * Return: 0 on success, or an error code on failure. - */ -static int kbase_backend_late_init(struct kbase_device *kbdev) -{ - int err; - - err = kbase_hwaccess_pm_init(kbdev); - if (err) - return err; - - err = kbase_reset_gpu_init(kbdev); - if (err) - goto fail_reset_gpu_init; - - err = kbase_hwaccess_pm_powerup(kbdev, PM_HW_ISSUES_DETECT); - if (err) - goto fail_pm_powerup; - - err = kbase_backend_timer_init(kbdev); - if (err) - goto fail_timer; - -#ifdef CONFIG_MALI_VALHALL_DEBUG -#if IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) - if (kbase_validate_interrupts(kbdev) != 0) { - dev_err(kbdev->dev, "Interrupt validation failed.\n"); - err = -EINVAL; - goto fail_interrupt_test; - } -#endif /* IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) */ -#endif /* CONFIG_MALI_VALHALL_DEBUG */ - - err = kbase_job_slot_init(kbdev); - if (err) - goto fail_job_slot; - - /* Do the initialisation of devfreq. - * Devfreq needs backend_timer_init() for completion of its - * initialisation and it also needs to catch the first callback - * occurrence of the runtime_suspend event for maintaining state - * coherence with the backend power management, hence needs to be - * placed before the kbase_pm_context_idle(). - */ - err = kbase_backend_devfreq_init(kbdev); - if (err) - goto fail_devfreq_init; - - /* Update gpuprops with L2_FEATURES if applicable */ - err = kbase_gpuprops_update_l2_features(kbdev); - if (err) - goto fail_update_l2_features; - - init_waitqueue_head(&kbdev->hwaccess.backend.reset_wait); - - /* Idle the GPU and/or cores, if the policy wants it to */ - kbase_pm_context_idle(kbdev); - - mutex_init(&kbdev->fw_load_lock); - - return 0; - -fail_update_l2_features: - kbase_backend_devfreq_term(kbdev); -fail_devfreq_init: - kbase_job_slot_term(kbdev); -fail_job_slot: - -#ifdef CONFIG_MALI_VALHALL_DEBUG -#if IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) -fail_interrupt_test: -#endif /* IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) */ -#endif /* CONFIG_MALI_VALHALL_DEBUG */ - - kbase_backend_timer_term(kbdev); -fail_timer: - kbase_pm_context_idle(kbdev); - kbase_hwaccess_pm_halt(kbdev); -fail_pm_powerup: - kbase_reset_gpu_term(kbdev); -fail_reset_gpu_init: - kbase_hwaccess_pm_term(kbdev); - - return err; -} - -/** - * kbase_backend_late_term - Perform any backend-specific termination. - * @kbdev: Device pointer - */ -static void kbase_backend_late_term(struct kbase_device *kbdev) -{ - kbase_backend_devfreq_term(kbdev); - kbase_job_slot_halt(kbdev); - kbase_job_slot_term(kbdev); - kbase_backend_timer_term(kbdev); - kbase_hwaccess_pm_halt(kbdev); - kbase_reset_gpu_term(kbdev); - kbase_hwaccess_pm_term(kbdev); -} - -/** - * kbase_device_hwcnt_watchdog_if_init - Create hardware counter watchdog - * interface. - * @kbdev: Device pointer - * Return: 0 on success, or an error code on failure. - */ -static int kbase_device_hwcnt_watchdog_if_init(struct kbase_device *kbdev) -{ - return kbase_hwcnt_watchdog_if_timer_create(&kbdev->hwcnt_watchdog_timer); -} - -/** - * kbase_device_hwcnt_watchdog_if_term - Terminate hardware counter watchdog - * interface. - * @kbdev: Device pointer - */ -static void kbase_device_hwcnt_watchdog_if_term(struct kbase_device *kbdev) -{ - kbase_hwcnt_watchdog_if_timer_destroy(&kbdev->hwcnt_watchdog_timer); -} - -/** - * kbase_device_hwcnt_backend_jm_init - Create hardware counter backend. - * @kbdev: Device pointer - * Return: 0 on success, or an error code on failure. - */ -static int kbase_device_hwcnt_backend_jm_init(struct kbase_device *kbdev) -{ - return kbase_hwcnt_backend_jm_create(kbdev, &kbdev->hwcnt_gpu_jm_backend); -} - -/** - * kbase_device_hwcnt_backend_jm_term - Terminate hardware counter backend. - * @kbdev: Device pointer - */ -static void kbase_device_hwcnt_backend_jm_term(struct kbase_device *kbdev) -{ - kbase_hwcnt_backend_jm_destroy(&kbdev->hwcnt_gpu_jm_backend); -} - -/** - * kbase_device_hwcnt_backend_jm_watchdog_init - Create hardware counter watchdog backend. - * @kbdev: Device pointer - * Return: 0 on success, or an error code on failure. - */ -static int kbase_device_hwcnt_backend_jm_watchdog_init(struct kbase_device *kbdev) -{ - const u32 timer_interval = - (kbdev->gpu_props.impl_tech == THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_FPGA) || - (kbdev->gpu_props.impl_tech == - THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_SOFTWARE) ? - HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_FPGA_MS : - HWCNT_BACKEND_WATCHDOG_TIMER_INTERVAL_MS; - return kbase_hwcnt_backend_jm_watchdog_create(&kbdev->hwcnt_gpu_jm_backend, - &kbdev->hwcnt_watchdog_timer, - &kbdev->hwcnt_gpu_iface, timer_interval); -} - -/** - * kbase_device_hwcnt_backend_jm_watchdog_term - Terminate hardware counter watchdog backend. - * @kbdev: Device pointer - */ -static void kbase_device_hwcnt_backend_jm_watchdog_term(struct kbase_device *kbdev) -{ - kbase_hwcnt_backend_jm_watchdog_destroy(&kbdev->hwcnt_gpu_iface); -} - -static const struct kbase_device_init dev_init[] = { -#if !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) - { kbase_gpu_device_create, kbase_gpu_device_destroy, "Dummy model initialization failed" }, -#else /* !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) */ - { kbase_get_irqs, NULL, "IRQ search failed" }, - { registers_map, registers_unmap, "Register map failed" }, -#endif /* !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) */ -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - { kbase_gpu_metrics_init, kbase_gpu_metrics_term, "GPU metrics initialization failed" }, -#endif /* IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) */ - { power_control_init, power_control_term, "Power control initialization failed" }, - { kbase_io_init, kbase_io_term, "Kbase IO initialization failed" }, - { kbase_device_io_history_init, kbase_device_io_history_term, - "Register access history initialization failed" }, - { kbase_device_early_init, kbase_device_early_term, "Early device initialization failed" }, - { kbase_backend_time_init, NULL, "Time backend initialization failed" }, - { kbase_device_misc_init, kbase_device_misc_term, - "Miscellaneous device initialization failed" }, - { kbase_device_pcm_dev_init, kbase_device_pcm_dev_term, - "Priority control manager initialization failed" }, - { kbase_ctx_sched_init, kbase_ctx_sched_term, "Context scheduler initialization failed" }, - { kbase_mem_init, kbase_mem_term, "Memory subsystem initialization failed" }, - { kbase_device_coherency_init, NULL, "Device coherency init failed" }, - { kbase_protected_mode_init, kbase_protected_mode_term, - "Protected mode subsystem initialization failed" }, - { kbase_device_list_init, kbase_device_list_term, "Device list setup failed" }, - { kbasep_js_devdata_init, kbasep_js_devdata_term, "Job JS devdata initialization failed" }, - { kbase_device_timeline_init, kbase_device_timeline_term, - "Timeline stream initialization failed" }, - { kbase_clk_rate_trace_manager_init, kbase_clk_rate_trace_manager_term, - "Clock rate trace manager initialization failed" }, - { kbase_instr_backend_init, kbase_instr_backend_term, - "Instrumentation backend initialization failed" }, - { kbase_device_hwcnt_watchdog_if_init, kbase_device_hwcnt_watchdog_if_term, - "GPU hwcnt backend watchdog interface creation failed" }, - { kbase_device_hwcnt_backend_jm_init, kbase_device_hwcnt_backend_jm_term, - "GPU hwcnt backend creation failed" }, - { kbase_device_hwcnt_backend_jm_watchdog_init, kbase_device_hwcnt_backend_jm_watchdog_term, - "GPU hwcnt watchdog backend creation failed" }, - { kbase_device_hwcnt_context_init, kbase_device_hwcnt_context_term, - "GPU hwcnt context initialization failed" }, - { kbase_device_hwcnt_virtualizer_init, kbase_device_hwcnt_virtualizer_term, - "GPU hwcnt virtualizer initialization failed" }, - { kbase_device_kinstr_prfcnt_init, kbase_device_kinstr_prfcnt_term, - "Performance counter instrumentation initialization failed" }, - { kbase_backend_late_init, kbase_backend_late_term, "Late backend initialization failed" }, - { kbase_debug_job_fault_dev_init, kbase_debug_job_fault_dev_term, - "Job fault debug initialization failed" }, - { kbase_device_debugfs_init, kbase_device_debugfs_term, "DebugFS initialization failed" }, - /* Sysfs init needs to happen before registering the device with - * misc_register(), otherwise it causes a race condition between - * registering the device and a uevent event being generated for - * userspace, causing udev rules to run which might expect certain - * sysfs attributes present. As a result of the race condition - * we avoid, some Mali sysfs entries may have appeared to udev - * to not exist. - * For more information, see - * https://www.kernel.org/doc/Documentation/driver-model/device.txt, the - * paragraph that starts with "Word of warning", currently the - * second-last paragraph. - */ - { kbase_sysfs_init, kbase_sysfs_term, "SysFS group creation failed" }, - { kbase_device_misc_register, kbase_device_misc_deregister, - "Misc device registration failed" }, - { kbase_gpuprops_populate_user_buffer, kbase_gpuprops_free_user_buffer, - "GPU property population failed" }, - { NULL, kbase_dummy_job_wa_cleanup, NULL }, - { kbase_device_late_init, kbase_device_late_term, "Late device initialization failed" }, -}; - -static void kbase_device_term_partial(struct kbase_device *kbdev, unsigned int i) -{ - while (i-- > 0) { - if (dev_init[i].term) - dev_init[i].term(kbdev); - } -} - -void kbase_device_term(struct kbase_device *kbdev) -{ - kbase_device_term_partial(kbdev, ARRAY_SIZE(dev_init)); - kbasep_js_devdata_halt(kbdev); - kbase_mem_halt(kbdev); -} - -int kbase_device_init(struct kbase_device *kbdev) -{ - int err = 0; - unsigned int i = 0; - - dev_info(kbdev->dev, "Kernel DDK version %s", MALI_RELEASE_NAME); - - kbase_device_id_init(kbdev); - kbase_disjoint_init(kbdev); - - for (i = 0; i < ARRAY_SIZE(dev_init); i++) { - if (dev_init[i].init) { - err = dev_init[i].init(kbdev); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(kbdev->dev, "%s error = %d\n", dev_init[i].err_mes, - err); - kbase_device_term_partial(kbdev, i); - break; - } - } - } - - return err; -} - -int kbase_device_firmware_init_once(struct kbase_device *kbdev) -{ - int ret = 0; - - mutex_lock(&kbdev->fw_load_lock); - - if (!kbdev->dummy_job_wa_loaded) { - ret = kbase_dummy_job_wa_load(kbdev); - if (!ret) - kbdev->dummy_job_wa_loaded = true; - } - - mutex_unlock(&kbdev->fw_load_lock); - - return ret; -} diff --git a/drivers/gpu/arm/valhall/device/mali_kbase_device.c b/drivers/gpu/arm/valhall/device/mali_kbase_device.c index 8de24066f2ee..78eab00ea46b 100644 --- a/drivers/gpu/arm/valhall/device/mali_kbase_device.c +++ b/drivers/gpu/arm/valhall/device/mali_kbase_device.c @@ -53,6 +53,12 @@ #include "arbiter/mali_kbase_arbiter_pm.h" #include +static uint64_t neural_allowed_mask = UINT64_MAX; +module_param(neural_allowed_mask, ullong, 0444); +MODULE_PARM_DESC( + neural_allowed_mask, + "Additional optional bitmask to restrict which neural engine cores any CSG can enable"); + #if defined(CONFIG_DEBUG_FS) && !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) /* Number of register accesses for the buffer that we allocate during @@ -123,8 +129,6 @@ static void kbase_device_all_as_term(struct kbase_device *kbdev) static int pcm_prioritized_process_cb(struct notifier_block *nb, unsigned long action, void *data) { -#if MALI_USE_CSF - struct kbase_device *const kbdev = container_of(nb, struct kbase_device, pcm_prioritized_process_nb); struct pcm_prioritized_process_notifier_data *const notifier_data = data; @@ -143,8 +147,6 @@ static int pcm_prioritized_process_cb(struct notifier_block *nb, unsigned long a return ret; -#endif /* MALI_USE_CSF */ - return 0; } @@ -351,12 +353,7 @@ int kbase_device_misc_init(struct kbase_device *const kbdev) kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD; -#if MALI_USE_CSF kbdev->reset_timeout_ms = kbase_get_timeout_ms(kbdev, CSF_GPU_RESET_TIMEOUT); -#else /* MALI_USE_CSF */ - kbdev->reset_timeout_ms = JM_DEFAULT_RESET_TIMEOUT_MS; -#endif /* !MALI_USE_CSF */ - kbdev->mmu_mode = kbase_mmu_mode_get_aarch64(); mutex_init(&kbdev->kctx_list_lock); @@ -372,15 +369,9 @@ int kbase_device_misc_init(struct kbase_device *const kbdev) kbdev->oom_notifier_block.notifier_call = NULL; } -#if !MALI_USE_CSF - spin_lock_init(&kbdev->quick_reset_lock); - kbdev->quick_reset_enabled = true; - kbdev->num_of_atoms_hw_completed = 0; -#endif - -#if MALI_USE_CSF atomic_set(&kbdev->fence_signal_timeout_enabled, 1); -#endif + + kbdev->csf.neural_allowed_mask = neural_allowed_mask; return 0; @@ -405,43 +396,12 @@ void kbase_device_misc_term(struct kbase_device *kbdev) if (kbdev->oom_notifier_block.notifier_call) unregister_oom_notifier(&kbdev->oom_notifier_block); -#if MALI_USE_CSF && IS_ENABLED(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) if (atomic_read(&kbdev->live_fence_metadata) > 0) dev_warn(kbdev->dev, "Terminating Kbase device with live fence metadata!"); #endif } -#if !MALI_USE_CSF -void kbase_enable_quick_reset(struct kbase_device *kbdev) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->quick_reset_lock, flags); - - kbdev->quick_reset_enabled = true; - kbdev->num_of_atoms_hw_completed = 0; - - spin_unlock_irqrestore(&kbdev->quick_reset_lock, flags); -} - -void kbase_disable_quick_reset(struct kbase_device *kbdev) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->quick_reset_lock, flags); - - kbdev->quick_reset_enabled = false; - kbdev->num_of_atoms_hw_completed = 0; - - spin_unlock_irqrestore(&kbdev->quick_reset_lock, flags); -} - -bool kbase_is_quick_reset_enabled(struct kbase_device *kbdev) -{ - return kbdev->quick_reset_enabled; -} -#endif - void kbase_device_free(struct kbase_device *kbdev) { vfree(kbdev); diff --git a/drivers/gpu/arm/valhall/device/mali_kbase_device.h b/drivers/gpu/arm/valhall/device/mali_kbase_device.h index 32dff8c2ed1e..2c40fefffc04 100644 --- a/drivers/gpu/arm/valhall/device/mali_kbase_device.h +++ b/drivers/gpu/arm/valhall/device/mali_kbase_device.h @@ -102,10 +102,8 @@ void kbase_device_term(struct kbase_device *kbdev); * * Return: 0 if successful or a negative error code on failure. */ -#if MALI_USE_CSF int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phys_addr_t phys, size_t nr_bytes, u32 flush_op); -#endif /* MALI_USE_CSF */ /** * kbase_gpu_cache_flush_and_busy_wait - Start a cache flush and busy wait @@ -196,7 +194,6 @@ void kbase_clean_caches_done(struct kbase_device *kbdev); */ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val); -#if MALI_USE_CSF /** * kbase_pwr_interrupt - GPU power interrupt handler * @kbdev: Kbase device pointer @@ -206,5 +203,4 @@ void kbase_gpu_interrupt(struct kbase_device *kbdev, u32 val); * handled. */ void kbase_pwr_interrupt(struct kbase_device *kbdev, u32 val); -#endif /* MALI_USE_CSF */ #endif /* _MALI_KBASE_DEVICE_H_ */ diff --git a/drivers/gpu/arm/valhall/device/mali_kbase_device_hw.c b/drivers/gpu/arm/valhall/device/mali_kbase_device_hw.c index 3bfcc5e8f54e..5cfd10afa597 100644 --- a/drivers/gpu/arm/valhall/device/mali_kbase_device_hw.c +++ b/drivers/gpu/arm/valhall/device/mali_kbase_device_hw.c @@ -44,9 +44,7 @@ static int busy_wait_cache_operation(struct kbase_device *kbdev, u32 irq_bit) bool completed = false; s64 diff; u32 irq_bits_to_check = irq_bit; -#if MALI_USE_CSF const bool has_host_pwr_iface = kbdev->pm.backend.has_host_pwr_iface; -#endif /* MALI_USE_CSF */ /* hwaccess_lock must be held to prevent concurrent threads from * cleaning the IRQ bits, otherwise it could be possible for this thread @@ -60,12 +58,8 @@ static int busy_wait_cache_operation(struct kbase_device *kbdev, u32 irq_bit) * been reset which implies that any cache flush operation has been * completed, too. */ -#if MALI_USE_CSF if (!has_host_pwr_iface) -#endif /* MALI_USE_CSF */ - { irq_bits_to_check |= RESET_COMPLETED; - } do { unsigned int i; @@ -76,7 +70,6 @@ static int busy_wait_cache_operation(struct kbase_device *kbdev, u32 irq_bit) completed = true; break; } -#if MALI_USE_CSF /* Check whether the GPU has been reset, which implies that any * cache flush operation has been completed. */ @@ -87,11 +80,8 @@ static int busy_wait_cache_operation(struct kbase_device *kbdev, u32 irq_bit) break; } } -#endif /* MALI_USE_CSF */ } - if (kbase_io_is_aw_removed(kbdev)) - return -ENODEV; diff = ktime_to_ms(ktime_sub(ktime_get_raw(), wait_loop_start)); } while ((diff < wait_time_ms) && !completed); @@ -127,8 +117,6 @@ static int busy_wait_cache_operation(struct kbase_device *kbdev, u32 irq_bit) return 0; } -#if MALI_USE_CSF - int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phys_addr_t phys, size_t nr_bytes, u32 flush_op) { @@ -137,6 +125,7 @@ int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phy lockdep_assert_held(&kbdev->hwaccess_lock); + /* 1. Clear the interrupt FLUSH_PA_RANGE_COMPLETED bit. */ kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_CLEAR), FLUSH_PA_RANGE_COMPLETED); @@ -153,7 +142,6 @@ int kbase_gpu_cache_flush_pa_range_and_busy_wait(struct kbase_device *kbdev, phy return ret; } -#endif /* MALI_USE_CSF */ int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, u32 flush_op) { @@ -165,6 +153,7 @@ int kbase_gpu_cache_flush_and_busy_wait(struct kbase_device *kbdev, u32 flush_op */ lockdep_assert_held(&kbdev->hwaccess_lock); + /* 1. Check if kbdev->cache_clean_in_progress is set. * If it is set, it means there are threads waiting for * CLEAN_CACHES_COMPLETED irq to be raised and that the @@ -218,6 +207,7 @@ void kbase_gpu_start_cache_clean_nolock(struct kbase_device *kbdev, u32 flush_op lockdep_assert_held(&kbdev->hwaccess_lock); + if (kbdev->cache_clean_in_progress) { /* If this is called while another clean is in progress, we * can't rely on the current one to flush any new changes in diff --git a/drivers/gpu/arm/valhall/gpu/Kbuild b/drivers/gpu/arm/valhall/gpu/Kbuild index 772182586a24..cffa4edad1d8 100644 --- a/drivers/gpu/arm/valhall/gpu/Kbuild +++ b/drivers/gpu/arm/valhall/gpu/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2012, 2020-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2012, 2020-2021, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -19,9 +19,4 @@ # valhall_kbase-y += gpu/mali_kbase_gpu.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += gpu/backend/mali_kbase_gpu_fault_csf.o -else - valhall_kbase-y += gpu/backend/mali_kbase_gpu_fault_jm.o -endif +valhall_kbase-y += gpu/backend/mali_kbase_gpu_fault_csf.o diff --git a/drivers/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_fault_jm.c b/drivers/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_fault_jm.c deleted file mode 100644 index 7f3743ca6432..000000000000 --- a/drivers/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_fault_jm.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2022 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include - -#include - -const char *kbase_gpu_exception_name(u32 const exception_code) -{ - const char *e; - - switch (exception_code) { - /* Non-Fault Status code */ - case 0x00: - e = "NOT_STARTED/IDLE/OK"; - break; - case 0x01: - e = "DONE"; - break; - case 0x02: - e = "INTERRUPTED"; - break; - case 0x03: - e = "STOPPED"; - break; - case 0x04: - e = "TERMINATED"; - break; - case 0x08: - e = "ACTIVE"; - break; - /* Job exceptions */ - case 0x40: - e = "JOB_CONFIG_FAULT"; - break; - case 0x41: - e = "JOB_POWER_FAULT"; - break; - case 0x42: - e = "JOB_READ_FAULT"; - break; - case 0x43: - e = "JOB_WRITE_FAULT"; - break; - case 0x44: - e = "JOB_AFFINITY_FAULT"; - break; - case 0x48: - e = "JOB_BUS_FAULT"; - break; - case 0x50: - e = "INSTR_INVALID_PC"; - break; - case 0x51: - e = "INSTR_INVALID_ENC"; - break; - case 0x52: - e = "INSTR_TYPE_MISMATCH"; - break; - case 0x53: - e = "INSTR_OPERAND_FAULT"; - break; - case 0x54: - e = "INSTR_TLS_FAULT"; - break; - case 0x55: - e = "INSTR_BARRIER_FAULT"; - break; - case 0x56: - e = "INSTR_ALIGN_FAULT"; - break; - case 0x58: - e = "DATA_INVALID_FAULT"; - break; - case 0x59: - e = "TILE_RANGE_FAULT"; - break; - case 0x5A: - e = "ADDR_RANGE_FAULT"; - break; - case 0x60: - e = "OUT_OF_MEMORY"; - break; - /* GPU exceptions */ - case 0x80: - e = "DELAYED_BUS_FAULT"; - break; - case 0x88: - e = "SHAREABILITY_FAULT"; - break; - /* MMU exceptions */ - case 0xC0: - case 0xC1: - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - e = "TRANSLATION_FAULT"; - break; - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - e = "PERMISSION_FAULT"; - break; - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - e = "TRANSTAB_BUS_FAULT"; - break; - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - e = "ACCESS_FLAG"; - break; - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - e = "ADDRESS_SIZE_FAULT"; - break; - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - e = "MEMORY_ATTRIBUTES_FAULT"; - break; - default: - e = "UNKNOWN"; - break; - } - - return e; -} diff --git a/drivers/gpu/arm/valhall/hw_access/Kbuild b/drivers/gpu/arm/valhall/hw_access/Kbuild index f3bbfc8bafe2..0d3d45fb0900 100644 --- a/drivers/gpu/arm/valhall/hw_access/Kbuild +++ b/drivers/gpu/arm/valhall/hw_access/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2023 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -19,12 +19,7 @@ # valhall_kbase-y += hw_access/mali_kbase_hw_access.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += hw_access/regmap/mali_kbase_regmap_csf.o -else - valhall_kbase-y += hw_access/regmap/mali_kbase_regmap_jm.o -endif +valhall_kbase-y += hw_access/regmap/mali_kbase_regmap_csf.o ifeq ($(CONFIG_MALI_VALHALL_REAL_HW), y) valhall_kbase-y += hw_access/backend/mali_kbase_hw_access_real_hw.o diff --git a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.c b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.c index f06a62b607c6..45fb2e65640d 100644 --- a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.c +++ b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.c @@ -33,19 +33,6 @@ static u32 always_powered_regs[] = { -#if !MALI_USE_CSF - PTM_AW_IRQ_CLEAR, - PTM_AW_IRQ_INJECTION, - PTM_AW_IRQ_MASK, - PTM_AW_IRQ_RAWSTAT, - PTM_AW_IRQ_STATUS, - PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0, - PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1, - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0, - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1, - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS, - PTM_ID, -#endif /* !MALI_USE_CSF */ }; static void kbasep_reg_setup_always_powered_registers(struct kbase_device *kbdev) @@ -53,11 +40,6 @@ static void kbasep_reg_setup_always_powered_registers(struct kbase_device *kbdev u32 i; -#if !MALI_USE_CSF - if (kbdev->gpu_props.gpu_id.arch_id < GPU_ID_ARCH_MAKE(9, 14, 0)) - return; -#endif /* MALI_USE_CSF */ - for (i = 0; i < ARRAY_SIZE(always_powered_regs); i++) { u32 reg_enum = always_powered_regs[i]; diff --git a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.h b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.h index 1e9f016e2969..3aa50b0770a3 100644 --- a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.h +++ b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access.h @@ -270,9 +270,7 @@ static inline u32 kbase_reg_gpu_irq_all(bool is_legacy) u32 mask = GPU_IRQ_REG_COMMON; if (is_legacy) { -#if MALI_USE_CSF mask |= (RESET_COMPLETED | POWER_CHANGED_ALL); -#endif /* MALI_USE_CSF */ /* Include POWER_CHANGED_SINGLE in debug builds for use in irq latency test. */ if (IS_ENABLED(CONFIG_MALI_VALHALL_DEBUG)) mask |= POWER_CHANGED_SINGLE; diff --git a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap.h b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap.h index c10a32de1e91..bf00919e720a 100644 --- a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap.h +++ b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap.h @@ -22,13 +22,8 @@ #ifndef _MALI_KBASE_HW_ACCESS_REGMAP_H_ #define _MALI_KBASE_HW_ACCESS_REGMAP_H_ -#if MALI_USE_CSF #include "regmap/mali_kbase_regmap_csf_enums.h" #include "regmap/mali_kbase_regmap_csf_macros.h" -#else -#include "regmap/mali_kbase_regmap_jm_enums.h" -#include "regmap/mali_kbase_regmap_jm_macros.h" -#endif /* GPU_U definition */ #ifdef __ASSEMBLER__ diff --git a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap_legacy.h b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap_legacy.h index 1722428a7904..d4b0b6ee86d3 100644 --- a/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap_legacy.h +++ b/drivers/gpu/arm/valhall/hw_access/mali_kbase_hw_access_regmap_legacy.h @@ -22,11 +22,7 @@ #ifndef _MALI_KBASE_REGMAP_LEGACY_H_ #define _MALI_KBASE_REGMAP_LEGACY_H_ -#if MALI_USE_CSF #include "regmap/mali_kbase_regmap_legacy_csf.h" -#else -#include "regmap/mali_kbase_regmap_legacy_jm.h" -#endif /* Begin Register Offsets */ diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_enums.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_enums.h index a912c1fd095a..300781384fe9 100644 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_enums.h +++ b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_enums.h @@ -27,10 +27,6 @@ #ifndef _MALI_KBASE_REGMAP_CSF_ENUMS_H_ #define _MALI_KBASE_REGMAP_CSF_ENUMS_H_ -#if !MALI_USE_CSF -#error "Cannot be compiled with JM" -#endif - enum kbase_regmap_enum_v10_8 { GPU_CONTROL__GPU_ID = 0, /* (RO) 32-bit 0x0 */ GPU_CONTROL__L2_FEATURES, /* (RO) 32-bit 0x4 */ diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_macros.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_macros.h index afdd0dfd44c2..121312acef24 100644 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_macros.h +++ b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_csf_macros.h @@ -22,10 +22,6 @@ #ifndef _MALI_KBASE_REGMAP_CSF_MACROS_H_ #define _MALI_KBASE_REGMAP_CSF_MACROS_H_ -#if !MALI_USE_CSF -#error "Cannot be compiled with JM" -#endif - #define ENUM_OFFSET(_index, _base, _next) (_base + _index * (_next - _base)) diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm.c b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm.c deleted file mode 100644 index 819fae7ed398..000000000000 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm.c +++ /dev/null @@ -1,3041 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * This file is autogenerated. Avoid modifying this file unless absolutely - * necessary. - */ - -#include -#include - -#include -#include "mali_kbase_regmap_jm_enums.h" -#include - -static void kbase_regmap_v6_0_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V6_0_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbdev->regmap.flags[GPU_CONTROL__GPU_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__L2_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TILER_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__MEM_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__MMU_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__AS_PRESENT] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS_PRESENT] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__GPU_IRQ_RAWSTAT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__GPU_IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__GPU_IRQ_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__GPU_IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__GPU_COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__GPU_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__LATEST_FLUSH] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__GPU_FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__GPU_FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__AFBC_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__PWR_KEY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PWR_OVERRIDE0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PWR_OVERRIDE1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_BASE] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_JM_EN] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_SHADER_EN] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_TILER_EN] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__PRFCNT_MMU_L2_EN] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__CYCLE_COUNT] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TIMESTAMP] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__THREAD_MAX_THREADS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__THREAD_MAX_WORKGROUP_SIZE] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__THREAD_MAX_BARRIER_SIZE] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__THREAD_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TEXTURE_FEATURES_0] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TEXTURE_FEATURES_1] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TEXTURE_FEATURES_2] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS0_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS1_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS2_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS3_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS4_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS5_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS6_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS7_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS8_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS9_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS10_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS11_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS12_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS13_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS14_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__JS15_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__SHADER_PRESENT] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TILER_PRESENT] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__L2_PRESENT] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__SHADER_READY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TILER_READY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__L2_READY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__SHADER_PWRON] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__TILER_PWRON] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__L2_PWRON] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__SHADER_PWROFF] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__TILER_PWROFF] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__L2_PWROFF] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__SHADER_PWRTRANS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TILER_PWRTRANS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__L2_PWRTRANS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__SHADER_PWRACTIVE] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__TILER_PWRACTIVE] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__L2_PWRACTIVE] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__COHERENCY_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__COHERENCY_ENABLE] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__GPU_USER_INn] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__GPU_USER_OUTn] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__JM_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__SHADER_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__TILER_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__L2_MMU_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_RAWSTAT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_JS_STATE] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_THROTTLE] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__EVENT_IRQ_RAWSTAT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__EVENT_IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__EVENT_IRQ_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__EVENT_IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS0__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS0__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS1__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS1__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS2__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS2__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS3__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS3__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS4__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS4__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS5__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS5__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS6__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS6__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS7__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS7__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS8__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS8__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS9__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS9__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS10__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS10__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS11__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS11__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS12__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS12__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS13__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS13__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS14__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS14__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__HEAD] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__TAIL] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__AFFINITY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__CONFIG] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__XAFFINITY] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__COMMAND] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__FLUSH_ID] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[JOB_CONTROL__JS15__EVENT_0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__EVENT_1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__EVENT_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__HEAD_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__TAIL_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__AFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__CONFIG_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__XAFFINITY_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__COMMAND_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__FLUSH_ID_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[JOB_CONTROL__JS15__EVENT_MASK_NEXT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__IRQ_RAWSTAT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__IRQ_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS0__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS1__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS2__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS3__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS4__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS5__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS6__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS7__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS8__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS9__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS10__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS11__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS12__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS13__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS14__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE1__ST1MMU__AS15__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__IRQ_RAWSTAT] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__IRQ_MASK] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS0__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS1__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS2__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS3__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS4__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS5__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS6__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS7__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS8__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS9__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS10__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS11__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS12__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS13__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS14__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__TRANSTAB] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__MEMATTR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__LOCKADDR] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__COMMAND] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__FAULTSTATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__FAULTADDRESS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__STATUS] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__TRANSCFG] = - KBASE_REGMAP_WIDTH_64_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[MMU_STAGE2__ST2MMU__AS15__FAULTEXTRA] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - - kbdev->regmap.regs[GPU_CONTROL__GPU_ID] = kbdev->reg + 0x0; - kbdev->regmap.regs[GPU_CONTROL__L2_FEATURES] = kbdev->reg + 0x4; - kbdev->regmap.regs[GPU_CONTROL__TILER_FEATURES] = kbdev->reg + 0xc; - kbdev->regmap.regs[GPU_CONTROL__MEM_FEATURES] = kbdev->reg + 0x10; - kbdev->regmap.regs[GPU_CONTROL__MMU_FEATURES] = kbdev->reg + 0x14; - kbdev->regmap.regs[GPU_CONTROL__AS_PRESENT] = kbdev->reg + 0x18; - kbdev->regmap.regs[GPU_CONTROL__JS_PRESENT] = kbdev->reg + 0x1c; - kbdev->regmap.regs[GPU_CONTROL__GPU_IRQ_RAWSTAT] = kbdev->reg + 0x20; - kbdev->regmap.regs[GPU_CONTROL__GPU_IRQ_CLEAR] = kbdev->reg + 0x24; - kbdev->regmap.regs[GPU_CONTROL__GPU_IRQ_MASK] = kbdev->reg + 0x28; - kbdev->regmap.regs[GPU_CONTROL__GPU_IRQ_STATUS] = kbdev->reg + 0x2c; - kbdev->regmap.regs[GPU_CONTROL__GPU_COMMAND] = kbdev->reg + 0x30; - kbdev->regmap.regs[GPU_CONTROL__GPU_STATUS] = kbdev->reg + 0x34; - kbdev->regmap.regs[GPU_CONTROL__LATEST_FLUSH] = kbdev->reg + 0x38; - kbdev->regmap.regs[GPU_CONTROL__GPU_FAULTSTATUS] = kbdev->reg + 0x3c; - kbdev->regmap.regs[GPU_CONTROL__GPU_FAULTADDRESS] = kbdev->reg + 0x40; - kbdev->regmap.regs[GPU_CONTROL__AFBC_FEATURES] = kbdev->reg + 0x4c; - kbdev->regmap.regs[GPU_CONTROL__PWR_KEY] = kbdev->reg + 0x50; - kbdev->regmap.regs[GPU_CONTROL__PWR_OVERRIDE0] = kbdev->reg + 0x54; - kbdev->regmap.regs[GPU_CONTROL__PWR_OVERRIDE1] = kbdev->reg + 0x58; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_BASE] = kbdev->reg + 0x60; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_CONFIG] = kbdev->reg + 0x68; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_JM_EN] = kbdev->reg + 0x6c; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_SHADER_EN] = kbdev->reg + 0x70; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_TILER_EN] = kbdev->reg + 0x74; - kbdev->regmap.regs[GPU_CONTROL__PRFCNT_MMU_L2_EN] = kbdev->reg + 0x7c; - kbdev->regmap.regs[GPU_CONTROL__CYCLE_COUNT] = kbdev->reg + 0x90; - kbdev->regmap.regs[GPU_CONTROL__TIMESTAMP] = kbdev->reg + 0x98; - kbdev->regmap.regs[GPU_CONTROL__THREAD_MAX_THREADS] = kbdev->reg + 0xa0; - kbdev->regmap.regs[GPU_CONTROL__THREAD_MAX_WORKGROUP_SIZE] = kbdev->reg + 0xa4; - kbdev->regmap.regs[GPU_CONTROL__THREAD_MAX_BARRIER_SIZE] = kbdev->reg + 0xa8; - kbdev->regmap.regs[GPU_CONTROL__THREAD_FEATURES] = kbdev->reg + 0xac; - kbdev->regmap.regs[GPU_CONTROL__TEXTURE_FEATURES_0] = kbdev->reg + 0xb0; - kbdev->regmap.regs[GPU_CONTROL__TEXTURE_FEATURES_1] = kbdev->reg + 0xb4; - kbdev->regmap.regs[GPU_CONTROL__TEXTURE_FEATURES_2] = kbdev->reg + 0xb8; - kbdev->regmap.regs[GPU_CONTROL__JS0_FEATURES] = kbdev->reg + 0xc0; - kbdev->regmap.regs[GPU_CONTROL__JS1_FEATURES] = kbdev->reg + 0xc4; - kbdev->regmap.regs[GPU_CONTROL__JS2_FEATURES] = kbdev->reg + 0xc8; - kbdev->regmap.regs[GPU_CONTROL__JS3_FEATURES] = kbdev->reg + 0xcc; - kbdev->regmap.regs[GPU_CONTROL__JS4_FEATURES] = kbdev->reg + 0xd0; - kbdev->regmap.regs[GPU_CONTROL__JS5_FEATURES] = kbdev->reg + 0xd4; - kbdev->regmap.regs[GPU_CONTROL__JS6_FEATURES] = kbdev->reg + 0xd8; - kbdev->regmap.regs[GPU_CONTROL__JS7_FEATURES] = kbdev->reg + 0xdc; - kbdev->regmap.regs[GPU_CONTROL__JS8_FEATURES] = kbdev->reg + 0xe0; - kbdev->regmap.regs[GPU_CONTROL__JS9_FEATURES] = kbdev->reg + 0xe4; - kbdev->regmap.regs[GPU_CONTROL__JS10_FEATURES] = kbdev->reg + 0xe8; - kbdev->regmap.regs[GPU_CONTROL__JS11_FEATURES] = kbdev->reg + 0xec; - kbdev->regmap.regs[GPU_CONTROL__JS12_FEATURES] = kbdev->reg + 0xf0; - kbdev->regmap.regs[GPU_CONTROL__JS13_FEATURES] = kbdev->reg + 0xf4; - kbdev->regmap.regs[GPU_CONTROL__JS14_FEATURES] = kbdev->reg + 0xf8; - kbdev->regmap.regs[GPU_CONTROL__JS15_FEATURES] = kbdev->reg + 0xfc; - kbdev->regmap.regs[GPU_CONTROL__SHADER_PRESENT] = kbdev->reg + 0x100; - kbdev->regmap.regs[GPU_CONTROL__TILER_PRESENT] = kbdev->reg + 0x110; - kbdev->regmap.regs[GPU_CONTROL__L2_PRESENT] = kbdev->reg + 0x120; - kbdev->regmap.regs[GPU_CONTROL__SHADER_READY] = kbdev->reg + 0x140; - kbdev->regmap.regs[GPU_CONTROL__TILER_READY] = kbdev->reg + 0x150; - kbdev->regmap.regs[GPU_CONTROL__L2_READY] = kbdev->reg + 0x160; - kbdev->regmap.regs[GPU_CONTROL__SHADER_PWRON] = kbdev->reg + 0x180; - kbdev->regmap.regs[GPU_CONTROL__TILER_PWRON] = kbdev->reg + 0x190; - kbdev->regmap.regs[GPU_CONTROL__L2_PWRON] = kbdev->reg + 0x1a0; - kbdev->regmap.regs[GPU_CONTROL__SHADER_PWROFF] = kbdev->reg + 0x1c0; - kbdev->regmap.regs[GPU_CONTROL__TILER_PWROFF] = kbdev->reg + 0x1d0; - kbdev->regmap.regs[GPU_CONTROL__L2_PWROFF] = kbdev->reg + 0x1e0; - kbdev->regmap.regs[GPU_CONTROL__SHADER_PWRTRANS] = kbdev->reg + 0x200; - kbdev->regmap.regs[GPU_CONTROL__TILER_PWRTRANS] = kbdev->reg + 0x210; - kbdev->regmap.regs[GPU_CONTROL__L2_PWRTRANS] = kbdev->reg + 0x220; - kbdev->regmap.regs[GPU_CONTROL__SHADER_PWRACTIVE] = kbdev->reg + 0x240; - kbdev->regmap.regs[GPU_CONTROL__TILER_PWRACTIVE] = kbdev->reg + 0x250; - kbdev->regmap.regs[GPU_CONTROL__L2_PWRACTIVE] = kbdev->reg + 0x260; - kbdev->regmap.regs[GPU_CONTROL__COHERENCY_FEATURES] = kbdev->reg + 0x300; - kbdev->regmap.regs[GPU_CONTROL__COHERENCY_ENABLE] = kbdev->reg + 0x304; - kbdev->regmap.regs[GPU_CONTROL__GPU_USER_INn] = kbdev->reg + 0x400; - kbdev->regmap.regs[GPU_CONTROL__GPU_USER_OUTn] = kbdev->reg + 0x500; - kbdev->regmap.regs[GPU_CONTROL__JM_CONFIG] = kbdev->reg + 0xf00; - kbdev->regmap.regs[GPU_CONTROL__SHADER_CONFIG] = kbdev->reg + 0xf04; - kbdev->regmap.regs[GPU_CONTROL__TILER_CONFIG] = kbdev->reg + 0xf08; - kbdev->regmap.regs[GPU_CONTROL__L2_MMU_CONFIG] = kbdev->reg + 0xf0c; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_RAWSTAT] = kbdev->reg + 0x1000; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_CLEAR] = kbdev->reg + 0x1004; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_MASK] = kbdev->reg + 0x1008; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_STATUS] = kbdev->reg + 0x100c; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_JS_STATE] = kbdev->reg + 0x1010; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_THROTTLE] = kbdev->reg + 0x1014; - kbdev->regmap.regs[JOB_CONTROL__EVENT_IRQ_RAWSTAT] = kbdev->reg + 0x1020; - kbdev->regmap.regs[JOB_CONTROL__EVENT_IRQ_CLEAR] = kbdev->reg + 0x1024; - kbdev->regmap.regs[JOB_CONTROL__EVENT_IRQ_MASK] = kbdev->reg + 0x1028; - kbdev->regmap.regs[JOB_CONTROL__EVENT_IRQ_STATUS] = kbdev->reg + 0x102c; - kbdev->regmap.regs[JOB_CONTROL__JS0__HEAD] = kbdev->reg + 0x1800; - kbdev->regmap.regs[JOB_CONTROL__JS0__TAIL] = kbdev->reg + 0x1808; - kbdev->regmap.regs[JOB_CONTROL__JS0__AFFINITY] = kbdev->reg + 0x1810; - kbdev->regmap.regs[JOB_CONTROL__JS0__CONFIG] = kbdev->reg + 0x1818; - kbdev->regmap.regs[JOB_CONTROL__JS0__XAFFINITY] = kbdev->reg + 0x181c; - kbdev->regmap.regs[JOB_CONTROL__JS0__COMMAND] = kbdev->reg + 0x1820; - kbdev->regmap.regs[JOB_CONTROL__JS0__STATUS] = kbdev->reg + 0x1824; - kbdev->regmap.regs[JOB_CONTROL__JS0__FLUSH_ID] = kbdev->reg + 0x1830; - kbdev->regmap.regs[JOB_CONTROL__JS0__EVENT_0] = kbdev->reg + 0x1834; - kbdev->regmap.regs[JOB_CONTROL__JS0__EVENT_1] = kbdev->reg + 0x1838; - kbdev->regmap.regs[JOB_CONTROL__JS0__EVENT_MASK] = kbdev->reg + 0x183c; - kbdev->regmap.regs[JOB_CONTROL__JS0__HEAD_NEXT] = kbdev->reg + 0x1840; - kbdev->regmap.regs[JOB_CONTROL__JS0__TAIL_NEXT] = kbdev->reg + 0x1848; - kbdev->regmap.regs[JOB_CONTROL__JS0__AFFINITY_NEXT] = kbdev->reg + 0x1850; - kbdev->regmap.regs[JOB_CONTROL__JS0__CONFIG_NEXT] = kbdev->reg + 0x1858; - kbdev->regmap.regs[JOB_CONTROL__JS0__XAFFINITY_NEXT] = kbdev->reg + 0x185c; - kbdev->regmap.regs[JOB_CONTROL__JS0__COMMAND_NEXT] = kbdev->reg + 0x1860; - kbdev->regmap.regs[JOB_CONTROL__JS0__FLUSH_ID_NEXT] = kbdev->reg + 0x1870; - kbdev->regmap.regs[JOB_CONTROL__JS0__EVENT_MASK_NEXT] = kbdev->reg + 0x187c; - kbdev->regmap.regs[JOB_CONTROL__JS1__HEAD] = kbdev->reg + 0x1880; - kbdev->regmap.regs[JOB_CONTROL__JS1__TAIL] = kbdev->reg + 0x1888; - kbdev->regmap.regs[JOB_CONTROL__JS1__AFFINITY] = kbdev->reg + 0x1890; - kbdev->regmap.regs[JOB_CONTROL__JS1__CONFIG] = kbdev->reg + 0x1898; - kbdev->regmap.regs[JOB_CONTROL__JS1__XAFFINITY] = kbdev->reg + 0x189c; - kbdev->regmap.regs[JOB_CONTROL__JS1__COMMAND] = kbdev->reg + 0x18a0; - kbdev->regmap.regs[JOB_CONTROL__JS1__STATUS] = kbdev->reg + 0x18a4; - kbdev->regmap.regs[JOB_CONTROL__JS1__FLUSH_ID] = kbdev->reg + 0x18b0; - kbdev->regmap.regs[JOB_CONTROL__JS1__EVENT_0] = kbdev->reg + 0x18b4; - kbdev->regmap.regs[JOB_CONTROL__JS1__EVENT_1] = kbdev->reg + 0x18b8; - kbdev->regmap.regs[JOB_CONTROL__JS1__EVENT_MASK] = kbdev->reg + 0x18bc; - kbdev->regmap.regs[JOB_CONTROL__JS1__HEAD_NEXT] = kbdev->reg + 0x18c0; - kbdev->regmap.regs[JOB_CONTROL__JS1__TAIL_NEXT] = kbdev->reg + 0x18c8; - kbdev->regmap.regs[JOB_CONTROL__JS1__AFFINITY_NEXT] = kbdev->reg + 0x18d0; - kbdev->regmap.regs[JOB_CONTROL__JS1__CONFIG_NEXT] = kbdev->reg + 0x18d8; - kbdev->regmap.regs[JOB_CONTROL__JS1__XAFFINITY_NEXT] = kbdev->reg + 0x18dc; - kbdev->regmap.regs[JOB_CONTROL__JS1__COMMAND_NEXT] = kbdev->reg + 0x18e0; - kbdev->regmap.regs[JOB_CONTROL__JS1__FLUSH_ID_NEXT] = kbdev->reg + 0x18f0; - kbdev->regmap.regs[JOB_CONTROL__JS1__EVENT_MASK_NEXT] = kbdev->reg + 0x18fc; - kbdev->regmap.regs[JOB_CONTROL__JS2__HEAD] = kbdev->reg + 0x1900; - kbdev->regmap.regs[JOB_CONTROL__JS2__TAIL] = kbdev->reg + 0x1908; - kbdev->regmap.regs[JOB_CONTROL__JS2__AFFINITY] = kbdev->reg + 0x1910; - kbdev->regmap.regs[JOB_CONTROL__JS2__CONFIG] = kbdev->reg + 0x1918; - kbdev->regmap.regs[JOB_CONTROL__JS2__XAFFINITY] = kbdev->reg + 0x191c; - kbdev->regmap.regs[JOB_CONTROL__JS2__COMMAND] = kbdev->reg + 0x1920; - kbdev->regmap.regs[JOB_CONTROL__JS2__STATUS] = kbdev->reg + 0x1924; - kbdev->regmap.regs[JOB_CONTROL__JS2__FLUSH_ID] = kbdev->reg + 0x1930; - kbdev->regmap.regs[JOB_CONTROL__JS2__EVENT_0] = kbdev->reg + 0x1934; - kbdev->regmap.regs[JOB_CONTROL__JS2__EVENT_1] = kbdev->reg + 0x1938; - kbdev->regmap.regs[JOB_CONTROL__JS2__EVENT_MASK] = kbdev->reg + 0x193c; - kbdev->regmap.regs[JOB_CONTROL__JS2__HEAD_NEXT] = kbdev->reg + 0x1940; - kbdev->regmap.regs[JOB_CONTROL__JS2__TAIL_NEXT] = kbdev->reg + 0x1948; - kbdev->regmap.regs[JOB_CONTROL__JS2__AFFINITY_NEXT] = kbdev->reg + 0x1950; - kbdev->regmap.regs[JOB_CONTROL__JS2__CONFIG_NEXT] = kbdev->reg + 0x1958; - kbdev->regmap.regs[JOB_CONTROL__JS2__XAFFINITY_NEXT] = kbdev->reg + 0x195c; - kbdev->regmap.regs[JOB_CONTROL__JS2__COMMAND_NEXT] = kbdev->reg + 0x1960; - kbdev->regmap.regs[JOB_CONTROL__JS2__FLUSH_ID_NEXT] = kbdev->reg + 0x1970; - kbdev->regmap.regs[JOB_CONTROL__JS2__EVENT_MASK_NEXT] = kbdev->reg + 0x197c; - kbdev->regmap.regs[JOB_CONTROL__JS3__HEAD] = kbdev->reg + 0x1980; - kbdev->regmap.regs[JOB_CONTROL__JS3__TAIL] = kbdev->reg + 0x1988; - kbdev->regmap.regs[JOB_CONTROL__JS3__AFFINITY] = kbdev->reg + 0x1990; - kbdev->regmap.regs[JOB_CONTROL__JS3__CONFIG] = kbdev->reg + 0x1998; - kbdev->regmap.regs[JOB_CONTROL__JS3__XAFFINITY] = kbdev->reg + 0x199c; - kbdev->regmap.regs[JOB_CONTROL__JS3__COMMAND] = kbdev->reg + 0x19a0; - kbdev->regmap.regs[JOB_CONTROL__JS3__STATUS] = kbdev->reg + 0x19a4; - kbdev->regmap.regs[JOB_CONTROL__JS3__FLUSH_ID] = kbdev->reg + 0x19b0; - kbdev->regmap.regs[JOB_CONTROL__JS3__EVENT_0] = kbdev->reg + 0x19b4; - kbdev->regmap.regs[JOB_CONTROL__JS3__EVENT_1] = kbdev->reg + 0x19b8; - kbdev->regmap.regs[JOB_CONTROL__JS3__EVENT_MASK] = kbdev->reg + 0x19bc; - kbdev->regmap.regs[JOB_CONTROL__JS3__HEAD_NEXT] = kbdev->reg + 0x19c0; - kbdev->regmap.regs[JOB_CONTROL__JS3__TAIL_NEXT] = kbdev->reg + 0x19c8; - kbdev->regmap.regs[JOB_CONTROL__JS3__AFFINITY_NEXT] = kbdev->reg + 0x19d0; - kbdev->regmap.regs[JOB_CONTROL__JS3__CONFIG_NEXT] = kbdev->reg + 0x19d8; - kbdev->regmap.regs[JOB_CONTROL__JS3__XAFFINITY_NEXT] = kbdev->reg + 0x19dc; - kbdev->regmap.regs[JOB_CONTROL__JS3__COMMAND_NEXT] = kbdev->reg + 0x19e0; - kbdev->regmap.regs[JOB_CONTROL__JS3__FLUSH_ID_NEXT] = kbdev->reg + 0x19f0; - kbdev->regmap.regs[JOB_CONTROL__JS3__EVENT_MASK_NEXT] = kbdev->reg + 0x19fc; - kbdev->regmap.regs[JOB_CONTROL__JS4__HEAD] = kbdev->reg + 0x1a00; - kbdev->regmap.regs[JOB_CONTROL__JS4__TAIL] = kbdev->reg + 0x1a08; - kbdev->regmap.regs[JOB_CONTROL__JS4__AFFINITY] = kbdev->reg + 0x1a10; - kbdev->regmap.regs[JOB_CONTROL__JS4__CONFIG] = kbdev->reg + 0x1a18; - kbdev->regmap.regs[JOB_CONTROL__JS4__XAFFINITY] = kbdev->reg + 0x1a1c; - kbdev->regmap.regs[JOB_CONTROL__JS4__COMMAND] = kbdev->reg + 0x1a20; - kbdev->regmap.regs[JOB_CONTROL__JS4__STATUS] = kbdev->reg + 0x1a24; - kbdev->regmap.regs[JOB_CONTROL__JS4__FLUSH_ID] = kbdev->reg + 0x1a30; - kbdev->regmap.regs[JOB_CONTROL__JS4__EVENT_0] = kbdev->reg + 0x1a34; - kbdev->regmap.regs[JOB_CONTROL__JS4__EVENT_1] = kbdev->reg + 0x1a38; - kbdev->regmap.regs[JOB_CONTROL__JS4__EVENT_MASK] = kbdev->reg + 0x1a3c; - kbdev->regmap.regs[JOB_CONTROL__JS4__HEAD_NEXT] = kbdev->reg + 0x1a40; - kbdev->regmap.regs[JOB_CONTROL__JS4__TAIL_NEXT] = kbdev->reg + 0x1a48; - kbdev->regmap.regs[JOB_CONTROL__JS4__AFFINITY_NEXT] = kbdev->reg + 0x1a50; - kbdev->regmap.regs[JOB_CONTROL__JS4__CONFIG_NEXT] = kbdev->reg + 0x1a58; - kbdev->regmap.regs[JOB_CONTROL__JS4__XAFFINITY_NEXT] = kbdev->reg + 0x1a5c; - kbdev->regmap.regs[JOB_CONTROL__JS4__COMMAND_NEXT] = kbdev->reg + 0x1a60; - kbdev->regmap.regs[JOB_CONTROL__JS4__FLUSH_ID_NEXT] = kbdev->reg + 0x1a70; - kbdev->regmap.regs[JOB_CONTROL__JS4__EVENT_MASK_NEXT] = kbdev->reg + 0x1a7c; - kbdev->regmap.regs[JOB_CONTROL__JS5__HEAD] = kbdev->reg + 0x1a80; - kbdev->regmap.regs[JOB_CONTROL__JS5__TAIL] = kbdev->reg + 0x1a88; - kbdev->regmap.regs[JOB_CONTROL__JS5__AFFINITY] = kbdev->reg + 0x1a90; - kbdev->regmap.regs[JOB_CONTROL__JS5__CONFIG] = kbdev->reg + 0x1a98; - kbdev->regmap.regs[JOB_CONTROL__JS5__XAFFINITY] = kbdev->reg + 0x1a9c; - kbdev->regmap.regs[JOB_CONTROL__JS5__COMMAND] = kbdev->reg + 0x1aa0; - kbdev->regmap.regs[JOB_CONTROL__JS5__STATUS] = kbdev->reg + 0x1aa4; - kbdev->regmap.regs[JOB_CONTROL__JS5__FLUSH_ID] = kbdev->reg + 0x1ab0; - kbdev->regmap.regs[JOB_CONTROL__JS5__EVENT_0] = kbdev->reg + 0x1ab4; - kbdev->regmap.regs[JOB_CONTROL__JS5__EVENT_1] = kbdev->reg + 0x1ab8; - kbdev->regmap.regs[JOB_CONTROL__JS5__EVENT_MASK] = kbdev->reg + 0x1abc; - kbdev->regmap.regs[JOB_CONTROL__JS5__HEAD_NEXT] = kbdev->reg + 0x1ac0; - kbdev->regmap.regs[JOB_CONTROL__JS5__TAIL_NEXT] = kbdev->reg + 0x1ac8; - kbdev->regmap.regs[JOB_CONTROL__JS5__AFFINITY_NEXT] = kbdev->reg + 0x1ad0; - kbdev->regmap.regs[JOB_CONTROL__JS5__CONFIG_NEXT] = kbdev->reg + 0x1ad8; - kbdev->regmap.regs[JOB_CONTROL__JS5__XAFFINITY_NEXT] = kbdev->reg + 0x1adc; - kbdev->regmap.regs[JOB_CONTROL__JS5__COMMAND_NEXT] = kbdev->reg + 0x1ae0; - kbdev->regmap.regs[JOB_CONTROL__JS5__FLUSH_ID_NEXT] = kbdev->reg + 0x1af0; - kbdev->regmap.regs[JOB_CONTROL__JS5__EVENT_MASK_NEXT] = kbdev->reg + 0x1afc; - kbdev->regmap.regs[JOB_CONTROL__JS6__HEAD] = kbdev->reg + 0x1b00; - kbdev->regmap.regs[JOB_CONTROL__JS6__TAIL] = kbdev->reg + 0x1b08; - kbdev->regmap.regs[JOB_CONTROL__JS6__AFFINITY] = kbdev->reg + 0x1b10; - kbdev->regmap.regs[JOB_CONTROL__JS6__CONFIG] = kbdev->reg + 0x1b18; - kbdev->regmap.regs[JOB_CONTROL__JS6__XAFFINITY] = kbdev->reg + 0x1b1c; - kbdev->regmap.regs[JOB_CONTROL__JS6__COMMAND] = kbdev->reg + 0x1b20; - kbdev->regmap.regs[JOB_CONTROL__JS6__STATUS] = kbdev->reg + 0x1b24; - kbdev->regmap.regs[JOB_CONTROL__JS6__FLUSH_ID] = kbdev->reg + 0x1b30; - kbdev->regmap.regs[JOB_CONTROL__JS6__EVENT_0] = kbdev->reg + 0x1b34; - kbdev->regmap.regs[JOB_CONTROL__JS6__EVENT_1] = kbdev->reg + 0x1b38; - kbdev->regmap.regs[JOB_CONTROL__JS6__EVENT_MASK] = kbdev->reg + 0x1b3c; - kbdev->regmap.regs[JOB_CONTROL__JS6__HEAD_NEXT] = kbdev->reg + 0x1b40; - kbdev->regmap.regs[JOB_CONTROL__JS6__TAIL_NEXT] = kbdev->reg + 0x1b48; - kbdev->regmap.regs[JOB_CONTROL__JS6__AFFINITY_NEXT] = kbdev->reg + 0x1b50; - kbdev->regmap.regs[JOB_CONTROL__JS6__CONFIG_NEXT] = kbdev->reg + 0x1b58; - kbdev->regmap.regs[JOB_CONTROL__JS6__XAFFINITY_NEXT] = kbdev->reg + 0x1b5c; - kbdev->regmap.regs[JOB_CONTROL__JS6__COMMAND_NEXT] = kbdev->reg + 0x1b60; - kbdev->regmap.regs[JOB_CONTROL__JS6__FLUSH_ID_NEXT] = kbdev->reg + 0x1b70; - kbdev->regmap.regs[JOB_CONTROL__JS6__EVENT_MASK_NEXT] = kbdev->reg + 0x1b7c; - kbdev->regmap.regs[JOB_CONTROL__JS7__HEAD] = kbdev->reg + 0x1b80; - kbdev->regmap.regs[JOB_CONTROL__JS7__TAIL] = kbdev->reg + 0x1b88; - kbdev->regmap.regs[JOB_CONTROL__JS7__AFFINITY] = kbdev->reg + 0x1b90; - kbdev->regmap.regs[JOB_CONTROL__JS7__CONFIG] = kbdev->reg + 0x1b98; - kbdev->regmap.regs[JOB_CONTROL__JS7__XAFFINITY] = kbdev->reg + 0x1b9c; - kbdev->regmap.regs[JOB_CONTROL__JS7__COMMAND] = kbdev->reg + 0x1ba0; - kbdev->regmap.regs[JOB_CONTROL__JS7__STATUS] = kbdev->reg + 0x1ba4; - kbdev->regmap.regs[JOB_CONTROL__JS7__FLUSH_ID] = kbdev->reg + 0x1bb0; - kbdev->regmap.regs[JOB_CONTROL__JS7__EVENT_0] = kbdev->reg + 0x1bb4; - kbdev->regmap.regs[JOB_CONTROL__JS7__EVENT_1] = kbdev->reg + 0x1bb8; - kbdev->regmap.regs[JOB_CONTROL__JS7__EVENT_MASK] = kbdev->reg + 0x1bbc; - kbdev->regmap.regs[JOB_CONTROL__JS7__HEAD_NEXT] = kbdev->reg + 0x1bc0; - kbdev->regmap.regs[JOB_CONTROL__JS7__TAIL_NEXT] = kbdev->reg + 0x1bc8; - kbdev->regmap.regs[JOB_CONTROL__JS7__AFFINITY_NEXT] = kbdev->reg + 0x1bd0; - kbdev->regmap.regs[JOB_CONTROL__JS7__CONFIG_NEXT] = kbdev->reg + 0x1bd8; - kbdev->regmap.regs[JOB_CONTROL__JS7__XAFFINITY_NEXT] = kbdev->reg + 0x1bdc; - kbdev->regmap.regs[JOB_CONTROL__JS7__COMMAND_NEXT] = kbdev->reg + 0x1be0; - kbdev->regmap.regs[JOB_CONTROL__JS7__FLUSH_ID_NEXT] = kbdev->reg + 0x1bf0; - kbdev->regmap.regs[JOB_CONTROL__JS7__EVENT_MASK_NEXT] = kbdev->reg + 0x1bfc; - kbdev->regmap.regs[JOB_CONTROL__JS8__HEAD] = kbdev->reg + 0x1c00; - kbdev->regmap.regs[JOB_CONTROL__JS8__TAIL] = kbdev->reg + 0x1c08; - kbdev->regmap.regs[JOB_CONTROL__JS8__AFFINITY] = kbdev->reg + 0x1c10; - kbdev->regmap.regs[JOB_CONTROL__JS8__CONFIG] = kbdev->reg + 0x1c18; - kbdev->regmap.regs[JOB_CONTROL__JS8__XAFFINITY] = kbdev->reg + 0x1c1c; - kbdev->regmap.regs[JOB_CONTROL__JS8__COMMAND] = kbdev->reg + 0x1c20; - kbdev->regmap.regs[JOB_CONTROL__JS8__STATUS] = kbdev->reg + 0x1c24; - kbdev->regmap.regs[JOB_CONTROL__JS8__FLUSH_ID] = kbdev->reg + 0x1c30; - kbdev->regmap.regs[JOB_CONTROL__JS8__EVENT_0] = kbdev->reg + 0x1c34; - kbdev->regmap.regs[JOB_CONTROL__JS8__EVENT_1] = kbdev->reg + 0x1c38; - kbdev->regmap.regs[JOB_CONTROL__JS8__EVENT_MASK] = kbdev->reg + 0x1c3c; - kbdev->regmap.regs[JOB_CONTROL__JS8__HEAD_NEXT] = kbdev->reg + 0x1c40; - kbdev->regmap.regs[JOB_CONTROL__JS8__TAIL_NEXT] = kbdev->reg + 0x1c48; - kbdev->regmap.regs[JOB_CONTROL__JS8__AFFINITY_NEXT] = kbdev->reg + 0x1c50; - kbdev->regmap.regs[JOB_CONTROL__JS8__CONFIG_NEXT] = kbdev->reg + 0x1c58; - kbdev->regmap.regs[JOB_CONTROL__JS8__XAFFINITY_NEXT] = kbdev->reg + 0x1c5c; - kbdev->regmap.regs[JOB_CONTROL__JS8__COMMAND_NEXT] = kbdev->reg + 0x1c60; - kbdev->regmap.regs[JOB_CONTROL__JS8__FLUSH_ID_NEXT] = kbdev->reg + 0x1c70; - kbdev->regmap.regs[JOB_CONTROL__JS8__EVENT_MASK_NEXT] = kbdev->reg + 0x1c7c; - kbdev->regmap.regs[JOB_CONTROL__JS9__HEAD] = kbdev->reg + 0x1c80; - kbdev->regmap.regs[JOB_CONTROL__JS9__TAIL] = kbdev->reg + 0x1c88; - kbdev->regmap.regs[JOB_CONTROL__JS9__AFFINITY] = kbdev->reg + 0x1c90; - kbdev->regmap.regs[JOB_CONTROL__JS9__CONFIG] = kbdev->reg + 0x1c98; - kbdev->regmap.regs[JOB_CONTROL__JS9__XAFFINITY] = kbdev->reg + 0x1c9c; - kbdev->regmap.regs[JOB_CONTROL__JS9__COMMAND] = kbdev->reg + 0x1ca0; - kbdev->regmap.regs[JOB_CONTROL__JS9__STATUS] = kbdev->reg + 0x1ca4; - kbdev->regmap.regs[JOB_CONTROL__JS9__FLUSH_ID] = kbdev->reg + 0x1cb0; - kbdev->regmap.regs[JOB_CONTROL__JS9__EVENT_0] = kbdev->reg + 0x1cb4; - kbdev->regmap.regs[JOB_CONTROL__JS9__EVENT_1] = kbdev->reg + 0x1cb8; - kbdev->regmap.regs[JOB_CONTROL__JS9__EVENT_MASK] = kbdev->reg + 0x1cbc; - kbdev->regmap.regs[JOB_CONTROL__JS9__HEAD_NEXT] = kbdev->reg + 0x1cc0; - kbdev->regmap.regs[JOB_CONTROL__JS9__TAIL_NEXT] = kbdev->reg + 0x1cc8; - kbdev->regmap.regs[JOB_CONTROL__JS9__AFFINITY_NEXT] = kbdev->reg + 0x1cd0; - kbdev->regmap.regs[JOB_CONTROL__JS9__CONFIG_NEXT] = kbdev->reg + 0x1cd8; - kbdev->regmap.regs[JOB_CONTROL__JS9__XAFFINITY_NEXT] = kbdev->reg + 0x1cdc; - kbdev->regmap.regs[JOB_CONTROL__JS9__COMMAND_NEXT] = kbdev->reg + 0x1ce0; - kbdev->regmap.regs[JOB_CONTROL__JS9__FLUSH_ID_NEXT] = kbdev->reg + 0x1cf0; - kbdev->regmap.regs[JOB_CONTROL__JS9__EVENT_MASK_NEXT] = kbdev->reg + 0x1cfc; - kbdev->regmap.regs[JOB_CONTROL__JS10__HEAD] = kbdev->reg + 0x1d00; - kbdev->regmap.regs[JOB_CONTROL__JS10__TAIL] = kbdev->reg + 0x1d08; - kbdev->regmap.regs[JOB_CONTROL__JS10__AFFINITY] = kbdev->reg + 0x1d10; - kbdev->regmap.regs[JOB_CONTROL__JS10__CONFIG] = kbdev->reg + 0x1d18; - kbdev->regmap.regs[JOB_CONTROL__JS10__XAFFINITY] = kbdev->reg + 0x1d1c; - kbdev->regmap.regs[JOB_CONTROL__JS10__COMMAND] = kbdev->reg + 0x1d20; - kbdev->regmap.regs[JOB_CONTROL__JS10__STATUS] = kbdev->reg + 0x1d24; - kbdev->regmap.regs[JOB_CONTROL__JS10__FLUSH_ID] = kbdev->reg + 0x1d30; - kbdev->regmap.regs[JOB_CONTROL__JS10__EVENT_0] = kbdev->reg + 0x1d34; - kbdev->regmap.regs[JOB_CONTROL__JS10__EVENT_1] = kbdev->reg + 0x1d38; - kbdev->regmap.regs[JOB_CONTROL__JS10__EVENT_MASK] = kbdev->reg + 0x1d3c; - kbdev->regmap.regs[JOB_CONTROL__JS10__HEAD_NEXT] = kbdev->reg + 0x1d40; - kbdev->regmap.regs[JOB_CONTROL__JS10__TAIL_NEXT] = kbdev->reg + 0x1d48; - kbdev->regmap.regs[JOB_CONTROL__JS10__AFFINITY_NEXT] = kbdev->reg + 0x1d50; - kbdev->regmap.regs[JOB_CONTROL__JS10__CONFIG_NEXT] = kbdev->reg + 0x1d58; - kbdev->regmap.regs[JOB_CONTROL__JS10__XAFFINITY_NEXT] = kbdev->reg + 0x1d5c; - kbdev->regmap.regs[JOB_CONTROL__JS10__COMMAND_NEXT] = kbdev->reg + 0x1d60; - kbdev->regmap.regs[JOB_CONTROL__JS10__FLUSH_ID_NEXT] = kbdev->reg + 0x1d70; - kbdev->regmap.regs[JOB_CONTROL__JS10__EVENT_MASK_NEXT] = kbdev->reg + 0x1d7c; - kbdev->regmap.regs[JOB_CONTROL__JS11__HEAD] = kbdev->reg + 0x1d80; - kbdev->regmap.regs[JOB_CONTROL__JS11__TAIL] = kbdev->reg + 0x1d88; - kbdev->regmap.regs[JOB_CONTROL__JS11__AFFINITY] = kbdev->reg + 0x1d90; - kbdev->regmap.regs[JOB_CONTROL__JS11__CONFIG] = kbdev->reg + 0x1d98; - kbdev->regmap.regs[JOB_CONTROL__JS11__XAFFINITY] = kbdev->reg + 0x1d9c; - kbdev->regmap.regs[JOB_CONTROL__JS11__COMMAND] = kbdev->reg + 0x1da0; - kbdev->regmap.regs[JOB_CONTROL__JS11__STATUS] = kbdev->reg + 0x1da4; - kbdev->regmap.regs[JOB_CONTROL__JS11__FLUSH_ID] = kbdev->reg + 0x1db0; - kbdev->regmap.regs[JOB_CONTROL__JS11__EVENT_0] = kbdev->reg + 0x1db4; - kbdev->regmap.regs[JOB_CONTROL__JS11__EVENT_1] = kbdev->reg + 0x1db8; - kbdev->regmap.regs[JOB_CONTROL__JS11__EVENT_MASK] = kbdev->reg + 0x1dbc; - kbdev->regmap.regs[JOB_CONTROL__JS11__HEAD_NEXT] = kbdev->reg + 0x1dc0; - kbdev->regmap.regs[JOB_CONTROL__JS11__TAIL_NEXT] = kbdev->reg + 0x1dc8; - kbdev->regmap.regs[JOB_CONTROL__JS11__AFFINITY_NEXT] = kbdev->reg + 0x1dd0; - kbdev->regmap.regs[JOB_CONTROL__JS11__CONFIG_NEXT] = kbdev->reg + 0x1dd8; - kbdev->regmap.regs[JOB_CONTROL__JS11__XAFFINITY_NEXT] = kbdev->reg + 0x1ddc; - kbdev->regmap.regs[JOB_CONTROL__JS11__COMMAND_NEXT] = kbdev->reg + 0x1de0; - kbdev->regmap.regs[JOB_CONTROL__JS11__FLUSH_ID_NEXT] = kbdev->reg + 0x1df0; - kbdev->regmap.regs[JOB_CONTROL__JS11__EVENT_MASK_NEXT] = kbdev->reg + 0x1dfc; - kbdev->regmap.regs[JOB_CONTROL__JS12__HEAD] = kbdev->reg + 0x1e00; - kbdev->regmap.regs[JOB_CONTROL__JS12__TAIL] = kbdev->reg + 0x1e08; - kbdev->regmap.regs[JOB_CONTROL__JS12__AFFINITY] = kbdev->reg + 0x1e10; - kbdev->regmap.regs[JOB_CONTROL__JS12__CONFIG] = kbdev->reg + 0x1e18; - kbdev->regmap.regs[JOB_CONTROL__JS12__XAFFINITY] = kbdev->reg + 0x1e1c; - kbdev->regmap.regs[JOB_CONTROL__JS12__COMMAND] = kbdev->reg + 0x1e20; - kbdev->regmap.regs[JOB_CONTROL__JS12__STATUS] = kbdev->reg + 0x1e24; - kbdev->regmap.regs[JOB_CONTROL__JS12__FLUSH_ID] = kbdev->reg + 0x1e30; - kbdev->regmap.regs[JOB_CONTROL__JS12__EVENT_0] = kbdev->reg + 0x1e34; - kbdev->regmap.regs[JOB_CONTROL__JS12__EVENT_1] = kbdev->reg + 0x1e38; - kbdev->regmap.regs[JOB_CONTROL__JS12__EVENT_MASK] = kbdev->reg + 0x1e3c; - kbdev->regmap.regs[JOB_CONTROL__JS12__HEAD_NEXT] = kbdev->reg + 0x1e40; - kbdev->regmap.regs[JOB_CONTROL__JS12__TAIL_NEXT] = kbdev->reg + 0x1e48; - kbdev->regmap.regs[JOB_CONTROL__JS12__AFFINITY_NEXT] = kbdev->reg + 0x1e50; - kbdev->regmap.regs[JOB_CONTROL__JS12__CONFIG_NEXT] = kbdev->reg + 0x1e58; - kbdev->regmap.regs[JOB_CONTROL__JS12__XAFFINITY_NEXT] = kbdev->reg + 0x1e5c; - kbdev->regmap.regs[JOB_CONTROL__JS12__COMMAND_NEXT] = kbdev->reg + 0x1e60; - kbdev->regmap.regs[JOB_CONTROL__JS12__FLUSH_ID_NEXT] = kbdev->reg + 0x1e70; - kbdev->regmap.regs[JOB_CONTROL__JS12__EVENT_MASK_NEXT] = kbdev->reg + 0x1e7c; - kbdev->regmap.regs[JOB_CONTROL__JS13__HEAD] = kbdev->reg + 0x1e80; - kbdev->regmap.regs[JOB_CONTROL__JS13__TAIL] = kbdev->reg + 0x1e88; - kbdev->regmap.regs[JOB_CONTROL__JS13__AFFINITY] = kbdev->reg + 0x1e90; - kbdev->regmap.regs[JOB_CONTROL__JS13__CONFIG] = kbdev->reg + 0x1e98; - kbdev->regmap.regs[JOB_CONTROL__JS13__XAFFINITY] = kbdev->reg + 0x1e9c; - kbdev->regmap.regs[JOB_CONTROL__JS13__COMMAND] = kbdev->reg + 0x1ea0; - kbdev->regmap.regs[JOB_CONTROL__JS13__STATUS] = kbdev->reg + 0x1ea4; - kbdev->regmap.regs[JOB_CONTROL__JS13__FLUSH_ID] = kbdev->reg + 0x1eb0; - kbdev->regmap.regs[JOB_CONTROL__JS13__EVENT_0] = kbdev->reg + 0x1eb4; - kbdev->regmap.regs[JOB_CONTROL__JS13__EVENT_1] = kbdev->reg + 0x1eb8; - kbdev->regmap.regs[JOB_CONTROL__JS13__EVENT_MASK] = kbdev->reg + 0x1ebc; - kbdev->regmap.regs[JOB_CONTROL__JS13__HEAD_NEXT] = kbdev->reg + 0x1ec0; - kbdev->regmap.regs[JOB_CONTROL__JS13__TAIL_NEXT] = kbdev->reg + 0x1ec8; - kbdev->regmap.regs[JOB_CONTROL__JS13__AFFINITY_NEXT] = kbdev->reg + 0x1ed0; - kbdev->regmap.regs[JOB_CONTROL__JS13__CONFIG_NEXT] = kbdev->reg + 0x1ed8; - kbdev->regmap.regs[JOB_CONTROL__JS13__XAFFINITY_NEXT] = kbdev->reg + 0x1edc; - kbdev->regmap.regs[JOB_CONTROL__JS13__COMMAND_NEXT] = kbdev->reg + 0x1ee0; - kbdev->regmap.regs[JOB_CONTROL__JS13__FLUSH_ID_NEXT] = kbdev->reg + 0x1ef0; - kbdev->regmap.regs[JOB_CONTROL__JS13__EVENT_MASK_NEXT] = kbdev->reg + 0x1efc; - kbdev->regmap.regs[JOB_CONTROL__JS14__HEAD] = kbdev->reg + 0x1f00; - kbdev->regmap.regs[JOB_CONTROL__JS14__TAIL] = kbdev->reg + 0x1f08; - kbdev->regmap.regs[JOB_CONTROL__JS14__AFFINITY] = kbdev->reg + 0x1f10; - kbdev->regmap.regs[JOB_CONTROL__JS14__CONFIG] = kbdev->reg + 0x1f18; - kbdev->regmap.regs[JOB_CONTROL__JS14__XAFFINITY] = kbdev->reg + 0x1f1c; - kbdev->regmap.regs[JOB_CONTROL__JS14__COMMAND] = kbdev->reg + 0x1f20; - kbdev->regmap.regs[JOB_CONTROL__JS14__STATUS] = kbdev->reg + 0x1f24; - kbdev->regmap.regs[JOB_CONTROL__JS14__FLUSH_ID] = kbdev->reg + 0x1f30; - kbdev->regmap.regs[JOB_CONTROL__JS14__EVENT_0] = kbdev->reg + 0x1f34; - kbdev->regmap.regs[JOB_CONTROL__JS14__EVENT_1] = kbdev->reg + 0x1f38; - kbdev->regmap.regs[JOB_CONTROL__JS14__EVENT_MASK] = kbdev->reg + 0x1f3c; - kbdev->regmap.regs[JOB_CONTROL__JS14__HEAD_NEXT] = kbdev->reg + 0x1f40; - kbdev->regmap.regs[JOB_CONTROL__JS14__TAIL_NEXT] = kbdev->reg + 0x1f48; - kbdev->regmap.regs[JOB_CONTROL__JS14__AFFINITY_NEXT] = kbdev->reg + 0x1f50; - kbdev->regmap.regs[JOB_CONTROL__JS14__CONFIG_NEXT] = kbdev->reg + 0x1f58; - kbdev->regmap.regs[JOB_CONTROL__JS14__XAFFINITY_NEXT] = kbdev->reg + 0x1f5c; - kbdev->regmap.regs[JOB_CONTROL__JS14__COMMAND_NEXT] = kbdev->reg + 0x1f60; - kbdev->regmap.regs[JOB_CONTROL__JS14__FLUSH_ID_NEXT] = kbdev->reg + 0x1f70; - kbdev->regmap.regs[JOB_CONTROL__JS14__EVENT_MASK_NEXT] = kbdev->reg + 0x1f7c; - kbdev->regmap.regs[JOB_CONTROL__JS15__HEAD] = kbdev->reg + 0x1f80; - kbdev->regmap.regs[JOB_CONTROL__JS15__TAIL] = kbdev->reg + 0x1f88; - kbdev->regmap.regs[JOB_CONTROL__JS15__AFFINITY] = kbdev->reg + 0x1f90; - kbdev->regmap.regs[JOB_CONTROL__JS15__CONFIG] = kbdev->reg + 0x1f98; - kbdev->regmap.regs[JOB_CONTROL__JS15__XAFFINITY] = kbdev->reg + 0x1f9c; - kbdev->regmap.regs[JOB_CONTROL__JS15__COMMAND] = kbdev->reg + 0x1fa0; - kbdev->regmap.regs[JOB_CONTROL__JS15__STATUS] = kbdev->reg + 0x1fa4; - kbdev->regmap.regs[JOB_CONTROL__JS15__FLUSH_ID] = kbdev->reg + 0x1fb0; - kbdev->regmap.regs[JOB_CONTROL__JS15__EVENT_0] = kbdev->reg + 0x1fb4; - kbdev->regmap.regs[JOB_CONTROL__JS15__EVENT_1] = kbdev->reg + 0x1fb8; - kbdev->regmap.regs[JOB_CONTROL__JS15__EVENT_MASK] = kbdev->reg + 0x1fbc; - kbdev->regmap.regs[JOB_CONTROL__JS15__HEAD_NEXT] = kbdev->reg + 0x1fc0; - kbdev->regmap.regs[JOB_CONTROL__JS15__TAIL_NEXT] = kbdev->reg + 0x1fc8; - kbdev->regmap.regs[JOB_CONTROL__JS15__AFFINITY_NEXT] = kbdev->reg + 0x1fd0; - kbdev->regmap.regs[JOB_CONTROL__JS15__CONFIG_NEXT] = kbdev->reg + 0x1fd8; - kbdev->regmap.regs[JOB_CONTROL__JS15__XAFFINITY_NEXT] = kbdev->reg + 0x1fdc; - kbdev->regmap.regs[JOB_CONTROL__JS15__COMMAND_NEXT] = kbdev->reg + 0x1fe0; - kbdev->regmap.regs[JOB_CONTROL__JS15__FLUSH_ID_NEXT] = kbdev->reg + 0x1ff0; - kbdev->regmap.regs[JOB_CONTROL__JS15__EVENT_MASK_NEXT] = kbdev->reg + 0x1ffc; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__IRQ_RAWSTAT] = kbdev->reg + 0x2000; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__IRQ_CLEAR] = kbdev->reg + 0x2004; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__IRQ_MASK] = kbdev->reg + 0x2008; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__IRQ_STATUS] = kbdev->reg + 0x200c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__TRANSTAB] = kbdev->reg + 0x2400; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__MEMATTR] = kbdev->reg + 0x2408; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__LOCKADDR] = kbdev->reg + 0x2410; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__COMMAND] = kbdev->reg + 0x2418; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__FAULTSTATUS] = kbdev->reg + 0x241c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__FAULTADDRESS] = kbdev->reg + 0x2420; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__STATUS] = kbdev->reg + 0x2428; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__TRANSCFG] = kbdev->reg + 0x2430; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS0__FAULTEXTRA] = kbdev->reg + 0x2438; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__TRANSTAB] = kbdev->reg + 0x2440; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__MEMATTR] = kbdev->reg + 0x2448; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__LOCKADDR] = kbdev->reg + 0x2450; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__COMMAND] = kbdev->reg + 0x2458; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__FAULTSTATUS] = kbdev->reg + 0x245c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__FAULTADDRESS] = kbdev->reg + 0x2460; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__STATUS] = kbdev->reg + 0x2468; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__TRANSCFG] = kbdev->reg + 0x2470; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS1__FAULTEXTRA] = kbdev->reg + 0x2478; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__TRANSTAB] = kbdev->reg + 0x2480; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__MEMATTR] = kbdev->reg + 0x2488; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__LOCKADDR] = kbdev->reg + 0x2490; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__COMMAND] = kbdev->reg + 0x2498; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__FAULTSTATUS] = kbdev->reg + 0x249c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__FAULTADDRESS] = kbdev->reg + 0x24a0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__STATUS] = kbdev->reg + 0x24a8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__TRANSCFG] = kbdev->reg + 0x24b0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS2__FAULTEXTRA] = kbdev->reg + 0x24b8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__TRANSTAB] = kbdev->reg + 0x24c0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__MEMATTR] = kbdev->reg + 0x24c8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__LOCKADDR] = kbdev->reg + 0x24d0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__COMMAND] = kbdev->reg + 0x24d8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__FAULTSTATUS] = kbdev->reg + 0x24dc; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__FAULTADDRESS] = kbdev->reg + 0x24e0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__STATUS] = kbdev->reg + 0x24e8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__TRANSCFG] = kbdev->reg + 0x24f0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS3__FAULTEXTRA] = kbdev->reg + 0x24f8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__TRANSTAB] = kbdev->reg + 0x2500; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__MEMATTR] = kbdev->reg + 0x2508; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__LOCKADDR] = kbdev->reg + 0x2510; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__COMMAND] = kbdev->reg + 0x2518; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__FAULTSTATUS] = kbdev->reg + 0x251c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__FAULTADDRESS] = kbdev->reg + 0x2520; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__STATUS] = kbdev->reg + 0x2528; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__TRANSCFG] = kbdev->reg + 0x2530; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS4__FAULTEXTRA] = kbdev->reg + 0x2538; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__TRANSTAB] = kbdev->reg + 0x2540; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__MEMATTR] = kbdev->reg + 0x2548; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__LOCKADDR] = kbdev->reg + 0x2550; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__COMMAND] = kbdev->reg + 0x2558; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__FAULTSTATUS] = kbdev->reg + 0x255c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__FAULTADDRESS] = kbdev->reg + 0x2560; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__STATUS] = kbdev->reg + 0x2568; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__TRANSCFG] = kbdev->reg + 0x2570; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS5__FAULTEXTRA] = kbdev->reg + 0x2578; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__TRANSTAB] = kbdev->reg + 0x2580; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__MEMATTR] = kbdev->reg + 0x2588; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__LOCKADDR] = kbdev->reg + 0x2590; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__COMMAND] = kbdev->reg + 0x2598; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__FAULTSTATUS] = kbdev->reg + 0x259c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__FAULTADDRESS] = kbdev->reg + 0x25a0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__STATUS] = kbdev->reg + 0x25a8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__TRANSCFG] = kbdev->reg + 0x25b0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS6__FAULTEXTRA] = kbdev->reg + 0x25b8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__TRANSTAB] = kbdev->reg + 0x25c0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__MEMATTR] = kbdev->reg + 0x25c8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__LOCKADDR] = kbdev->reg + 0x25d0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__COMMAND] = kbdev->reg + 0x25d8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__FAULTSTATUS] = kbdev->reg + 0x25dc; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__FAULTADDRESS] = kbdev->reg + 0x25e0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__STATUS] = kbdev->reg + 0x25e8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__TRANSCFG] = kbdev->reg + 0x25f0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS7__FAULTEXTRA] = kbdev->reg + 0x25f8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__TRANSTAB] = kbdev->reg + 0x2600; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__MEMATTR] = kbdev->reg + 0x2608; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__LOCKADDR] = kbdev->reg + 0x2610; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__COMMAND] = kbdev->reg + 0x2618; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__FAULTSTATUS] = kbdev->reg + 0x261c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__FAULTADDRESS] = kbdev->reg + 0x2620; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__STATUS] = kbdev->reg + 0x2628; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__TRANSCFG] = kbdev->reg + 0x2630; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS8__FAULTEXTRA] = kbdev->reg + 0x2638; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__TRANSTAB] = kbdev->reg + 0x2640; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__MEMATTR] = kbdev->reg + 0x2648; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__LOCKADDR] = kbdev->reg + 0x2650; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__COMMAND] = kbdev->reg + 0x2658; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__FAULTSTATUS] = kbdev->reg + 0x265c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__FAULTADDRESS] = kbdev->reg + 0x2660; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__STATUS] = kbdev->reg + 0x2668; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__TRANSCFG] = kbdev->reg + 0x2670; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS9__FAULTEXTRA] = kbdev->reg + 0x2678; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__TRANSTAB] = kbdev->reg + 0x2680; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__MEMATTR] = kbdev->reg + 0x2688; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__LOCKADDR] = kbdev->reg + 0x2690; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__COMMAND] = kbdev->reg + 0x2698; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__FAULTSTATUS] = kbdev->reg + 0x269c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__FAULTADDRESS] = kbdev->reg + 0x26a0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__STATUS] = kbdev->reg + 0x26a8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__TRANSCFG] = kbdev->reg + 0x26b0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS10__FAULTEXTRA] = kbdev->reg + 0x26b8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__TRANSTAB] = kbdev->reg + 0x26c0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__MEMATTR] = kbdev->reg + 0x26c8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__LOCKADDR] = kbdev->reg + 0x26d0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__COMMAND] = kbdev->reg + 0x26d8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__FAULTSTATUS] = kbdev->reg + 0x26dc; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__FAULTADDRESS] = kbdev->reg + 0x26e0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__STATUS] = kbdev->reg + 0x26e8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__TRANSCFG] = kbdev->reg + 0x26f0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS11__FAULTEXTRA] = kbdev->reg + 0x26f8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__TRANSTAB] = kbdev->reg + 0x2700; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__MEMATTR] = kbdev->reg + 0x2708; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__LOCKADDR] = kbdev->reg + 0x2710; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__COMMAND] = kbdev->reg + 0x2718; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__FAULTSTATUS] = kbdev->reg + 0x271c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__FAULTADDRESS] = kbdev->reg + 0x2720; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__STATUS] = kbdev->reg + 0x2728; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__TRANSCFG] = kbdev->reg + 0x2730; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS12__FAULTEXTRA] = kbdev->reg + 0x2738; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__TRANSTAB] = kbdev->reg + 0x2740; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__MEMATTR] = kbdev->reg + 0x2748; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__LOCKADDR] = kbdev->reg + 0x2750; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__COMMAND] = kbdev->reg + 0x2758; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__FAULTSTATUS] = kbdev->reg + 0x275c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__FAULTADDRESS] = kbdev->reg + 0x2760; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__STATUS] = kbdev->reg + 0x2768; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__TRANSCFG] = kbdev->reg + 0x2770; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS13__FAULTEXTRA] = kbdev->reg + 0x2778; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__TRANSTAB] = kbdev->reg + 0x2780; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__MEMATTR] = kbdev->reg + 0x2788; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__LOCKADDR] = kbdev->reg + 0x2790; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__COMMAND] = kbdev->reg + 0x2798; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__FAULTSTATUS] = kbdev->reg + 0x279c; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__FAULTADDRESS] = kbdev->reg + 0x27a0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__STATUS] = kbdev->reg + 0x27a8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__TRANSCFG] = kbdev->reg + 0x27b0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS14__FAULTEXTRA] = kbdev->reg + 0x27b8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__TRANSTAB] = kbdev->reg + 0x27c0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__MEMATTR] = kbdev->reg + 0x27c8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__LOCKADDR] = kbdev->reg + 0x27d0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__COMMAND] = kbdev->reg + 0x27d8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__FAULTSTATUS] = kbdev->reg + 0x27dc; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__FAULTADDRESS] = kbdev->reg + 0x27e0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__STATUS] = kbdev->reg + 0x27e8; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__TRANSCFG] = kbdev->reg + 0x27f0; - kbdev->regmap.regs[MMU_STAGE1__ST1MMU__AS15__FAULTEXTRA] = kbdev->reg + 0x27f8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__IRQ_RAWSTAT] = kbdev->reg + 0x10000; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__IRQ_CLEAR] = kbdev->reg + 0x10004; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__IRQ_MASK] = kbdev->reg + 0x10008; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__IRQ_STATUS] = kbdev->reg + 0x1000c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__TRANSTAB] = kbdev->reg + 0x10400; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__MEMATTR] = kbdev->reg + 0x10408; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__LOCKADDR] = kbdev->reg + 0x10410; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__COMMAND] = kbdev->reg + 0x10418; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__FAULTSTATUS] = kbdev->reg + 0x1041c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__FAULTADDRESS] = kbdev->reg + 0x10420; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__STATUS] = kbdev->reg + 0x10428; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__TRANSCFG] = kbdev->reg + 0x10430; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS0__FAULTEXTRA] = kbdev->reg + 0x10438; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__TRANSTAB] = kbdev->reg + 0x10440; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__MEMATTR] = kbdev->reg + 0x10448; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__LOCKADDR] = kbdev->reg + 0x10450; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__COMMAND] = kbdev->reg + 0x10458; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__FAULTSTATUS] = kbdev->reg + 0x1045c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__FAULTADDRESS] = kbdev->reg + 0x10460; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__STATUS] = kbdev->reg + 0x10468; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__TRANSCFG] = kbdev->reg + 0x10470; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS1__FAULTEXTRA] = kbdev->reg + 0x10478; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__TRANSTAB] = kbdev->reg + 0x10480; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__MEMATTR] = kbdev->reg + 0x10488; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__LOCKADDR] = kbdev->reg + 0x10490; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__COMMAND] = kbdev->reg + 0x10498; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__FAULTSTATUS] = kbdev->reg + 0x1049c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__FAULTADDRESS] = kbdev->reg + 0x104a0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__STATUS] = kbdev->reg + 0x104a8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__TRANSCFG] = kbdev->reg + 0x104b0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS2__FAULTEXTRA] = kbdev->reg + 0x104b8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__TRANSTAB] = kbdev->reg + 0x104c0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__MEMATTR] = kbdev->reg + 0x104c8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__LOCKADDR] = kbdev->reg + 0x104d0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__COMMAND] = kbdev->reg + 0x104d8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__FAULTSTATUS] = kbdev->reg + 0x104dc; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__FAULTADDRESS] = kbdev->reg + 0x104e0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__STATUS] = kbdev->reg + 0x104e8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__TRANSCFG] = kbdev->reg + 0x104f0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS3__FAULTEXTRA] = kbdev->reg + 0x104f8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__TRANSTAB] = kbdev->reg + 0x10500; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__MEMATTR] = kbdev->reg + 0x10508; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__LOCKADDR] = kbdev->reg + 0x10510; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__COMMAND] = kbdev->reg + 0x10518; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__FAULTSTATUS] = kbdev->reg + 0x1051c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__FAULTADDRESS] = kbdev->reg + 0x10520; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__STATUS] = kbdev->reg + 0x10528; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__TRANSCFG] = kbdev->reg + 0x10530; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS4__FAULTEXTRA] = kbdev->reg + 0x10538; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__TRANSTAB] = kbdev->reg + 0x10540; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__MEMATTR] = kbdev->reg + 0x10548; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__LOCKADDR] = kbdev->reg + 0x10550; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__COMMAND] = kbdev->reg + 0x10558; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__FAULTSTATUS] = kbdev->reg + 0x1055c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__FAULTADDRESS] = kbdev->reg + 0x10560; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__STATUS] = kbdev->reg + 0x10568; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__TRANSCFG] = kbdev->reg + 0x10570; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS5__FAULTEXTRA] = kbdev->reg + 0x10578; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__TRANSTAB] = kbdev->reg + 0x10580; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__MEMATTR] = kbdev->reg + 0x10588; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__LOCKADDR] = kbdev->reg + 0x10590; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__COMMAND] = kbdev->reg + 0x10598; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__FAULTSTATUS] = kbdev->reg + 0x1059c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__FAULTADDRESS] = kbdev->reg + 0x105a0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__STATUS] = kbdev->reg + 0x105a8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__TRANSCFG] = kbdev->reg + 0x105b0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS6__FAULTEXTRA] = kbdev->reg + 0x105b8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__TRANSTAB] = kbdev->reg + 0x105c0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__MEMATTR] = kbdev->reg + 0x105c8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__LOCKADDR] = kbdev->reg + 0x105d0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__COMMAND] = kbdev->reg + 0x105d8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__FAULTSTATUS] = kbdev->reg + 0x105dc; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__FAULTADDRESS] = kbdev->reg + 0x105e0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__STATUS] = kbdev->reg + 0x105e8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__TRANSCFG] = kbdev->reg + 0x105f0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS7__FAULTEXTRA] = kbdev->reg + 0x105f8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__TRANSTAB] = kbdev->reg + 0x10600; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__MEMATTR] = kbdev->reg + 0x10608; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__LOCKADDR] = kbdev->reg + 0x10610; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__COMMAND] = kbdev->reg + 0x10618; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__FAULTSTATUS] = kbdev->reg + 0x1061c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__FAULTADDRESS] = kbdev->reg + 0x10620; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__STATUS] = kbdev->reg + 0x10628; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__TRANSCFG] = kbdev->reg + 0x10630; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS8__FAULTEXTRA] = kbdev->reg + 0x10638; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__TRANSTAB] = kbdev->reg + 0x10640; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__MEMATTR] = kbdev->reg + 0x10648; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__LOCKADDR] = kbdev->reg + 0x10650; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__COMMAND] = kbdev->reg + 0x10658; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__FAULTSTATUS] = kbdev->reg + 0x1065c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__FAULTADDRESS] = kbdev->reg + 0x10660; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__STATUS] = kbdev->reg + 0x10668; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__TRANSCFG] = kbdev->reg + 0x10670; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS9__FAULTEXTRA] = kbdev->reg + 0x10678; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__TRANSTAB] = kbdev->reg + 0x10680; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__MEMATTR] = kbdev->reg + 0x10688; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__LOCKADDR] = kbdev->reg + 0x10690; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__COMMAND] = kbdev->reg + 0x10698; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__FAULTSTATUS] = kbdev->reg + 0x1069c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__FAULTADDRESS] = kbdev->reg + 0x106a0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__STATUS] = kbdev->reg + 0x106a8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__TRANSCFG] = kbdev->reg + 0x106b0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS10__FAULTEXTRA] = kbdev->reg + 0x106b8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__TRANSTAB] = kbdev->reg + 0x106c0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__MEMATTR] = kbdev->reg + 0x106c8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__LOCKADDR] = kbdev->reg + 0x106d0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__COMMAND] = kbdev->reg + 0x106d8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__FAULTSTATUS] = kbdev->reg + 0x106dc; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__FAULTADDRESS] = kbdev->reg + 0x106e0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__STATUS] = kbdev->reg + 0x106e8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__TRANSCFG] = kbdev->reg + 0x106f0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS11__FAULTEXTRA] = kbdev->reg + 0x106f8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__TRANSTAB] = kbdev->reg + 0x10700; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__MEMATTR] = kbdev->reg + 0x10708; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__LOCKADDR] = kbdev->reg + 0x10710; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__COMMAND] = kbdev->reg + 0x10718; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__FAULTSTATUS] = kbdev->reg + 0x1071c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__FAULTADDRESS] = kbdev->reg + 0x10720; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__STATUS] = kbdev->reg + 0x10728; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__TRANSCFG] = kbdev->reg + 0x10730; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS12__FAULTEXTRA] = kbdev->reg + 0x10738; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__TRANSTAB] = kbdev->reg + 0x10740; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__MEMATTR] = kbdev->reg + 0x10748; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__LOCKADDR] = kbdev->reg + 0x10750; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__COMMAND] = kbdev->reg + 0x10758; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__FAULTSTATUS] = kbdev->reg + 0x1075c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__FAULTADDRESS] = kbdev->reg + 0x10760; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__STATUS] = kbdev->reg + 0x10768; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__TRANSCFG] = kbdev->reg + 0x10770; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS13__FAULTEXTRA] = kbdev->reg + 0x10778; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__TRANSTAB] = kbdev->reg + 0x10780; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__MEMATTR] = kbdev->reg + 0x10788; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__LOCKADDR] = kbdev->reg + 0x10790; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__COMMAND] = kbdev->reg + 0x10798; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__FAULTSTATUS] = kbdev->reg + 0x1079c; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__FAULTADDRESS] = kbdev->reg + 0x107a0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__STATUS] = kbdev->reg + 0x107a8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__TRANSCFG] = kbdev->reg + 0x107b0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS14__FAULTEXTRA] = kbdev->reg + 0x107b8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__TRANSTAB] = kbdev->reg + 0x107c0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__MEMATTR] = kbdev->reg + 0x107c8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__LOCKADDR] = kbdev->reg + 0x107d0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__COMMAND] = kbdev->reg + 0x107d8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__FAULTSTATUS] = kbdev->reg + 0x107dc; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__FAULTADDRESS] = kbdev->reg + 0x107e0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__STATUS] = kbdev->reg + 0x107e8; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__TRANSCFG] = kbdev->reg + 0x107f0; - kbdev->regmap.regs[MMU_STAGE2__ST2MMU__AS15__FAULTEXTRA] = kbdev->reg + 0x107f8; -} - -static void kbase_regmap_v6_2_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V6_2_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v6_0_init(kbdev); - - kbdev->regmap.flags[GPU_CONTROL__REVIDR] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__STACK_PRESENT] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__STACK_PWROFF] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__STACK_PWRON] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[GPU_CONTROL__STACK_PWRTRANS] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__STACK_READY] = KBASE_REGMAP_WIDTH_64_BIT | - KBASE_REGMAP_PERM_READ; - - kbdev->regmap.regs[GPU_CONTROL__REVIDR] = kbdev->reg + 0x280; - kbdev->regmap.regs[GPU_CONTROL__STACK_PRESENT] = kbdev->reg + 0xe00; - kbdev->regmap.regs[GPU_CONTROL__STACK_PWROFF] = kbdev->reg + 0xe30; - kbdev->regmap.regs[GPU_CONTROL__STACK_PWRON] = kbdev->reg + 0xe20; - kbdev->regmap.regs[GPU_CONTROL__STACK_PWRTRANS] = kbdev->reg + 0xe40; - kbdev->regmap.regs[GPU_CONTROL__STACK_READY] = kbdev->reg + 0xe10; -} - -static void kbase_regmap_v7_0_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V7_0_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v6_2_init(kbdev); - - kbdev->regmap.flags[GPU_CONTROL__TEXTURE_FEATURES_3] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - - kbdev->regmap.regs[GPU_CONTROL__TEXTURE_FEATURES_3] = kbdev->reg + 0xbc; -} - -static void kbase_regmap_v7_2_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V7_2_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v7_0_init(kbdev); - - kbdev->regmap.flags[GPU_CONTROL__CORE_FEATURES] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[GPU_CONTROL__THREAD_TLS_ALLOC] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - - kbdev->regmap.regs[GPU_CONTROL__CORE_FEATURES] = kbdev->reg + 0x8; - kbdev->regmap.regs[GPU_CONTROL__THREAD_TLS_ALLOC] = kbdev->reg + 0x310; -} - -static void kbase_regmap_v9_0_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V9_0_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v7_2_init(kbdev); - - kbdev->regmap.flags[GPU_CONTROL__CORE_FEATURES] = 0; - kbdev->regmap.flags[GPU_CONTROL__THREAD_TLS_ALLOC] = 0; - kbdev->regmap.flags[JOB_CONTROL__JOB_IRQ_THROTTLE] = 0; - - kbdev->regmap.regs[GPU_CONTROL__CORE_FEATURES] = NULL; - kbdev->regmap.regs[GPU_CONTROL__THREAD_TLS_ALLOC] = NULL; - kbdev->regmap.regs[JOB_CONTROL__JOB_IRQ_THROTTLE] = NULL; -} - -static void kbase_regmap_v9_2_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V9_2_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v9_0_init(kbdev); - - kbdev->regmap.flags[GPU_CONTROL__L2_CONFIG] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - - kbdev->regmap.regs[GPU_CONTROL__L2_CONFIG] = kbdev->reg + 0x48; -} - -static void kbase_regmap_v9_14_init(struct kbase_device *kbdev) -{ - if (kbdev->regmap.regs == NULL && kbdev->regmap.flags == NULL) { - kbdev->regmap.size = NR_V9_14_REGS; - kbdev->regmap.regs = - kcalloc(kbdev->regmap.size, sizeof(void __iomem *), GFP_KERNEL); - kbdev->regmap.flags = kcalloc(kbdev->regmap.size, sizeof(u32), GFP_KERNEL); - } - - if (WARN_ON(kbdev->regmap.regs == NULL)) - return; - if (WARN_ON(kbdev->regmap.flags == NULL)) - return; - - kbase_regmap_v9_2_init(kbdev); - - kbdev->regmap.flags[PTM_AW_IRQ_CLEAR] = KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[PTM_AW_IRQ_INJECTION] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[PTM_AW_IRQ_MASK] = KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | - KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[PTM_AW_IRQ_RAWSTAT] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[PTM_AW_IRQ_STATUS] = KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1] = KBASE_REGMAP_WIDTH_32_BIT | - KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ | KBASE_REGMAP_PERM_WRITE; - kbdev->regmap.flags[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS] = - KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ; - kbdev->regmap.flags[PTM_ID] = KBASE_REGMAP_WIDTH_32_BIT | KBASE_REGMAP_PERM_READ; - - kbdev->regmap.regs[PTM_AW_IRQ_CLEAR] = kbdev->reg + 0x1ffc8; - kbdev->regmap.regs[PTM_AW_IRQ_INJECTION] = kbdev->reg + 0x1ffd4; - kbdev->regmap.regs[PTM_AW_IRQ_MASK] = kbdev->reg + 0x1ffcc; - kbdev->regmap.regs[PTM_AW_IRQ_RAWSTAT] = kbdev->reg + 0x1ffc4; - kbdev->regmap.regs[PTM_AW_IRQ_STATUS] = kbdev->reg + 0x1ffd0; - kbdev->regmap.regs[PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0] = kbdev->reg + 0x1ffd8; - kbdev->regmap.regs[PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1] = kbdev->reg + 0x1ffdc; - kbdev->regmap.regs[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0] = kbdev->reg + 0x1ffe4; - kbdev->regmap.regs[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1] = kbdev->reg + 0x1ffe8; - kbdev->regmap.regs[PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS] = kbdev->reg + 0x1ffe0; - kbdev->regmap.regs[PTM_ID] = kbdev->reg + 0x1ffc0; -} - -u32 kbase_regmap_backend_init(struct kbase_device *kbdev) -{ - int i = 0; - - struct { - u32 arch_id; - void (*init)(struct kbase_device *kbdev); - } init_array[] = { - { GPU_ID_ARCH_MAKE(6, 0, 0), kbase_regmap_v6_0_init }, - { GPU_ID_ARCH_MAKE(6, 2, 0), kbase_regmap_v6_2_init }, - { GPU_ID_ARCH_MAKE(7, 0, 0), kbase_regmap_v7_0_init }, - { GPU_ID_ARCH_MAKE(7, 2, 0), kbase_regmap_v7_2_init }, - { GPU_ID_ARCH_MAKE(9, 0, 0), kbase_regmap_v9_0_init }, - { GPU_ID_ARCH_MAKE(9, 2, 0), kbase_regmap_v9_2_init }, - { GPU_ID_ARCH_MAKE(9, 14, 0), kbase_regmap_v9_14_init }, - }; - - for (i = 0; i < ARRAY_SIZE(init_array) - 1; i++) { - if (kbdev->gpu_props.gpu_id.arch_id < init_array[i + 1].arch_id) { - init_array[i].init(kbdev); - return init_array[i].arch_id; - } - } - - /* arch_id greater than last entry in init_array */ - init_array[i].init(kbdev); - return init_array[i].arch_id; -} - -#ifdef CONFIG_MALI_VALHALL_DEBUG -static char *enum_strings[] = { - [GPU_CONTROL__GPU_ID] = "GPU_CONTROL__GPU_ID", - [GPU_CONTROL__L2_FEATURES] = "GPU_CONTROL__L2_FEATURES", - [GPU_CONTROL__TILER_FEATURES] = "GPU_CONTROL__TILER_FEATURES", - [GPU_CONTROL__MEM_FEATURES] = "GPU_CONTROL__MEM_FEATURES", - [GPU_CONTROL__MMU_FEATURES] = "GPU_CONTROL__MMU_FEATURES", - [GPU_CONTROL__AS_PRESENT] = "GPU_CONTROL__AS_PRESENT", - [GPU_CONTROL__JS_PRESENT] = "GPU_CONTROL__JS_PRESENT", - [GPU_CONTROL__GPU_IRQ_RAWSTAT] = "GPU_CONTROL__GPU_IRQ_RAWSTAT", - [GPU_CONTROL__GPU_IRQ_CLEAR] = "GPU_CONTROL__GPU_IRQ_CLEAR", - [GPU_CONTROL__GPU_IRQ_MASK] = "GPU_CONTROL__GPU_IRQ_MASK", - [GPU_CONTROL__GPU_IRQ_STATUS] = "GPU_CONTROL__GPU_IRQ_STATUS", - [GPU_CONTROL__GPU_COMMAND] = "GPU_CONTROL__GPU_COMMAND", - [GPU_CONTROL__GPU_STATUS] = "GPU_CONTROL__GPU_STATUS", - [GPU_CONTROL__LATEST_FLUSH] = "GPU_CONTROL__LATEST_FLUSH", - [GPU_CONTROL__GPU_FAULTSTATUS] = "GPU_CONTROL__GPU_FAULTSTATUS", - [GPU_CONTROL__GPU_FAULTADDRESS] = "GPU_CONTROL__GPU_FAULTADDRESS", - [GPU_CONTROL__AFBC_FEATURES] = "GPU_CONTROL__AFBC_FEATURES", - [GPU_CONTROL__PWR_KEY] = "GPU_CONTROL__PWR_KEY", - [GPU_CONTROL__PWR_OVERRIDE0] = "GPU_CONTROL__PWR_OVERRIDE0", - [GPU_CONTROL__PWR_OVERRIDE1] = "GPU_CONTROL__PWR_OVERRIDE1", - [GPU_CONTROL__PRFCNT_BASE] = "GPU_CONTROL__PRFCNT_BASE", - [GPU_CONTROL__PRFCNT_CONFIG] = "GPU_CONTROL__PRFCNT_CONFIG", - [GPU_CONTROL__PRFCNT_JM_EN] = "GPU_CONTROL__PRFCNT_JM_EN", - [GPU_CONTROL__PRFCNT_SHADER_EN] = "GPU_CONTROL__PRFCNT_SHADER_EN", - [GPU_CONTROL__PRFCNT_TILER_EN] = "GPU_CONTROL__PRFCNT_TILER_EN", - [GPU_CONTROL__PRFCNT_MMU_L2_EN] = "GPU_CONTROL__PRFCNT_MMU_L2_EN", - [GPU_CONTROL__CYCLE_COUNT] = "GPU_CONTROL__CYCLE_COUNT", - [GPU_CONTROL__TIMESTAMP] = "GPU_CONTROL__TIMESTAMP", - [GPU_CONTROL__THREAD_MAX_THREADS] = "GPU_CONTROL__THREAD_MAX_THREADS", - [GPU_CONTROL__THREAD_MAX_WORKGROUP_SIZE] = "GPU_CONTROL__THREAD_MAX_WORKGROUP_SIZE", - [GPU_CONTROL__THREAD_MAX_BARRIER_SIZE] = "GPU_CONTROL__THREAD_MAX_BARRIER_SIZE", - [GPU_CONTROL__THREAD_FEATURES] = "GPU_CONTROL__THREAD_FEATURES", - [GPU_CONTROL__TEXTURE_FEATURES_0] = "GPU_CONTROL__TEXTURE_FEATURES_0", - [GPU_CONTROL__TEXTURE_FEATURES_1] = "GPU_CONTROL__TEXTURE_FEATURES_1", - [GPU_CONTROL__TEXTURE_FEATURES_2] = "GPU_CONTROL__TEXTURE_FEATURES_2", - [GPU_CONTROL__JS0_FEATURES] = "GPU_CONTROL__JS0_FEATURES", - [GPU_CONTROL__JS1_FEATURES] = "GPU_CONTROL__JS1_FEATURES", - [GPU_CONTROL__JS2_FEATURES] = "GPU_CONTROL__JS2_FEATURES", - [GPU_CONTROL__JS3_FEATURES] = "GPU_CONTROL__JS3_FEATURES", - [GPU_CONTROL__JS4_FEATURES] = "GPU_CONTROL__JS4_FEATURES", - [GPU_CONTROL__JS5_FEATURES] = "GPU_CONTROL__JS5_FEATURES", - [GPU_CONTROL__JS6_FEATURES] = "GPU_CONTROL__JS6_FEATURES", - [GPU_CONTROL__JS7_FEATURES] = "GPU_CONTROL__JS7_FEATURES", - [GPU_CONTROL__JS8_FEATURES] = "GPU_CONTROL__JS8_FEATURES", - [GPU_CONTROL__JS9_FEATURES] = "GPU_CONTROL__JS9_FEATURES", - [GPU_CONTROL__JS10_FEATURES] = "GPU_CONTROL__JS10_FEATURES", - [GPU_CONTROL__JS11_FEATURES] = "GPU_CONTROL__JS11_FEATURES", - [GPU_CONTROL__JS12_FEATURES] = "GPU_CONTROL__JS12_FEATURES", - [GPU_CONTROL__JS13_FEATURES] = "GPU_CONTROL__JS13_FEATURES", - [GPU_CONTROL__JS14_FEATURES] = "GPU_CONTROL__JS14_FEATURES", - [GPU_CONTROL__JS15_FEATURES] = "GPU_CONTROL__JS15_FEATURES", - [GPU_CONTROL__SHADER_PRESENT] = "GPU_CONTROL__SHADER_PRESENT", - [GPU_CONTROL__TILER_PRESENT] = "GPU_CONTROL__TILER_PRESENT", - [GPU_CONTROL__L2_PRESENT] = "GPU_CONTROL__L2_PRESENT", - [GPU_CONTROL__SHADER_READY] = "GPU_CONTROL__SHADER_READY", - [GPU_CONTROL__TILER_READY] = "GPU_CONTROL__TILER_READY", - [GPU_CONTROL__L2_READY] = "GPU_CONTROL__L2_READY", - [GPU_CONTROL__SHADER_PWRON] = "GPU_CONTROL__SHADER_PWRON", - [GPU_CONTROL__TILER_PWRON] = "GPU_CONTROL__TILER_PWRON", - [GPU_CONTROL__L2_PWRON] = "GPU_CONTROL__L2_PWRON", - [GPU_CONTROL__SHADER_PWROFF] = "GPU_CONTROL__SHADER_PWROFF", - [GPU_CONTROL__TILER_PWROFF] = "GPU_CONTROL__TILER_PWROFF", - [GPU_CONTROL__L2_PWROFF] = "GPU_CONTROL__L2_PWROFF", - [GPU_CONTROL__SHADER_PWRTRANS] = "GPU_CONTROL__SHADER_PWRTRANS", - [GPU_CONTROL__TILER_PWRTRANS] = "GPU_CONTROL__TILER_PWRTRANS", - [GPU_CONTROL__L2_PWRTRANS] = "GPU_CONTROL__L2_PWRTRANS", - [GPU_CONTROL__SHADER_PWRACTIVE] = "GPU_CONTROL__SHADER_PWRACTIVE", - [GPU_CONTROL__TILER_PWRACTIVE] = "GPU_CONTROL__TILER_PWRACTIVE", - [GPU_CONTROL__L2_PWRACTIVE] = "GPU_CONTROL__L2_PWRACTIVE", - [GPU_CONTROL__COHERENCY_FEATURES] = "GPU_CONTROL__COHERENCY_FEATURES", - [GPU_CONTROL__COHERENCY_ENABLE] = "GPU_CONTROL__COHERENCY_ENABLE", - [GPU_CONTROL__GPU_USER_INn] = "GPU_CONTROL__GPU_USER_INn", - [GPU_CONTROL__GPU_USER_OUTn] = "GPU_CONTROL__GPU_USER_OUTn", - [GPU_CONTROL__JM_CONFIG] = "GPU_CONTROL__JM_CONFIG", - [GPU_CONTROL__SHADER_CONFIG] = "GPU_CONTROL__SHADER_CONFIG", - [GPU_CONTROL__TILER_CONFIG] = "GPU_CONTROL__TILER_CONFIG", - [GPU_CONTROL__L2_MMU_CONFIG] = "GPU_CONTROL__L2_MMU_CONFIG", - [JOB_CONTROL__JOB_IRQ_RAWSTAT] = "JOB_CONTROL__JOB_IRQ_RAWSTAT", - [JOB_CONTROL__JOB_IRQ_CLEAR] = "JOB_CONTROL__JOB_IRQ_CLEAR", - [JOB_CONTROL__JOB_IRQ_MASK] = "JOB_CONTROL__JOB_IRQ_MASK", - [JOB_CONTROL__JOB_IRQ_STATUS] = "JOB_CONTROL__JOB_IRQ_STATUS", - [JOB_CONTROL__JOB_IRQ_JS_STATE] = "JOB_CONTROL__JOB_IRQ_JS_STATE", - [JOB_CONTROL__JOB_IRQ_THROTTLE] = "JOB_CONTROL__JOB_IRQ_THROTTLE", - [JOB_CONTROL__EVENT_IRQ_RAWSTAT] = "JOB_CONTROL__EVENT_IRQ_RAWSTAT", - [JOB_CONTROL__EVENT_IRQ_CLEAR] = "JOB_CONTROL__EVENT_IRQ_CLEAR", - [JOB_CONTROL__EVENT_IRQ_MASK] = "JOB_CONTROL__EVENT_IRQ_MASK", - [JOB_CONTROL__EVENT_IRQ_STATUS] = "JOB_CONTROL__EVENT_IRQ_STATUS", - [JOB_CONTROL__JS0__HEAD] = "JOB_CONTROL__JS0__HEAD", - [JOB_CONTROL__JS0__TAIL] = "JOB_CONTROL__JS0__TAIL", - [JOB_CONTROL__JS0__AFFINITY] = "JOB_CONTROL__JS0__AFFINITY", - [JOB_CONTROL__JS0__CONFIG] = "JOB_CONTROL__JS0__CONFIG", - [JOB_CONTROL__JS0__XAFFINITY] = "JOB_CONTROL__JS0__XAFFINITY", - [JOB_CONTROL__JS0__COMMAND] = "JOB_CONTROL__JS0__COMMAND", - [JOB_CONTROL__JS0__STATUS] = "JOB_CONTROL__JS0__STATUS", - [JOB_CONTROL__JS0__FLUSH_ID] = "JOB_CONTROL__JS0__FLUSH_ID", - [JOB_CONTROL__JS0__EVENT_0] = "JOB_CONTROL__JS0__EVENT_0", - [JOB_CONTROL__JS0__EVENT_1] = "JOB_CONTROL__JS0__EVENT_1", - [JOB_CONTROL__JS0__EVENT_MASK] = "JOB_CONTROL__JS0__EVENT_MASK", - [JOB_CONTROL__JS0__HEAD_NEXT] = "JOB_CONTROL__JS0__HEAD_NEXT", - [JOB_CONTROL__JS0__TAIL_NEXT] = "JOB_CONTROL__JS0__TAIL_NEXT", - [JOB_CONTROL__JS0__AFFINITY_NEXT] = "JOB_CONTROL__JS0__AFFINITY_NEXT", - [JOB_CONTROL__JS0__CONFIG_NEXT] = "JOB_CONTROL__JS0__CONFIG_NEXT", - [JOB_CONTROL__JS0__XAFFINITY_NEXT] = "JOB_CONTROL__JS0__XAFFINITY_NEXT", - [JOB_CONTROL__JS0__COMMAND_NEXT] = "JOB_CONTROL__JS0__COMMAND_NEXT", - [JOB_CONTROL__JS0__FLUSH_ID_NEXT] = "JOB_CONTROL__JS0__FLUSH_ID_NEXT", - [JOB_CONTROL__JS0__EVENT_MASK_NEXT] = "JOB_CONTROL__JS0__EVENT_MASK_NEXT", - [JOB_CONTROL__JS1__HEAD] = "JOB_CONTROL__JS1__HEAD", - [JOB_CONTROL__JS1__TAIL] = "JOB_CONTROL__JS1__TAIL", - [JOB_CONTROL__JS1__AFFINITY] = "JOB_CONTROL__JS1__AFFINITY", - [JOB_CONTROL__JS1__CONFIG] = "JOB_CONTROL__JS1__CONFIG", - [JOB_CONTROL__JS1__XAFFINITY] = "JOB_CONTROL__JS1__XAFFINITY", - [JOB_CONTROL__JS1__COMMAND] = "JOB_CONTROL__JS1__COMMAND", - [JOB_CONTROL__JS1__STATUS] = "JOB_CONTROL__JS1__STATUS", - [JOB_CONTROL__JS1__FLUSH_ID] = "JOB_CONTROL__JS1__FLUSH_ID", - [JOB_CONTROL__JS1__EVENT_0] = "JOB_CONTROL__JS1__EVENT_0", - [JOB_CONTROL__JS1__EVENT_1] = "JOB_CONTROL__JS1__EVENT_1", - [JOB_CONTROL__JS1__EVENT_MASK] = "JOB_CONTROL__JS1__EVENT_MASK", - [JOB_CONTROL__JS1__HEAD_NEXT] = "JOB_CONTROL__JS1__HEAD_NEXT", - [JOB_CONTROL__JS1__TAIL_NEXT] = "JOB_CONTROL__JS1__TAIL_NEXT", - [JOB_CONTROL__JS1__AFFINITY_NEXT] = "JOB_CONTROL__JS1__AFFINITY_NEXT", - [JOB_CONTROL__JS1__CONFIG_NEXT] = "JOB_CONTROL__JS1__CONFIG_NEXT", - [JOB_CONTROL__JS1__XAFFINITY_NEXT] = "JOB_CONTROL__JS1__XAFFINITY_NEXT", - [JOB_CONTROL__JS1__COMMAND_NEXT] = "JOB_CONTROL__JS1__COMMAND_NEXT", - [JOB_CONTROL__JS1__FLUSH_ID_NEXT] = "JOB_CONTROL__JS1__FLUSH_ID_NEXT", - [JOB_CONTROL__JS1__EVENT_MASK_NEXT] = "JOB_CONTROL__JS1__EVENT_MASK_NEXT", - [JOB_CONTROL__JS2__HEAD] = "JOB_CONTROL__JS2__HEAD", - [JOB_CONTROL__JS2__TAIL] = "JOB_CONTROL__JS2__TAIL", - [JOB_CONTROL__JS2__AFFINITY] = "JOB_CONTROL__JS2__AFFINITY", - [JOB_CONTROL__JS2__CONFIG] = "JOB_CONTROL__JS2__CONFIG", - [JOB_CONTROL__JS2__XAFFINITY] = "JOB_CONTROL__JS2__XAFFINITY", - [JOB_CONTROL__JS2__COMMAND] = "JOB_CONTROL__JS2__COMMAND", - [JOB_CONTROL__JS2__STATUS] = "JOB_CONTROL__JS2__STATUS", - [JOB_CONTROL__JS2__FLUSH_ID] = "JOB_CONTROL__JS2__FLUSH_ID", - [JOB_CONTROL__JS2__EVENT_0] = "JOB_CONTROL__JS2__EVENT_0", - [JOB_CONTROL__JS2__EVENT_1] = "JOB_CONTROL__JS2__EVENT_1", - [JOB_CONTROL__JS2__EVENT_MASK] = "JOB_CONTROL__JS2__EVENT_MASK", - [JOB_CONTROL__JS2__HEAD_NEXT] = "JOB_CONTROL__JS2__HEAD_NEXT", - [JOB_CONTROL__JS2__TAIL_NEXT] = "JOB_CONTROL__JS2__TAIL_NEXT", - [JOB_CONTROL__JS2__AFFINITY_NEXT] = "JOB_CONTROL__JS2__AFFINITY_NEXT", - [JOB_CONTROL__JS2__CONFIG_NEXT] = "JOB_CONTROL__JS2__CONFIG_NEXT", - [JOB_CONTROL__JS2__XAFFINITY_NEXT] = "JOB_CONTROL__JS2__XAFFINITY_NEXT", - [JOB_CONTROL__JS2__COMMAND_NEXT] = "JOB_CONTROL__JS2__COMMAND_NEXT", - [JOB_CONTROL__JS2__FLUSH_ID_NEXT] = "JOB_CONTROL__JS2__FLUSH_ID_NEXT", - [JOB_CONTROL__JS2__EVENT_MASK_NEXT] = "JOB_CONTROL__JS2__EVENT_MASK_NEXT", - [JOB_CONTROL__JS3__HEAD] = "JOB_CONTROL__JS3__HEAD", - [JOB_CONTROL__JS3__TAIL] = "JOB_CONTROL__JS3__TAIL", - [JOB_CONTROL__JS3__AFFINITY] = "JOB_CONTROL__JS3__AFFINITY", - [JOB_CONTROL__JS3__CONFIG] = "JOB_CONTROL__JS3__CONFIG", - [JOB_CONTROL__JS3__XAFFINITY] = "JOB_CONTROL__JS3__XAFFINITY", - [JOB_CONTROL__JS3__COMMAND] = "JOB_CONTROL__JS3__COMMAND", - [JOB_CONTROL__JS3__STATUS] = "JOB_CONTROL__JS3__STATUS", - [JOB_CONTROL__JS3__FLUSH_ID] = "JOB_CONTROL__JS3__FLUSH_ID", - [JOB_CONTROL__JS3__EVENT_0] = "JOB_CONTROL__JS3__EVENT_0", - [JOB_CONTROL__JS3__EVENT_1] = "JOB_CONTROL__JS3__EVENT_1", - [JOB_CONTROL__JS3__EVENT_MASK] = "JOB_CONTROL__JS3__EVENT_MASK", - [JOB_CONTROL__JS3__HEAD_NEXT] = "JOB_CONTROL__JS3__HEAD_NEXT", - [JOB_CONTROL__JS3__TAIL_NEXT] = "JOB_CONTROL__JS3__TAIL_NEXT", - [JOB_CONTROL__JS3__AFFINITY_NEXT] = "JOB_CONTROL__JS3__AFFINITY_NEXT", - [JOB_CONTROL__JS3__CONFIG_NEXT] = "JOB_CONTROL__JS3__CONFIG_NEXT", - [JOB_CONTROL__JS3__XAFFINITY_NEXT] = "JOB_CONTROL__JS3__XAFFINITY_NEXT", - [JOB_CONTROL__JS3__COMMAND_NEXT] = "JOB_CONTROL__JS3__COMMAND_NEXT", - [JOB_CONTROL__JS3__FLUSH_ID_NEXT] = "JOB_CONTROL__JS3__FLUSH_ID_NEXT", - [JOB_CONTROL__JS3__EVENT_MASK_NEXT] = "JOB_CONTROL__JS3__EVENT_MASK_NEXT", - [JOB_CONTROL__JS4__HEAD] = "JOB_CONTROL__JS4__HEAD", - [JOB_CONTROL__JS4__TAIL] = "JOB_CONTROL__JS4__TAIL", - [JOB_CONTROL__JS4__AFFINITY] = "JOB_CONTROL__JS4__AFFINITY", - [JOB_CONTROL__JS4__CONFIG] = "JOB_CONTROL__JS4__CONFIG", - [JOB_CONTROL__JS4__XAFFINITY] = "JOB_CONTROL__JS4__XAFFINITY", - [JOB_CONTROL__JS4__COMMAND] = "JOB_CONTROL__JS4__COMMAND", - [JOB_CONTROL__JS4__STATUS] = "JOB_CONTROL__JS4__STATUS", - [JOB_CONTROL__JS4__FLUSH_ID] = "JOB_CONTROL__JS4__FLUSH_ID", - [JOB_CONTROL__JS4__EVENT_0] = "JOB_CONTROL__JS4__EVENT_0", - [JOB_CONTROL__JS4__EVENT_1] = "JOB_CONTROL__JS4__EVENT_1", - [JOB_CONTROL__JS4__EVENT_MASK] = "JOB_CONTROL__JS4__EVENT_MASK", - [JOB_CONTROL__JS4__HEAD_NEXT] = "JOB_CONTROL__JS4__HEAD_NEXT", - [JOB_CONTROL__JS4__TAIL_NEXT] = "JOB_CONTROL__JS4__TAIL_NEXT", - [JOB_CONTROL__JS4__AFFINITY_NEXT] = "JOB_CONTROL__JS4__AFFINITY_NEXT", - [JOB_CONTROL__JS4__CONFIG_NEXT] = "JOB_CONTROL__JS4__CONFIG_NEXT", - [JOB_CONTROL__JS4__XAFFINITY_NEXT] = "JOB_CONTROL__JS4__XAFFINITY_NEXT", - [JOB_CONTROL__JS4__COMMAND_NEXT] = "JOB_CONTROL__JS4__COMMAND_NEXT", - [JOB_CONTROL__JS4__FLUSH_ID_NEXT] = "JOB_CONTROL__JS4__FLUSH_ID_NEXT", - [JOB_CONTROL__JS4__EVENT_MASK_NEXT] = "JOB_CONTROL__JS4__EVENT_MASK_NEXT", - [JOB_CONTROL__JS5__HEAD] = "JOB_CONTROL__JS5__HEAD", - [JOB_CONTROL__JS5__TAIL] = "JOB_CONTROL__JS5__TAIL", - [JOB_CONTROL__JS5__AFFINITY] = "JOB_CONTROL__JS5__AFFINITY", - [JOB_CONTROL__JS5__CONFIG] = "JOB_CONTROL__JS5__CONFIG", - [JOB_CONTROL__JS5__XAFFINITY] = "JOB_CONTROL__JS5__XAFFINITY", - [JOB_CONTROL__JS5__COMMAND] = "JOB_CONTROL__JS5__COMMAND", - [JOB_CONTROL__JS5__STATUS] = "JOB_CONTROL__JS5__STATUS", - [JOB_CONTROL__JS5__FLUSH_ID] = "JOB_CONTROL__JS5__FLUSH_ID", - [JOB_CONTROL__JS5__EVENT_0] = "JOB_CONTROL__JS5__EVENT_0", - [JOB_CONTROL__JS5__EVENT_1] = "JOB_CONTROL__JS5__EVENT_1", - [JOB_CONTROL__JS5__EVENT_MASK] = "JOB_CONTROL__JS5__EVENT_MASK", - [JOB_CONTROL__JS5__HEAD_NEXT] = "JOB_CONTROL__JS5__HEAD_NEXT", - [JOB_CONTROL__JS5__TAIL_NEXT] = "JOB_CONTROL__JS5__TAIL_NEXT", - [JOB_CONTROL__JS5__AFFINITY_NEXT] = "JOB_CONTROL__JS5__AFFINITY_NEXT", - [JOB_CONTROL__JS5__CONFIG_NEXT] = "JOB_CONTROL__JS5__CONFIG_NEXT", - [JOB_CONTROL__JS5__XAFFINITY_NEXT] = "JOB_CONTROL__JS5__XAFFINITY_NEXT", - [JOB_CONTROL__JS5__COMMAND_NEXT] = "JOB_CONTROL__JS5__COMMAND_NEXT", - [JOB_CONTROL__JS5__FLUSH_ID_NEXT] = "JOB_CONTROL__JS5__FLUSH_ID_NEXT", - [JOB_CONTROL__JS5__EVENT_MASK_NEXT] = "JOB_CONTROL__JS5__EVENT_MASK_NEXT", - [JOB_CONTROL__JS6__HEAD] = "JOB_CONTROL__JS6__HEAD", - [JOB_CONTROL__JS6__TAIL] = "JOB_CONTROL__JS6__TAIL", - [JOB_CONTROL__JS6__AFFINITY] = "JOB_CONTROL__JS6__AFFINITY", - [JOB_CONTROL__JS6__CONFIG] = "JOB_CONTROL__JS6__CONFIG", - [JOB_CONTROL__JS6__XAFFINITY] = "JOB_CONTROL__JS6__XAFFINITY", - [JOB_CONTROL__JS6__COMMAND] = "JOB_CONTROL__JS6__COMMAND", - [JOB_CONTROL__JS6__STATUS] = "JOB_CONTROL__JS6__STATUS", - [JOB_CONTROL__JS6__FLUSH_ID] = "JOB_CONTROL__JS6__FLUSH_ID", - [JOB_CONTROL__JS6__EVENT_0] = "JOB_CONTROL__JS6__EVENT_0", - [JOB_CONTROL__JS6__EVENT_1] = "JOB_CONTROL__JS6__EVENT_1", - [JOB_CONTROL__JS6__EVENT_MASK] = "JOB_CONTROL__JS6__EVENT_MASK", - [JOB_CONTROL__JS6__HEAD_NEXT] = "JOB_CONTROL__JS6__HEAD_NEXT", - [JOB_CONTROL__JS6__TAIL_NEXT] = "JOB_CONTROL__JS6__TAIL_NEXT", - [JOB_CONTROL__JS6__AFFINITY_NEXT] = "JOB_CONTROL__JS6__AFFINITY_NEXT", - [JOB_CONTROL__JS6__CONFIG_NEXT] = "JOB_CONTROL__JS6__CONFIG_NEXT", - [JOB_CONTROL__JS6__XAFFINITY_NEXT] = "JOB_CONTROL__JS6__XAFFINITY_NEXT", - [JOB_CONTROL__JS6__COMMAND_NEXT] = "JOB_CONTROL__JS6__COMMAND_NEXT", - [JOB_CONTROL__JS6__FLUSH_ID_NEXT] = "JOB_CONTROL__JS6__FLUSH_ID_NEXT", - [JOB_CONTROL__JS6__EVENT_MASK_NEXT] = "JOB_CONTROL__JS6__EVENT_MASK_NEXT", - [JOB_CONTROL__JS7__HEAD] = "JOB_CONTROL__JS7__HEAD", - [JOB_CONTROL__JS7__TAIL] = "JOB_CONTROL__JS7__TAIL", - [JOB_CONTROL__JS7__AFFINITY] = "JOB_CONTROL__JS7__AFFINITY", - [JOB_CONTROL__JS7__CONFIG] = "JOB_CONTROL__JS7__CONFIG", - [JOB_CONTROL__JS7__XAFFINITY] = "JOB_CONTROL__JS7__XAFFINITY", - [JOB_CONTROL__JS7__COMMAND] = "JOB_CONTROL__JS7__COMMAND", - [JOB_CONTROL__JS7__STATUS] = "JOB_CONTROL__JS7__STATUS", - [JOB_CONTROL__JS7__FLUSH_ID] = "JOB_CONTROL__JS7__FLUSH_ID", - [JOB_CONTROL__JS7__EVENT_0] = "JOB_CONTROL__JS7__EVENT_0", - [JOB_CONTROL__JS7__EVENT_1] = "JOB_CONTROL__JS7__EVENT_1", - [JOB_CONTROL__JS7__EVENT_MASK] = "JOB_CONTROL__JS7__EVENT_MASK", - [JOB_CONTROL__JS7__HEAD_NEXT] = "JOB_CONTROL__JS7__HEAD_NEXT", - [JOB_CONTROL__JS7__TAIL_NEXT] = "JOB_CONTROL__JS7__TAIL_NEXT", - [JOB_CONTROL__JS7__AFFINITY_NEXT] = "JOB_CONTROL__JS7__AFFINITY_NEXT", - [JOB_CONTROL__JS7__CONFIG_NEXT] = "JOB_CONTROL__JS7__CONFIG_NEXT", - [JOB_CONTROL__JS7__XAFFINITY_NEXT] = "JOB_CONTROL__JS7__XAFFINITY_NEXT", - [JOB_CONTROL__JS7__COMMAND_NEXT] = "JOB_CONTROL__JS7__COMMAND_NEXT", - [JOB_CONTROL__JS7__FLUSH_ID_NEXT] = "JOB_CONTROL__JS7__FLUSH_ID_NEXT", - [JOB_CONTROL__JS7__EVENT_MASK_NEXT] = "JOB_CONTROL__JS7__EVENT_MASK_NEXT", - [JOB_CONTROL__JS8__HEAD] = "JOB_CONTROL__JS8__HEAD", - [JOB_CONTROL__JS8__TAIL] = "JOB_CONTROL__JS8__TAIL", - [JOB_CONTROL__JS8__AFFINITY] = "JOB_CONTROL__JS8__AFFINITY", - [JOB_CONTROL__JS8__CONFIG] = "JOB_CONTROL__JS8__CONFIG", - [JOB_CONTROL__JS8__XAFFINITY] = "JOB_CONTROL__JS8__XAFFINITY", - [JOB_CONTROL__JS8__COMMAND] = "JOB_CONTROL__JS8__COMMAND", - [JOB_CONTROL__JS8__STATUS] = "JOB_CONTROL__JS8__STATUS", - [JOB_CONTROL__JS8__FLUSH_ID] = "JOB_CONTROL__JS8__FLUSH_ID", - [JOB_CONTROL__JS8__EVENT_0] = "JOB_CONTROL__JS8__EVENT_0", - [JOB_CONTROL__JS8__EVENT_1] = "JOB_CONTROL__JS8__EVENT_1", - [JOB_CONTROL__JS8__EVENT_MASK] = "JOB_CONTROL__JS8__EVENT_MASK", - [JOB_CONTROL__JS8__HEAD_NEXT] = "JOB_CONTROL__JS8__HEAD_NEXT", - [JOB_CONTROL__JS8__TAIL_NEXT] = "JOB_CONTROL__JS8__TAIL_NEXT", - [JOB_CONTROL__JS8__AFFINITY_NEXT] = "JOB_CONTROL__JS8__AFFINITY_NEXT", - [JOB_CONTROL__JS8__CONFIG_NEXT] = "JOB_CONTROL__JS8__CONFIG_NEXT", - [JOB_CONTROL__JS8__XAFFINITY_NEXT] = "JOB_CONTROL__JS8__XAFFINITY_NEXT", - [JOB_CONTROL__JS8__COMMAND_NEXT] = "JOB_CONTROL__JS8__COMMAND_NEXT", - [JOB_CONTROL__JS8__FLUSH_ID_NEXT] = "JOB_CONTROL__JS8__FLUSH_ID_NEXT", - [JOB_CONTROL__JS8__EVENT_MASK_NEXT] = "JOB_CONTROL__JS8__EVENT_MASK_NEXT", - [JOB_CONTROL__JS9__HEAD] = "JOB_CONTROL__JS9__HEAD", - [JOB_CONTROL__JS9__TAIL] = "JOB_CONTROL__JS9__TAIL", - [JOB_CONTROL__JS9__AFFINITY] = "JOB_CONTROL__JS9__AFFINITY", - [JOB_CONTROL__JS9__CONFIG] = "JOB_CONTROL__JS9__CONFIG", - [JOB_CONTROL__JS9__XAFFINITY] = "JOB_CONTROL__JS9__XAFFINITY", - [JOB_CONTROL__JS9__COMMAND] = "JOB_CONTROL__JS9__COMMAND", - [JOB_CONTROL__JS9__STATUS] = "JOB_CONTROL__JS9__STATUS", - [JOB_CONTROL__JS9__FLUSH_ID] = "JOB_CONTROL__JS9__FLUSH_ID", - [JOB_CONTROL__JS9__EVENT_0] = "JOB_CONTROL__JS9__EVENT_0", - [JOB_CONTROL__JS9__EVENT_1] = "JOB_CONTROL__JS9__EVENT_1", - [JOB_CONTROL__JS9__EVENT_MASK] = "JOB_CONTROL__JS9__EVENT_MASK", - [JOB_CONTROL__JS9__HEAD_NEXT] = "JOB_CONTROL__JS9__HEAD_NEXT", - [JOB_CONTROL__JS9__TAIL_NEXT] = "JOB_CONTROL__JS9__TAIL_NEXT", - [JOB_CONTROL__JS9__AFFINITY_NEXT] = "JOB_CONTROL__JS9__AFFINITY_NEXT", - [JOB_CONTROL__JS9__CONFIG_NEXT] = "JOB_CONTROL__JS9__CONFIG_NEXT", - [JOB_CONTROL__JS9__XAFFINITY_NEXT] = "JOB_CONTROL__JS9__XAFFINITY_NEXT", - [JOB_CONTROL__JS9__COMMAND_NEXT] = "JOB_CONTROL__JS9__COMMAND_NEXT", - [JOB_CONTROL__JS9__FLUSH_ID_NEXT] = "JOB_CONTROL__JS9__FLUSH_ID_NEXT", - [JOB_CONTROL__JS9__EVENT_MASK_NEXT] = "JOB_CONTROL__JS9__EVENT_MASK_NEXT", - [JOB_CONTROL__JS10__HEAD] = "JOB_CONTROL__JS10__HEAD", - [JOB_CONTROL__JS10__TAIL] = "JOB_CONTROL__JS10__TAIL", - [JOB_CONTROL__JS10__AFFINITY] = "JOB_CONTROL__JS10__AFFINITY", - [JOB_CONTROL__JS10__CONFIG] = "JOB_CONTROL__JS10__CONFIG", - [JOB_CONTROL__JS10__XAFFINITY] = "JOB_CONTROL__JS10__XAFFINITY", - [JOB_CONTROL__JS10__COMMAND] = "JOB_CONTROL__JS10__COMMAND", - [JOB_CONTROL__JS10__STATUS] = "JOB_CONTROL__JS10__STATUS", - [JOB_CONTROL__JS10__FLUSH_ID] = "JOB_CONTROL__JS10__FLUSH_ID", - [JOB_CONTROL__JS10__EVENT_0] = "JOB_CONTROL__JS10__EVENT_0", - [JOB_CONTROL__JS10__EVENT_1] = "JOB_CONTROL__JS10__EVENT_1", - [JOB_CONTROL__JS10__EVENT_MASK] = "JOB_CONTROL__JS10__EVENT_MASK", - [JOB_CONTROL__JS10__HEAD_NEXT] = "JOB_CONTROL__JS10__HEAD_NEXT", - [JOB_CONTROL__JS10__TAIL_NEXT] = "JOB_CONTROL__JS10__TAIL_NEXT", - [JOB_CONTROL__JS10__AFFINITY_NEXT] = "JOB_CONTROL__JS10__AFFINITY_NEXT", - [JOB_CONTROL__JS10__CONFIG_NEXT] = "JOB_CONTROL__JS10__CONFIG_NEXT", - [JOB_CONTROL__JS10__XAFFINITY_NEXT] = "JOB_CONTROL__JS10__XAFFINITY_NEXT", - [JOB_CONTROL__JS10__COMMAND_NEXT] = "JOB_CONTROL__JS10__COMMAND_NEXT", - [JOB_CONTROL__JS10__FLUSH_ID_NEXT] = "JOB_CONTROL__JS10__FLUSH_ID_NEXT", - [JOB_CONTROL__JS10__EVENT_MASK_NEXT] = "JOB_CONTROL__JS10__EVENT_MASK_NEXT", - [JOB_CONTROL__JS11__HEAD] = "JOB_CONTROL__JS11__HEAD", - [JOB_CONTROL__JS11__TAIL] = "JOB_CONTROL__JS11__TAIL", - [JOB_CONTROL__JS11__AFFINITY] = "JOB_CONTROL__JS11__AFFINITY", - [JOB_CONTROL__JS11__CONFIG] = "JOB_CONTROL__JS11__CONFIG", - [JOB_CONTROL__JS11__XAFFINITY] = "JOB_CONTROL__JS11__XAFFINITY", - [JOB_CONTROL__JS11__COMMAND] = "JOB_CONTROL__JS11__COMMAND", - [JOB_CONTROL__JS11__STATUS] = "JOB_CONTROL__JS11__STATUS", - [JOB_CONTROL__JS11__FLUSH_ID] = "JOB_CONTROL__JS11__FLUSH_ID", - [JOB_CONTROL__JS11__EVENT_0] = "JOB_CONTROL__JS11__EVENT_0", - [JOB_CONTROL__JS11__EVENT_1] = "JOB_CONTROL__JS11__EVENT_1", - [JOB_CONTROL__JS11__EVENT_MASK] = "JOB_CONTROL__JS11__EVENT_MASK", - [JOB_CONTROL__JS11__HEAD_NEXT] = "JOB_CONTROL__JS11__HEAD_NEXT", - [JOB_CONTROL__JS11__TAIL_NEXT] = "JOB_CONTROL__JS11__TAIL_NEXT", - [JOB_CONTROL__JS11__AFFINITY_NEXT] = "JOB_CONTROL__JS11__AFFINITY_NEXT", - [JOB_CONTROL__JS11__CONFIG_NEXT] = "JOB_CONTROL__JS11__CONFIG_NEXT", - [JOB_CONTROL__JS11__XAFFINITY_NEXT] = "JOB_CONTROL__JS11__XAFFINITY_NEXT", - [JOB_CONTROL__JS11__COMMAND_NEXT] = "JOB_CONTROL__JS11__COMMAND_NEXT", - [JOB_CONTROL__JS11__FLUSH_ID_NEXT] = "JOB_CONTROL__JS11__FLUSH_ID_NEXT", - [JOB_CONTROL__JS11__EVENT_MASK_NEXT] = "JOB_CONTROL__JS11__EVENT_MASK_NEXT", - [JOB_CONTROL__JS12__HEAD] = "JOB_CONTROL__JS12__HEAD", - [JOB_CONTROL__JS12__TAIL] = "JOB_CONTROL__JS12__TAIL", - [JOB_CONTROL__JS12__AFFINITY] = "JOB_CONTROL__JS12__AFFINITY", - [JOB_CONTROL__JS12__CONFIG] = "JOB_CONTROL__JS12__CONFIG", - [JOB_CONTROL__JS12__XAFFINITY] = "JOB_CONTROL__JS12__XAFFINITY", - [JOB_CONTROL__JS12__COMMAND] = "JOB_CONTROL__JS12__COMMAND", - [JOB_CONTROL__JS12__STATUS] = "JOB_CONTROL__JS12__STATUS", - [JOB_CONTROL__JS12__FLUSH_ID] = "JOB_CONTROL__JS12__FLUSH_ID", - [JOB_CONTROL__JS12__EVENT_0] = "JOB_CONTROL__JS12__EVENT_0", - [JOB_CONTROL__JS12__EVENT_1] = "JOB_CONTROL__JS12__EVENT_1", - [JOB_CONTROL__JS12__EVENT_MASK] = "JOB_CONTROL__JS12__EVENT_MASK", - [JOB_CONTROL__JS12__HEAD_NEXT] = "JOB_CONTROL__JS12__HEAD_NEXT", - [JOB_CONTROL__JS12__TAIL_NEXT] = "JOB_CONTROL__JS12__TAIL_NEXT", - [JOB_CONTROL__JS12__AFFINITY_NEXT] = "JOB_CONTROL__JS12__AFFINITY_NEXT", - [JOB_CONTROL__JS12__CONFIG_NEXT] = "JOB_CONTROL__JS12__CONFIG_NEXT", - [JOB_CONTROL__JS12__XAFFINITY_NEXT] = "JOB_CONTROL__JS12__XAFFINITY_NEXT", - [JOB_CONTROL__JS12__COMMAND_NEXT] = "JOB_CONTROL__JS12__COMMAND_NEXT", - [JOB_CONTROL__JS12__FLUSH_ID_NEXT] = "JOB_CONTROL__JS12__FLUSH_ID_NEXT", - [JOB_CONTROL__JS12__EVENT_MASK_NEXT] = "JOB_CONTROL__JS12__EVENT_MASK_NEXT", - [JOB_CONTROL__JS13__HEAD] = "JOB_CONTROL__JS13__HEAD", - [JOB_CONTROL__JS13__TAIL] = "JOB_CONTROL__JS13__TAIL", - [JOB_CONTROL__JS13__AFFINITY] = "JOB_CONTROL__JS13__AFFINITY", - [JOB_CONTROL__JS13__CONFIG] = "JOB_CONTROL__JS13__CONFIG", - [JOB_CONTROL__JS13__XAFFINITY] = "JOB_CONTROL__JS13__XAFFINITY", - [JOB_CONTROL__JS13__COMMAND] = "JOB_CONTROL__JS13__COMMAND", - [JOB_CONTROL__JS13__STATUS] = "JOB_CONTROL__JS13__STATUS", - [JOB_CONTROL__JS13__FLUSH_ID] = "JOB_CONTROL__JS13__FLUSH_ID", - [JOB_CONTROL__JS13__EVENT_0] = "JOB_CONTROL__JS13__EVENT_0", - [JOB_CONTROL__JS13__EVENT_1] = "JOB_CONTROL__JS13__EVENT_1", - [JOB_CONTROL__JS13__EVENT_MASK] = "JOB_CONTROL__JS13__EVENT_MASK", - [JOB_CONTROL__JS13__HEAD_NEXT] = "JOB_CONTROL__JS13__HEAD_NEXT", - [JOB_CONTROL__JS13__TAIL_NEXT] = "JOB_CONTROL__JS13__TAIL_NEXT", - [JOB_CONTROL__JS13__AFFINITY_NEXT] = "JOB_CONTROL__JS13__AFFINITY_NEXT", - [JOB_CONTROL__JS13__CONFIG_NEXT] = "JOB_CONTROL__JS13__CONFIG_NEXT", - [JOB_CONTROL__JS13__XAFFINITY_NEXT] = "JOB_CONTROL__JS13__XAFFINITY_NEXT", - [JOB_CONTROL__JS13__COMMAND_NEXT] = "JOB_CONTROL__JS13__COMMAND_NEXT", - [JOB_CONTROL__JS13__FLUSH_ID_NEXT] = "JOB_CONTROL__JS13__FLUSH_ID_NEXT", - [JOB_CONTROL__JS13__EVENT_MASK_NEXT] = "JOB_CONTROL__JS13__EVENT_MASK_NEXT", - [JOB_CONTROL__JS14__HEAD] = "JOB_CONTROL__JS14__HEAD", - [JOB_CONTROL__JS14__TAIL] = "JOB_CONTROL__JS14__TAIL", - [JOB_CONTROL__JS14__AFFINITY] = "JOB_CONTROL__JS14__AFFINITY", - [JOB_CONTROL__JS14__CONFIG] = "JOB_CONTROL__JS14__CONFIG", - [JOB_CONTROL__JS14__XAFFINITY] = "JOB_CONTROL__JS14__XAFFINITY", - [JOB_CONTROL__JS14__COMMAND] = "JOB_CONTROL__JS14__COMMAND", - [JOB_CONTROL__JS14__STATUS] = "JOB_CONTROL__JS14__STATUS", - [JOB_CONTROL__JS14__FLUSH_ID] = "JOB_CONTROL__JS14__FLUSH_ID", - [JOB_CONTROL__JS14__EVENT_0] = "JOB_CONTROL__JS14__EVENT_0", - [JOB_CONTROL__JS14__EVENT_1] = "JOB_CONTROL__JS14__EVENT_1", - [JOB_CONTROL__JS14__EVENT_MASK] = "JOB_CONTROL__JS14__EVENT_MASK", - [JOB_CONTROL__JS14__HEAD_NEXT] = "JOB_CONTROL__JS14__HEAD_NEXT", - [JOB_CONTROL__JS14__TAIL_NEXT] = "JOB_CONTROL__JS14__TAIL_NEXT", - [JOB_CONTROL__JS14__AFFINITY_NEXT] = "JOB_CONTROL__JS14__AFFINITY_NEXT", - [JOB_CONTROL__JS14__CONFIG_NEXT] = "JOB_CONTROL__JS14__CONFIG_NEXT", - [JOB_CONTROL__JS14__XAFFINITY_NEXT] = "JOB_CONTROL__JS14__XAFFINITY_NEXT", - [JOB_CONTROL__JS14__COMMAND_NEXT] = "JOB_CONTROL__JS14__COMMAND_NEXT", - [JOB_CONTROL__JS14__FLUSH_ID_NEXT] = "JOB_CONTROL__JS14__FLUSH_ID_NEXT", - [JOB_CONTROL__JS14__EVENT_MASK_NEXT] = "JOB_CONTROL__JS14__EVENT_MASK_NEXT", - [JOB_CONTROL__JS15__HEAD] = "JOB_CONTROL__JS15__HEAD", - [JOB_CONTROL__JS15__TAIL] = "JOB_CONTROL__JS15__TAIL", - [JOB_CONTROL__JS15__AFFINITY] = "JOB_CONTROL__JS15__AFFINITY", - [JOB_CONTROL__JS15__CONFIG] = "JOB_CONTROL__JS15__CONFIG", - [JOB_CONTROL__JS15__XAFFINITY] = "JOB_CONTROL__JS15__XAFFINITY", - [JOB_CONTROL__JS15__COMMAND] = "JOB_CONTROL__JS15__COMMAND", - [JOB_CONTROL__JS15__STATUS] = "JOB_CONTROL__JS15__STATUS", - [JOB_CONTROL__JS15__FLUSH_ID] = "JOB_CONTROL__JS15__FLUSH_ID", - [JOB_CONTROL__JS15__EVENT_0] = "JOB_CONTROL__JS15__EVENT_0", - [JOB_CONTROL__JS15__EVENT_1] = "JOB_CONTROL__JS15__EVENT_1", - [JOB_CONTROL__JS15__EVENT_MASK] = "JOB_CONTROL__JS15__EVENT_MASK", - [JOB_CONTROL__JS15__HEAD_NEXT] = "JOB_CONTROL__JS15__HEAD_NEXT", - [JOB_CONTROL__JS15__TAIL_NEXT] = "JOB_CONTROL__JS15__TAIL_NEXT", - [JOB_CONTROL__JS15__AFFINITY_NEXT] = "JOB_CONTROL__JS15__AFFINITY_NEXT", - [JOB_CONTROL__JS15__CONFIG_NEXT] = "JOB_CONTROL__JS15__CONFIG_NEXT", - [JOB_CONTROL__JS15__XAFFINITY_NEXT] = "JOB_CONTROL__JS15__XAFFINITY_NEXT", - [JOB_CONTROL__JS15__COMMAND_NEXT] = "JOB_CONTROL__JS15__COMMAND_NEXT", - [JOB_CONTROL__JS15__FLUSH_ID_NEXT] = "JOB_CONTROL__JS15__FLUSH_ID_NEXT", - [JOB_CONTROL__JS15__EVENT_MASK_NEXT] = "JOB_CONTROL__JS15__EVENT_MASK_NEXT", - [MMU_STAGE1__ST1MMU__IRQ_RAWSTAT] = "MMU_STAGE1__ST1MMU__IRQ_RAWSTAT", - [MMU_STAGE1__ST1MMU__IRQ_CLEAR] = "MMU_STAGE1__ST1MMU__IRQ_CLEAR", - [MMU_STAGE1__ST1MMU__IRQ_MASK] = "MMU_STAGE1__ST1MMU__IRQ_MASK", - [MMU_STAGE1__ST1MMU__IRQ_STATUS] = "MMU_STAGE1__ST1MMU__IRQ_STATUS", - [MMU_STAGE1__ST1MMU__AS0__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS0__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS0__MEMATTR] = "MMU_STAGE1__ST1MMU__AS0__MEMATTR", - [MMU_STAGE1__ST1MMU__AS0__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS0__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS0__COMMAND] = "MMU_STAGE1__ST1MMU__AS0__COMMAND", - [MMU_STAGE1__ST1MMU__AS0__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS0__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS0__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS0__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS0__STATUS] = "MMU_STAGE1__ST1MMU__AS0__STATUS", - [MMU_STAGE1__ST1MMU__AS0__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS0__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS0__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS0__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS1__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS1__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS1__MEMATTR] = "MMU_STAGE1__ST1MMU__AS1__MEMATTR", - [MMU_STAGE1__ST1MMU__AS1__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS1__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS1__COMMAND] = "MMU_STAGE1__ST1MMU__AS1__COMMAND", - [MMU_STAGE1__ST1MMU__AS1__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS1__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS1__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS1__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS1__STATUS] = "MMU_STAGE1__ST1MMU__AS1__STATUS", - [MMU_STAGE1__ST1MMU__AS1__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS1__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS1__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS1__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS2__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS2__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS2__MEMATTR] = "MMU_STAGE1__ST1MMU__AS2__MEMATTR", - [MMU_STAGE1__ST1MMU__AS2__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS2__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS2__COMMAND] = "MMU_STAGE1__ST1MMU__AS2__COMMAND", - [MMU_STAGE1__ST1MMU__AS2__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS2__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS2__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS2__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS2__STATUS] = "MMU_STAGE1__ST1MMU__AS2__STATUS", - [MMU_STAGE1__ST1MMU__AS2__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS2__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS2__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS2__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS3__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS3__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS3__MEMATTR] = "MMU_STAGE1__ST1MMU__AS3__MEMATTR", - [MMU_STAGE1__ST1MMU__AS3__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS3__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS3__COMMAND] = "MMU_STAGE1__ST1MMU__AS3__COMMAND", - [MMU_STAGE1__ST1MMU__AS3__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS3__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS3__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS3__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS3__STATUS] = "MMU_STAGE1__ST1MMU__AS3__STATUS", - [MMU_STAGE1__ST1MMU__AS3__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS3__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS3__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS3__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS4__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS4__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS4__MEMATTR] = "MMU_STAGE1__ST1MMU__AS4__MEMATTR", - [MMU_STAGE1__ST1MMU__AS4__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS4__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS4__COMMAND] = "MMU_STAGE1__ST1MMU__AS4__COMMAND", - [MMU_STAGE1__ST1MMU__AS4__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS4__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS4__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS4__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS4__STATUS] = "MMU_STAGE1__ST1MMU__AS4__STATUS", - [MMU_STAGE1__ST1MMU__AS4__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS4__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS4__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS4__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS5__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS5__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS5__MEMATTR] = "MMU_STAGE1__ST1MMU__AS5__MEMATTR", - [MMU_STAGE1__ST1MMU__AS5__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS5__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS5__COMMAND] = "MMU_STAGE1__ST1MMU__AS5__COMMAND", - [MMU_STAGE1__ST1MMU__AS5__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS5__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS5__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS5__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS5__STATUS] = "MMU_STAGE1__ST1MMU__AS5__STATUS", - [MMU_STAGE1__ST1MMU__AS5__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS5__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS5__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS5__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS6__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS6__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS6__MEMATTR] = "MMU_STAGE1__ST1MMU__AS6__MEMATTR", - [MMU_STAGE1__ST1MMU__AS6__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS6__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS6__COMMAND] = "MMU_STAGE1__ST1MMU__AS6__COMMAND", - [MMU_STAGE1__ST1MMU__AS6__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS6__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS6__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS6__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS6__STATUS] = "MMU_STAGE1__ST1MMU__AS6__STATUS", - [MMU_STAGE1__ST1MMU__AS6__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS6__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS6__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS6__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS7__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS7__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS7__MEMATTR] = "MMU_STAGE1__ST1MMU__AS7__MEMATTR", - [MMU_STAGE1__ST1MMU__AS7__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS7__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS7__COMMAND] = "MMU_STAGE1__ST1MMU__AS7__COMMAND", - [MMU_STAGE1__ST1MMU__AS7__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS7__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS7__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS7__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS7__STATUS] = "MMU_STAGE1__ST1MMU__AS7__STATUS", - [MMU_STAGE1__ST1MMU__AS7__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS7__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS7__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS7__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS8__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS8__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS8__MEMATTR] = "MMU_STAGE1__ST1MMU__AS8__MEMATTR", - [MMU_STAGE1__ST1MMU__AS8__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS8__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS8__COMMAND] = "MMU_STAGE1__ST1MMU__AS8__COMMAND", - [MMU_STAGE1__ST1MMU__AS8__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS8__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS8__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS8__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS8__STATUS] = "MMU_STAGE1__ST1MMU__AS8__STATUS", - [MMU_STAGE1__ST1MMU__AS8__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS8__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS8__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS8__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS9__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS9__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS9__MEMATTR] = "MMU_STAGE1__ST1MMU__AS9__MEMATTR", - [MMU_STAGE1__ST1MMU__AS9__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS9__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS9__COMMAND] = "MMU_STAGE1__ST1MMU__AS9__COMMAND", - [MMU_STAGE1__ST1MMU__AS9__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS9__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS9__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS9__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS9__STATUS] = "MMU_STAGE1__ST1MMU__AS9__STATUS", - [MMU_STAGE1__ST1MMU__AS9__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS9__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS9__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS9__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS10__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS10__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS10__MEMATTR] = "MMU_STAGE1__ST1MMU__AS10__MEMATTR", - [MMU_STAGE1__ST1MMU__AS10__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS10__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS10__COMMAND] = "MMU_STAGE1__ST1MMU__AS10__COMMAND", - [MMU_STAGE1__ST1MMU__AS10__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS10__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS10__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS10__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS10__STATUS] = "MMU_STAGE1__ST1MMU__AS10__STATUS", - [MMU_STAGE1__ST1MMU__AS10__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS10__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS10__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS10__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS11__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS11__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS11__MEMATTR] = "MMU_STAGE1__ST1MMU__AS11__MEMATTR", - [MMU_STAGE1__ST1MMU__AS11__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS11__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS11__COMMAND] = "MMU_STAGE1__ST1MMU__AS11__COMMAND", - [MMU_STAGE1__ST1MMU__AS11__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS11__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS11__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS11__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS11__STATUS] = "MMU_STAGE1__ST1MMU__AS11__STATUS", - [MMU_STAGE1__ST1MMU__AS11__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS11__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS11__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS11__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS12__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS12__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS12__MEMATTR] = "MMU_STAGE1__ST1MMU__AS12__MEMATTR", - [MMU_STAGE1__ST1MMU__AS12__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS12__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS12__COMMAND] = "MMU_STAGE1__ST1MMU__AS12__COMMAND", - [MMU_STAGE1__ST1MMU__AS12__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS12__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS12__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS12__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS12__STATUS] = "MMU_STAGE1__ST1MMU__AS12__STATUS", - [MMU_STAGE1__ST1MMU__AS12__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS12__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS12__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS12__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS13__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS13__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS13__MEMATTR] = "MMU_STAGE1__ST1MMU__AS13__MEMATTR", - [MMU_STAGE1__ST1MMU__AS13__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS13__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS13__COMMAND] = "MMU_STAGE1__ST1MMU__AS13__COMMAND", - [MMU_STAGE1__ST1MMU__AS13__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS13__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS13__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS13__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS13__STATUS] = "MMU_STAGE1__ST1MMU__AS13__STATUS", - [MMU_STAGE1__ST1MMU__AS13__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS13__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS13__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS13__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS14__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS14__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS14__MEMATTR] = "MMU_STAGE1__ST1MMU__AS14__MEMATTR", - [MMU_STAGE1__ST1MMU__AS14__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS14__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS14__COMMAND] = "MMU_STAGE1__ST1MMU__AS14__COMMAND", - [MMU_STAGE1__ST1MMU__AS14__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS14__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS14__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS14__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS14__STATUS] = "MMU_STAGE1__ST1MMU__AS14__STATUS", - [MMU_STAGE1__ST1MMU__AS14__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS14__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS14__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS14__FAULTEXTRA", - [MMU_STAGE1__ST1MMU__AS15__TRANSTAB] = "MMU_STAGE1__ST1MMU__AS15__TRANSTAB", - [MMU_STAGE1__ST1MMU__AS15__MEMATTR] = "MMU_STAGE1__ST1MMU__AS15__MEMATTR", - [MMU_STAGE1__ST1MMU__AS15__LOCKADDR] = "MMU_STAGE1__ST1MMU__AS15__LOCKADDR", - [MMU_STAGE1__ST1MMU__AS15__COMMAND] = "MMU_STAGE1__ST1MMU__AS15__COMMAND", - [MMU_STAGE1__ST1MMU__AS15__FAULTSTATUS] = "MMU_STAGE1__ST1MMU__AS15__FAULTSTATUS", - [MMU_STAGE1__ST1MMU__AS15__FAULTADDRESS] = "MMU_STAGE1__ST1MMU__AS15__FAULTADDRESS", - [MMU_STAGE1__ST1MMU__AS15__STATUS] = "MMU_STAGE1__ST1MMU__AS15__STATUS", - [MMU_STAGE1__ST1MMU__AS15__TRANSCFG] = "MMU_STAGE1__ST1MMU__AS15__TRANSCFG", - [MMU_STAGE1__ST1MMU__AS15__FAULTEXTRA] = "MMU_STAGE1__ST1MMU__AS15__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__IRQ_RAWSTAT] = "MMU_STAGE2__ST2MMU__IRQ_RAWSTAT", - [MMU_STAGE2__ST2MMU__IRQ_CLEAR] = "MMU_STAGE2__ST2MMU__IRQ_CLEAR", - [MMU_STAGE2__ST2MMU__IRQ_MASK] = "MMU_STAGE2__ST2MMU__IRQ_MASK", - [MMU_STAGE2__ST2MMU__IRQ_STATUS] = "MMU_STAGE2__ST2MMU__IRQ_STATUS", - [MMU_STAGE2__ST2MMU__AS0__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS0__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS0__MEMATTR] = "MMU_STAGE2__ST2MMU__AS0__MEMATTR", - [MMU_STAGE2__ST2MMU__AS0__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS0__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS0__COMMAND] = "MMU_STAGE2__ST2MMU__AS0__COMMAND", - [MMU_STAGE2__ST2MMU__AS0__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS0__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS0__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS0__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS0__STATUS] = "MMU_STAGE2__ST2MMU__AS0__STATUS", - [MMU_STAGE2__ST2MMU__AS0__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS0__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS0__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS0__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS1__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS1__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS1__MEMATTR] = "MMU_STAGE2__ST2MMU__AS1__MEMATTR", - [MMU_STAGE2__ST2MMU__AS1__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS1__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS1__COMMAND] = "MMU_STAGE2__ST2MMU__AS1__COMMAND", - [MMU_STAGE2__ST2MMU__AS1__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS1__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS1__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS1__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS1__STATUS] = "MMU_STAGE2__ST2MMU__AS1__STATUS", - [MMU_STAGE2__ST2MMU__AS1__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS1__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS1__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS1__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS2__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS2__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS2__MEMATTR] = "MMU_STAGE2__ST2MMU__AS2__MEMATTR", - [MMU_STAGE2__ST2MMU__AS2__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS2__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS2__COMMAND] = "MMU_STAGE2__ST2MMU__AS2__COMMAND", - [MMU_STAGE2__ST2MMU__AS2__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS2__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS2__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS2__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS2__STATUS] = "MMU_STAGE2__ST2MMU__AS2__STATUS", - [MMU_STAGE2__ST2MMU__AS2__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS2__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS2__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS2__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS3__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS3__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS3__MEMATTR] = "MMU_STAGE2__ST2MMU__AS3__MEMATTR", - [MMU_STAGE2__ST2MMU__AS3__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS3__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS3__COMMAND] = "MMU_STAGE2__ST2MMU__AS3__COMMAND", - [MMU_STAGE2__ST2MMU__AS3__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS3__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS3__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS3__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS3__STATUS] = "MMU_STAGE2__ST2MMU__AS3__STATUS", - [MMU_STAGE2__ST2MMU__AS3__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS3__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS3__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS3__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS4__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS4__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS4__MEMATTR] = "MMU_STAGE2__ST2MMU__AS4__MEMATTR", - [MMU_STAGE2__ST2MMU__AS4__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS4__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS4__COMMAND] = "MMU_STAGE2__ST2MMU__AS4__COMMAND", - [MMU_STAGE2__ST2MMU__AS4__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS4__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS4__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS4__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS4__STATUS] = "MMU_STAGE2__ST2MMU__AS4__STATUS", - [MMU_STAGE2__ST2MMU__AS4__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS4__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS4__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS4__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS5__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS5__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS5__MEMATTR] = "MMU_STAGE2__ST2MMU__AS5__MEMATTR", - [MMU_STAGE2__ST2MMU__AS5__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS5__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS5__COMMAND] = "MMU_STAGE2__ST2MMU__AS5__COMMAND", - [MMU_STAGE2__ST2MMU__AS5__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS5__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS5__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS5__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS5__STATUS] = "MMU_STAGE2__ST2MMU__AS5__STATUS", - [MMU_STAGE2__ST2MMU__AS5__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS5__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS5__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS5__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS6__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS6__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS6__MEMATTR] = "MMU_STAGE2__ST2MMU__AS6__MEMATTR", - [MMU_STAGE2__ST2MMU__AS6__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS6__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS6__COMMAND] = "MMU_STAGE2__ST2MMU__AS6__COMMAND", - [MMU_STAGE2__ST2MMU__AS6__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS6__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS6__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS6__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS6__STATUS] = "MMU_STAGE2__ST2MMU__AS6__STATUS", - [MMU_STAGE2__ST2MMU__AS6__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS6__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS6__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS6__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS7__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS7__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS7__MEMATTR] = "MMU_STAGE2__ST2MMU__AS7__MEMATTR", - [MMU_STAGE2__ST2MMU__AS7__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS7__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS7__COMMAND] = "MMU_STAGE2__ST2MMU__AS7__COMMAND", - [MMU_STAGE2__ST2MMU__AS7__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS7__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS7__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS7__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS7__STATUS] = "MMU_STAGE2__ST2MMU__AS7__STATUS", - [MMU_STAGE2__ST2MMU__AS7__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS7__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS7__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS7__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS8__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS8__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS8__MEMATTR] = "MMU_STAGE2__ST2MMU__AS8__MEMATTR", - [MMU_STAGE2__ST2MMU__AS8__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS8__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS8__COMMAND] = "MMU_STAGE2__ST2MMU__AS8__COMMAND", - [MMU_STAGE2__ST2MMU__AS8__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS8__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS8__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS8__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS8__STATUS] = "MMU_STAGE2__ST2MMU__AS8__STATUS", - [MMU_STAGE2__ST2MMU__AS8__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS8__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS8__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS8__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS9__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS9__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS9__MEMATTR] = "MMU_STAGE2__ST2MMU__AS9__MEMATTR", - [MMU_STAGE2__ST2MMU__AS9__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS9__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS9__COMMAND] = "MMU_STAGE2__ST2MMU__AS9__COMMAND", - [MMU_STAGE2__ST2MMU__AS9__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS9__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS9__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS9__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS9__STATUS] = "MMU_STAGE2__ST2MMU__AS9__STATUS", - [MMU_STAGE2__ST2MMU__AS9__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS9__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS9__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS9__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS10__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS10__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS10__MEMATTR] = "MMU_STAGE2__ST2MMU__AS10__MEMATTR", - [MMU_STAGE2__ST2MMU__AS10__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS10__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS10__COMMAND] = "MMU_STAGE2__ST2MMU__AS10__COMMAND", - [MMU_STAGE2__ST2MMU__AS10__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS10__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS10__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS10__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS10__STATUS] = "MMU_STAGE2__ST2MMU__AS10__STATUS", - [MMU_STAGE2__ST2MMU__AS10__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS10__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS10__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS10__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS11__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS11__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS11__MEMATTR] = "MMU_STAGE2__ST2MMU__AS11__MEMATTR", - [MMU_STAGE2__ST2MMU__AS11__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS11__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS11__COMMAND] = "MMU_STAGE2__ST2MMU__AS11__COMMAND", - [MMU_STAGE2__ST2MMU__AS11__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS11__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS11__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS11__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS11__STATUS] = "MMU_STAGE2__ST2MMU__AS11__STATUS", - [MMU_STAGE2__ST2MMU__AS11__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS11__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS11__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS11__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS12__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS12__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS12__MEMATTR] = "MMU_STAGE2__ST2MMU__AS12__MEMATTR", - [MMU_STAGE2__ST2MMU__AS12__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS12__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS12__COMMAND] = "MMU_STAGE2__ST2MMU__AS12__COMMAND", - [MMU_STAGE2__ST2MMU__AS12__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS12__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS12__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS12__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS12__STATUS] = "MMU_STAGE2__ST2MMU__AS12__STATUS", - [MMU_STAGE2__ST2MMU__AS12__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS12__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS12__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS12__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS13__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS13__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS13__MEMATTR] = "MMU_STAGE2__ST2MMU__AS13__MEMATTR", - [MMU_STAGE2__ST2MMU__AS13__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS13__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS13__COMMAND] = "MMU_STAGE2__ST2MMU__AS13__COMMAND", - [MMU_STAGE2__ST2MMU__AS13__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS13__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS13__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS13__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS13__STATUS] = "MMU_STAGE2__ST2MMU__AS13__STATUS", - [MMU_STAGE2__ST2MMU__AS13__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS13__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS13__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS13__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS14__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS14__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS14__MEMATTR] = "MMU_STAGE2__ST2MMU__AS14__MEMATTR", - [MMU_STAGE2__ST2MMU__AS14__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS14__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS14__COMMAND] = "MMU_STAGE2__ST2MMU__AS14__COMMAND", - [MMU_STAGE2__ST2MMU__AS14__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS14__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS14__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS14__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS14__STATUS] = "MMU_STAGE2__ST2MMU__AS14__STATUS", - [MMU_STAGE2__ST2MMU__AS14__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS14__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS14__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS14__FAULTEXTRA", - [MMU_STAGE2__ST2MMU__AS15__TRANSTAB] = "MMU_STAGE2__ST2MMU__AS15__TRANSTAB", - [MMU_STAGE2__ST2MMU__AS15__MEMATTR] = "MMU_STAGE2__ST2MMU__AS15__MEMATTR", - [MMU_STAGE2__ST2MMU__AS15__LOCKADDR] = "MMU_STAGE2__ST2MMU__AS15__LOCKADDR", - [MMU_STAGE2__ST2MMU__AS15__COMMAND] = "MMU_STAGE2__ST2MMU__AS15__COMMAND", - [MMU_STAGE2__ST2MMU__AS15__FAULTSTATUS] = "MMU_STAGE2__ST2MMU__AS15__FAULTSTATUS", - [MMU_STAGE2__ST2MMU__AS15__FAULTADDRESS] = "MMU_STAGE2__ST2MMU__AS15__FAULTADDRESS", - [MMU_STAGE2__ST2MMU__AS15__STATUS] = "MMU_STAGE2__ST2MMU__AS15__STATUS", - [MMU_STAGE2__ST2MMU__AS15__TRANSCFG] = "MMU_STAGE2__ST2MMU__AS15__TRANSCFG", - [MMU_STAGE2__ST2MMU__AS15__FAULTEXTRA] = "MMU_STAGE2__ST2MMU__AS15__FAULTEXTRA", - [GPU_CONTROL__REVIDR] = "GPU_CONTROL__REVIDR", - [GPU_CONTROL__STACK_PRESENT] = "GPU_CONTROL__STACK_PRESENT", - [GPU_CONTROL__STACK_PWROFF] = "GPU_CONTROL__STACK_PWROFF", - [GPU_CONTROL__STACK_PWRON] = "GPU_CONTROL__STACK_PWRON", - [GPU_CONTROL__STACK_PWRTRANS] = "GPU_CONTROL__STACK_PWRTRANS", - [GPU_CONTROL__STACK_READY] = "GPU_CONTROL__STACK_READY", - [GPU_CONTROL__TEXTURE_FEATURES_3] = "GPU_CONTROL__TEXTURE_FEATURES_3", - [GPU_CONTROL__CORE_FEATURES] = "GPU_CONTROL__CORE_FEATURES", - [GPU_CONTROL__THREAD_TLS_ALLOC] = "GPU_CONTROL__THREAD_TLS_ALLOC", - [GPU_CONTROL__L2_CONFIG] = "GPU_CONTROL__L2_CONFIG", - [PTM_AW_IRQ_CLEAR] = "PTM_AW_IRQ_CLEAR", - [PTM_AW_IRQ_INJECTION] = "PTM_AW_IRQ_INJECTION", - [PTM_AW_IRQ_MASK] = "PTM_AW_IRQ_MASK", - [PTM_AW_IRQ_RAWSTAT] = "PTM_AW_IRQ_RAWSTAT", - [PTM_AW_IRQ_STATUS] = "PTM_AW_IRQ_STATUS", - [PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0] = "PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0", - [PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1] = "PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1", - [PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0] = "PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0", - [PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1] = "PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1", - [PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS] = - "PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS", - [PTM_ID] = "PTM_ID", -}; - -const char *kbase_reg_get_enum_string(u32 reg_enum) -{ - if (reg_enum >= ARRAY_SIZE(enum_strings)) - return "INVALID_REG"; - return enum_strings[reg_enum]; -} -#endif /* CONFIG_MALI_VALHALL_DEBUG */ diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_enums.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_enums.h deleted file mode 100644 index 59d8745eaf4a..000000000000 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_enums.h +++ /dev/null @@ -1,777 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * This header is autogenerated. Avoid modifying this file unless absolutely - * necessary. - */ - -#ifndef _MALI_KBASE_REGMAP_JM_ENUMS_H_ -#define _MALI_KBASE_REGMAP_JM_ENUMS_H_ - -#if MALI_USE_CSF -#error "Cannot be compiled with CSF" -#endif - -enum kbase_regmap_enum_v6_0 { - GPU_CONTROL__GPU_ID = 0, /* (RO) 32-bit 0x0 */ - GPU_CONTROL__L2_FEATURES, /* (RO) 32-bit 0x4 */ - GPU_CONTROL__TILER_FEATURES, /* (RO) 32-bit 0xC */ - GPU_CONTROL__MEM_FEATURES, /* (RO) 32-bit 0x10 */ - GPU_CONTROL__MMU_FEATURES, /* (RO) 32-bit 0x14 */ - GPU_CONTROL__AS_PRESENT, /* (RO) 32-bit 0x18 */ - GPU_CONTROL__JS_PRESENT, /* (RO) 32-bit 0x1C */ - GPU_CONTROL__GPU_IRQ_RAWSTAT, /* (RW) 32-bit 0x20 */ - GPU_CONTROL__GPU_IRQ_CLEAR, /* (WO) 32-bit 0x24 */ - GPU_CONTROL__GPU_IRQ_MASK, /* (RW) 32-bit 0x28 */ - GPU_CONTROL__GPU_IRQ_STATUS, /* (RO) 32-bit 0x2C */ - GPU_CONTROL__GPU_COMMAND, /* (WO) 32-bit 0x30 */ - GPU_CONTROL__GPU_STATUS, /* (RO) 32-bit 0x34 */ - GPU_CONTROL__LATEST_FLUSH, /* (RO) 32-bit 0x38 */ - GPU_CONTROL__GPU_FAULTSTATUS, /* (RO) 32-bit 0x3C */ - GPU_CONTROL__GPU_FAULTADDRESS, /* (RO) 64-bit 0x40 */ - GPU_CONTROL__AFBC_FEATURES, /* (RO) 32-bit 0x4C */ - GPU_CONTROL__PWR_KEY, /* (WO) 32-bit 0x50 */ - GPU_CONTROL__PWR_OVERRIDE0, /* (RW) 32-bit 0x54 */ - GPU_CONTROL__PWR_OVERRIDE1, /* (RW) 32-bit 0x58 */ - GPU_CONTROL__PRFCNT_BASE, /* (RW) 64-bit 0x60 */ - GPU_CONTROL__PRFCNT_CONFIG, /* (RW) 32-bit 0x68 */ - GPU_CONTROL__PRFCNT_JM_EN, /* (RW) 32-bit 0x6C */ - GPU_CONTROL__PRFCNT_SHADER_EN, /* (RW) 32-bit 0x70 */ - GPU_CONTROL__PRFCNT_TILER_EN, /* (RW) 32-bit 0x74 */ - GPU_CONTROL__PRFCNT_MMU_L2_EN, /* (RW) 32-bit 0x7C */ - GPU_CONTROL__CYCLE_COUNT, /* (RO) 64-bit 0x90 */ - GPU_CONTROL__TIMESTAMP, /* (RO) 64-bit 0x98 */ - GPU_CONTROL__THREAD_MAX_THREADS, /* (RO) 32-bit 0xA0 */ - GPU_CONTROL__THREAD_MAX_WORKGROUP_SIZE, /* (RO) 32-bit 0xA4 */ - GPU_CONTROL__THREAD_MAX_BARRIER_SIZE, /* (RO) 32-bit 0xA8 */ - GPU_CONTROL__THREAD_FEATURES, /* (RO) 32-bit 0xAC */ - GPU_CONTROL__TEXTURE_FEATURES_0, /* (RO) 32-bit 0xB0 */ - GPU_CONTROL__TEXTURE_FEATURES_1, /* (RO) 32-bit 0xB4 */ - GPU_CONTROL__TEXTURE_FEATURES_2, /* (RO) 32-bit 0xB8 */ - GPU_CONTROL__JS0_FEATURES, /* (RO) 32-bit 0xC0 */ - GPU_CONTROL__JS1_FEATURES, /* (RO) 32-bit 0xC4 */ - GPU_CONTROL__JS2_FEATURES, /* (RO) 32-bit 0xC8 */ - GPU_CONTROL__JS3_FEATURES, /* (RO) 32-bit 0xCC */ - GPU_CONTROL__JS4_FEATURES, /* (RO) 32-bit 0xD0 */ - GPU_CONTROL__JS5_FEATURES, /* (RO) 32-bit 0xD4 */ - GPU_CONTROL__JS6_FEATURES, /* (RO) 32-bit 0xD8 */ - GPU_CONTROL__JS7_FEATURES, /* (RO) 32-bit 0xDC */ - GPU_CONTROL__JS8_FEATURES, /* (RO) 32-bit 0xE0 */ - GPU_CONTROL__JS9_FEATURES, /* (RO) 32-bit 0xE4 */ - GPU_CONTROL__JS10_FEATURES, /* (RO) 32-bit 0xE8 */ - GPU_CONTROL__JS11_FEATURES, /* (RO) 32-bit 0xEC */ - GPU_CONTROL__JS12_FEATURES, /* (RO) 32-bit 0xF0 */ - GPU_CONTROL__JS13_FEATURES, /* (RO) 32-bit 0xF4 */ - GPU_CONTROL__JS14_FEATURES, /* (RO) 32-bit 0xF8 */ - GPU_CONTROL__JS15_FEATURES, /* (RO) 32-bit 0xFC */ - GPU_CONTROL__SHADER_PRESENT, /* (RO) 64-bit 0x100 */ - GPU_CONTROL__TILER_PRESENT, /* (RO) 64-bit 0x110 */ - GPU_CONTROL__L2_PRESENT, /* (RO) 64-bit 0x120 */ - GPU_CONTROL__SHADER_READY, /* (RO) 64-bit 0x140 */ - GPU_CONTROL__TILER_READY, /* (RO) 64-bit 0x150 */ - GPU_CONTROL__L2_READY, /* (RO) 64-bit 0x160 */ - GPU_CONTROL__SHADER_PWRON, /* (WO) 64-bit 0x180 */ - GPU_CONTROL__TILER_PWRON, /* (WO) 64-bit 0x190 */ - GPU_CONTROL__L2_PWRON, /* (WO) 64-bit 0x1A0 */ - GPU_CONTROL__SHADER_PWROFF, /* (WO) 64-bit 0x1C0 */ - GPU_CONTROL__TILER_PWROFF, /* (WO) 64-bit 0x1D0 */ - GPU_CONTROL__L2_PWROFF, /* (WO) 64-bit 0x1E0 */ - GPU_CONTROL__SHADER_PWRTRANS, /* (RO) 64-bit 0x200 */ - GPU_CONTROL__TILER_PWRTRANS, /* (RO) 64-bit 0x210 */ - GPU_CONTROL__L2_PWRTRANS, /* (RO) 64-bit 0x220 */ - GPU_CONTROL__SHADER_PWRACTIVE, /* (RO) 64-bit 0x240 */ - GPU_CONTROL__TILER_PWRACTIVE, /* (RO) 64-bit 0x250 */ - GPU_CONTROL__L2_PWRACTIVE, /* (RO) 64-bit 0x260 */ - GPU_CONTROL__COHERENCY_FEATURES, /* (RO) 32-bit 0x300 */ - GPU_CONTROL__COHERENCY_ENABLE, /* (RW) 32-bit 0x304 */ - GPU_CONTROL__GPU_USER_INn, /* (RO) 32-bit 0x400 */ - GPU_CONTROL__GPU_USER_OUTn, /* (RW) 32-bit 0x500 */ - GPU_CONTROL__JM_CONFIG, /* (RW) 32-bit 0xF00 */ - GPU_CONTROL__SHADER_CONFIG, /* (RW) 32-bit 0xF04 */ - GPU_CONTROL__TILER_CONFIG, /* (RW) 32-bit 0xF08 */ - GPU_CONTROL__L2_MMU_CONFIG, /* (RW) 32-bit 0xF0C */ - JOB_CONTROL__JOB_IRQ_RAWSTAT, /* (RW) 32-bit 0x1000 */ - JOB_CONTROL__JOB_IRQ_CLEAR, /* (WO) 32-bit 0x1004 */ - JOB_CONTROL__JOB_IRQ_MASK, /* (RW) 32-bit 0x1008 */ - JOB_CONTROL__JOB_IRQ_STATUS, /* (RO) 32-bit 0x100C */ - JOB_CONTROL__JOB_IRQ_JS_STATE, /* (RO) 32-bit 0x1010 */ - JOB_CONTROL__JOB_IRQ_THROTTLE, /* (RW) 32-bit 0x1014 */ - JOB_CONTROL__EVENT_IRQ_RAWSTAT, /* (RW) 32-bit 0x1020 */ - JOB_CONTROL__EVENT_IRQ_CLEAR, /* (WO) 32-bit 0x1024 */ - JOB_CONTROL__EVENT_IRQ_MASK, /* (RW) 32-bit 0x1028 */ - JOB_CONTROL__EVENT_IRQ_STATUS, /* (RO) 32-bit 0x102C */ - JOB_CONTROL__JS0__HEAD, /* (RO) 64-bit 0x1800 */ - JOB_CONTROL__JS0__TAIL, /* (RO) 64-bit 0x1808 */ - JOB_CONTROL__JS0__AFFINITY, /* (RO) 64-bit 0x1810 */ - JOB_CONTROL__JS0__CONFIG, /* (RO) 32-bit 0x1818 */ - JOB_CONTROL__JS0__XAFFINITY, /* (RO) 32-bit 0x181C */ - JOB_CONTROL__JS0__COMMAND, /* (RW) 32-bit 0x1820 */ - JOB_CONTROL__JS0__STATUS, /* (RO) 32-bit 0x1824 */ - JOB_CONTROL__JS0__FLUSH_ID, /* (RO) 32-bit 0x1830 */ - JOB_CONTROL__JS0__EVENT_0, /* (RW) 32-bit 0x1834 */ - JOB_CONTROL__JS0__EVENT_1, /* (RW) 32-bit 0x1838 */ - JOB_CONTROL__JS0__EVENT_MASK, /* (RW) 32-bit 0x183C */ - JOB_CONTROL__JS0__HEAD_NEXT, /* (RW) 64-bit 0x1840 */ - JOB_CONTROL__JS0__TAIL_NEXT, /* (RW) 64-bit 0x1848 */ - JOB_CONTROL__JS0__AFFINITY_NEXT, /* (RW) 64-bit 0x1850 */ - JOB_CONTROL__JS0__CONFIG_NEXT, /* (RW) 32-bit 0x1858 */ - JOB_CONTROL__JS0__XAFFINITY_NEXT, /* (RW) 32-bit 0x185C */ - JOB_CONTROL__JS0__COMMAND_NEXT, /* (RW) 32-bit 0x1860 */ - JOB_CONTROL__JS0__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1870 */ - JOB_CONTROL__JS0__EVENT_MASK_NEXT, /* (RW) 32-bit 0x187C */ - JOB_CONTROL__JS1__HEAD, /* (RO) 64-bit 0x1880 */ - JOB_CONTROL__JS1__TAIL, /* (RO) 64-bit 0x1888 */ - JOB_CONTROL__JS1__AFFINITY, /* (RO) 64-bit 0x1890 */ - JOB_CONTROL__JS1__CONFIG, /* (RO) 32-bit 0x1898 */ - JOB_CONTROL__JS1__XAFFINITY, /* (RO) 32-bit 0x189C */ - JOB_CONTROL__JS1__COMMAND, /* (RW) 32-bit 0x18A0 */ - JOB_CONTROL__JS1__STATUS, /* (RO) 32-bit 0x18A4 */ - JOB_CONTROL__JS1__FLUSH_ID, /* (RO) 32-bit 0x18B0 */ - JOB_CONTROL__JS1__EVENT_0, /* (RW) 32-bit 0x18B4 */ - JOB_CONTROL__JS1__EVENT_1, /* (RW) 32-bit 0x18B8 */ - JOB_CONTROL__JS1__EVENT_MASK, /* (RW) 32-bit 0x18BC */ - JOB_CONTROL__JS1__HEAD_NEXT, /* (RW) 64-bit 0x18C0 */ - JOB_CONTROL__JS1__TAIL_NEXT, /* (RW) 64-bit 0x18C8 */ - JOB_CONTROL__JS1__AFFINITY_NEXT, /* (RW) 64-bit 0x18D0 */ - JOB_CONTROL__JS1__CONFIG_NEXT, /* (RW) 32-bit 0x18D8 */ - JOB_CONTROL__JS1__XAFFINITY_NEXT, /* (RW) 32-bit 0x18DC */ - JOB_CONTROL__JS1__COMMAND_NEXT, /* (RW) 32-bit 0x18E0 */ - JOB_CONTROL__JS1__FLUSH_ID_NEXT, /* (RW) 32-bit 0x18F0 */ - JOB_CONTROL__JS1__EVENT_MASK_NEXT, /* (RW) 32-bit 0x18FC */ - JOB_CONTROL__JS2__HEAD, /* (RO) 64-bit 0x1900 */ - JOB_CONTROL__JS2__TAIL, /* (RO) 64-bit 0x1908 */ - JOB_CONTROL__JS2__AFFINITY, /* (RO) 64-bit 0x1910 */ - JOB_CONTROL__JS2__CONFIG, /* (RO) 32-bit 0x1918 */ - JOB_CONTROL__JS2__XAFFINITY, /* (RO) 32-bit 0x191C */ - JOB_CONTROL__JS2__COMMAND, /* (RW) 32-bit 0x1920 */ - JOB_CONTROL__JS2__STATUS, /* (RO) 32-bit 0x1924 */ - JOB_CONTROL__JS2__FLUSH_ID, /* (RO) 32-bit 0x1930 */ - JOB_CONTROL__JS2__EVENT_0, /* (RW) 32-bit 0x1934 */ - JOB_CONTROL__JS2__EVENT_1, /* (RW) 32-bit 0x1938 */ - JOB_CONTROL__JS2__EVENT_MASK, /* (RW) 32-bit 0x193C */ - JOB_CONTROL__JS2__HEAD_NEXT, /* (RW) 64-bit 0x1940 */ - JOB_CONTROL__JS2__TAIL_NEXT, /* (RW) 64-bit 0x1948 */ - JOB_CONTROL__JS2__AFFINITY_NEXT, /* (RW) 64-bit 0x1950 */ - JOB_CONTROL__JS2__CONFIG_NEXT, /* (RW) 32-bit 0x1958 */ - JOB_CONTROL__JS2__XAFFINITY_NEXT, /* (RW) 32-bit 0x195C */ - JOB_CONTROL__JS2__COMMAND_NEXT, /* (RW) 32-bit 0x1960 */ - JOB_CONTROL__JS2__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1970 */ - JOB_CONTROL__JS2__EVENT_MASK_NEXT, /* (RW) 32-bit 0x197C */ - JOB_CONTROL__JS3__HEAD, /* (RO) 64-bit 0x1980 */ - JOB_CONTROL__JS3__TAIL, /* (RO) 64-bit 0x1988 */ - JOB_CONTROL__JS3__AFFINITY, /* (RO) 64-bit 0x1990 */ - JOB_CONTROL__JS3__CONFIG, /* (RO) 32-bit 0x1998 */ - JOB_CONTROL__JS3__XAFFINITY, /* (RO) 32-bit 0x199C */ - JOB_CONTROL__JS3__COMMAND, /* (RW) 32-bit 0x19A0 */ - JOB_CONTROL__JS3__STATUS, /* (RO) 32-bit 0x19A4 */ - JOB_CONTROL__JS3__FLUSH_ID, /* (RO) 32-bit 0x19B0 */ - JOB_CONTROL__JS3__EVENT_0, /* (RW) 32-bit 0x19B4 */ - JOB_CONTROL__JS3__EVENT_1, /* (RW) 32-bit 0x19B8 */ - JOB_CONTROL__JS3__EVENT_MASK, /* (RW) 32-bit 0x19BC */ - JOB_CONTROL__JS3__HEAD_NEXT, /* (RW) 64-bit 0x19C0 */ - JOB_CONTROL__JS3__TAIL_NEXT, /* (RW) 64-bit 0x19C8 */ - JOB_CONTROL__JS3__AFFINITY_NEXT, /* (RW) 64-bit 0x19D0 */ - JOB_CONTROL__JS3__CONFIG_NEXT, /* (RW) 32-bit 0x19D8 */ - JOB_CONTROL__JS3__XAFFINITY_NEXT, /* (RW) 32-bit 0x19DC */ - JOB_CONTROL__JS3__COMMAND_NEXT, /* (RW) 32-bit 0x19E0 */ - JOB_CONTROL__JS3__FLUSH_ID_NEXT, /* (RW) 32-bit 0x19F0 */ - JOB_CONTROL__JS3__EVENT_MASK_NEXT, /* (RW) 32-bit 0x19FC */ - JOB_CONTROL__JS4__HEAD, /* (RO) 64-bit 0x1A00 */ - JOB_CONTROL__JS4__TAIL, /* (RO) 64-bit 0x1A08 */ - JOB_CONTROL__JS4__AFFINITY, /* (RO) 64-bit 0x1A10 */ - JOB_CONTROL__JS4__CONFIG, /* (RO) 32-bit 0x1A18 */ - JOB_CONTROL__JS4__XAFFINITY, /* (RO) 32-bit 0x1A1C */ - JOB_CONTROL__JS4__COMMAND, /* (RW) 32-bit 0x1A20 */ - JOB_CONTROL__JS4__STATUS, /* (RO) 32-bit 0x1A24 */ - JOB_CONTROL__JS4__FLUSH_ID, /* (RO) 32-bit 0x1A30 */ - JOB_CONTROL__JS4__EVENT_0, /* (RW) 32-bit 0x1A34 */ - JOB_CONTROL__JS4__EVENT_1, /* (RW) 32-bit 0x1A38 */ - JOB_CONTROL__JS4__EVENT_MASK, /* (RW) 32-bit 0x1A3C */ - JOB_CONTROL__JS4__HEAD_NEXT, /* (RW) 64-bit 0x1A40 */ - JOB_CONTROL__JS4__TAIL_NEXT, /* (RW) 64-bit 0x1A48 */ - JOB_CONTROL__JS4__AFFINITY_NEXT, /* (RW) 64-bit 0x1A50 */ - JOB_CONTROL__JS4__CONFIG_NEXT, /* (RW) 32-bit 0x1A58 */ - JOB_CONTROL__JS4__XAFFINITY_NEXT, /* (RW) 32-bit 0x1A5C */ - JOB_CONTROL__JS4__COMMAND_NEXT, /* (RW) 32-bit 0x1A60 */ - JOB_CONTROL__JS4__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1A70 */ - JOB_CONTROL__JS4__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1A7C */ - JOB_CONTROL__JS5__HEAD, /* (RO) 64-bit 0x1A80 */ - JOB_CONTROL__JS5__TAIL, /* (RO) 64-bit 0x1A88 */ - JOB_CONTROL__JS5__AFFINITY, /* (RO) 64-bit 0x1A90 */ - JOB_CONTROL__JS5__CONFIG, /* (RO) 32-bit 0x1A98 */ - JOB_CONTROL__JS5__XAFFINITY, /* (RO) 32-bit 0x1A9C */ - JOB_CONTROL__JS5__COMMAND, /* (RW) 32-bit 0x1AA0 */ - JOB_CONTROL__JS5__STATUS, /* (RO) 32-bit 0x1AA4 */ - JOB_CONTROL__JS5__FLUSH_ID, /* (RO) 32-bit 0x1AB0 */ - JOB_CONTROL__JS5__EVENT_0, /* (RW) 32-bit 0x1AB4 */ - JOB_CONTROL__JS5__EVENT_1, /* (RW) 32-bit 0x1AB8 */ - JOB_CONTROL__JS5__EVENT_MASK, /* (RW) 32-bit 0x1ABC */ - JOB_CONTROL__JS5__HEAD_NEXT, /* (RW) 64-bit 0x1AC0 */ - JOB_CONTROL__JS5__TAIL_NEXT, /* (RW) 64-bit 0x1AC8 */ - JOB_CONTROL__JS5__AFFINITY_NEXT, /* (RW) 64-bit 0x1AD0 */ - JOB_CONTROL__JS5__CONFIG_NEXT, /* (RW) 32-bit 0x1AD8 */ - JOB_CONTROL__JS5__XAFFINITY_NEXT, /* (RW) 32-bit 0x1ADC */ - JOB_CONTROL__JS5__COMMAND_NEXT, /* (RW) 32-bit 0x1AE0 */ - JOB_CONTROL__JS5__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1AF0 */ - JOB_CONTROL__JS5__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1AFC */ - JOB_CONTROL__JS6__HEAD, /* (RO) 64-bit 0x1B00 */ - JOB_CONTROL__JS6__TAIL, /* (RO) 64-bit 0x1B08 */ - JOB_CONTROL__JS6__AFFINITY, /* (RO) 64-bit 0x1B10 */ - JOB_CONTROL__JS6__CONFIG, /* (RO) 32-bit 0x1B18 */ - JOB_CONTROL__JS6__XAFFINITY, /* (RO) 32-bit 0x1B1C */ - JOB_CONTROL__JS6__COMMAND, /* (RW) 32-bit 0x1B20 */ - JOB_CONTROL__JS6__STATUS, /* (RO) 32-bit 0x1B24 */ - JOB_CONTROL__JS6__FLUSH_ID, /* (RO) 32-bit 0x1B30 */ - JOB_CONTROL__JS6__EVENT_0, /* (RW) 32-bit 0x1B34 */ - JOB_CONTROL__JS6__EVENT_1, /* (RW) 32-bit 0x1B38 */ - JOB_CONTROL__JS6__EVENT_MASK, /* (RW) 32-bit 0x1B3C */ - JOB_CONTROL__JS6__HEAD_NEXT, /* (RW) 64-bit 0x1B40 */ - JOB_CONTROL__JS6__TAIL_NEXT, /* (RW) 64-bit 0x1B48 */ - JOB_CONTROL__JS6__AFFINITY_NEXT, /* (RW) 64-bit 0x1B50 */ - JOB_CONTROL__JS6__CONFIG_NEXT, /* (RW) 32-bit 0x1B58 */ - JOB_CONTROL__JS6__XAFFINITY_NEXT, /* (RW) 32-bit 0x1B5C */ - JOB_CONTROL__JS6__COMMAND_NEXT, /* (RW) 32-bit 0x1B60 */ - JOB_CONTROL__JS6__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1B70 */ - JOB_CONTROL__JS6__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1B7C */ - JOB_CONTROL__JS7__HEAD, /* (RO) 64-bit 0x1B80 */ - JOB_CONTROL__JS7__TAIL, /* (RO) 64-bit 0x1B88 */ - JOB_CONTROL__JS7__AFFINITY, /* (RO) 64-bit 0x1B90 */ - JOB_CONTROL__JS7__CONFIG, /* (RO) 32-bit 0x1B98 */ - JOB_CONTROL__JS7__XAFFINITY, /* (RO) 32-bit 0x1B9C */ - JOB_CONTROL__JS7__COMMAND, /* (RW) 32-bit 0x1BA0 */ - JOB_CONTROL__JS7__STATUS, /* (RO) 32-bit 0x1BA4 */ - JOB_CONTROL__JS7__FLUSH_ID, /* (RO) 32-bit 0x1BB0 */ - JOB_CONTROL__JS7__EVENT_0, /* (RW) 32-bit 0x1BB4 */ - JOB_CONTROL__JS7__EVENT_1, /* (RW) 32-bit 0x1BB8 */ - JOB_CONTROL__JS7__EVENT_MASK, /* (RW) 32-bit 0x1BBC */ - JOB_CONTROL__JS7__HEAD_NEXT, /* (RW) 64-bit 0x1BC0 */ - JOB_CONTROL__JS7__TAIL_NEXT, /* (RW) 64-bit 0x1BC8 */ - JOB_CONTROL__JS7__AFFINITY_NEXT, /* (RW) 64-bit 0x1BD0 */ - JOB_CONTROL__JS7__CONFIG_NEXT, /* (RW) 32-bit 0x1BD8 */ - JOB_CONTROL__JS7__XAFFINITY_NEXT, /* (RW) 32-bit 0x1BDC */ - JOB_CONTROL__JS7__COMMAND_NEXT, /* (RW) 32-bit 0x1BE0 */ - JOB_CONTROL__JS7__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1BF0 */ - JOB_CONTROL__JS7__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1BFC */ - JOB_CONTROL__JS8__HEAD, /* (RO) 64-bit 0x1C00 */ - JOB_CONTROL__JS8__TAIL, /* (RO) 64-bit 0x1C08 */ - JOB_CONTROL__JS8__AFFINITY, /* (RO) 64-bit 0x1C10 */ - JOB_CONTROL__JS8__CONFIG, /* (RO) 32-bit 0x1C18 */ - JOB_CONTROL__JS8__XAFFINITY, /* (RO) 32-bit 0x1C1C */ - JOB_CONTROL__JS8__COMMAND, /* (RW) 32-bit 0x1C20 */ - JOB_CONTROL__JS8__STATUS, /* (RO) 32-bit 0x1C24 */ - JOB_CONTROL__JS8__FLUSH_ID, /* (RO) 32-bit 0x1C30 */ - JOB_CONTROL__JS8__EVENT_0, /* (RW) 32-bit 0x1C34 */ - JOB_CONTROL__JS8__EVENT_1, /* (RW) 32-bit 0x1C38 */ - JOB_CONTROL__JS8__EVENT_MASK, /* (RW) 32-bit 0x1C3C */ - JOB_CONTROL__JS8__HEAD_NEXT, /* (RW) 64-bit 0x1C40 */ - JOB_CONTROL__JS8__TAIL_NEXT, /* (RW) 64-bit 0x1C48 */ - JOB_CONTROL__JS8__AFFINITY_NEXT, /* (RW) 64-bit 0x1C50 */ - JOB_CONTROL__JS8__CONFIG_NEXT, /* (RW) 32-bit 0x1C58 */ - JOB_CONTROL__JS8__XAFFINITY_NEXT, /* (RW) 32-bit 0x1C5C */ - JOB_CONTROL__JS8__COMMAND_NEXT, /* (RW) 32-bit 0x1C60 */ - JOB_CONTROL__JS8__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1C70 */ - JOB_CONTROL__JS8__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1C7C */ - JOB_CONTROL__JS9__HEAD, /* (RO) 64-bit 0x1C80 */ - JOB_CONTROL__JS9__TAIL, /* (RO) 64-bit 0x1C88 */ - JOB_CONTROL__JS9__AFFINITY, /* (RO) 64-bit 0x1C90 */ - JOB_CONTROL__JS9__CONFIG, /* (RO) 32-bit 0x1C98 */ - JOB_CONTROL__JS9__XAFFINITY, /* (RO) 32-bit 0x1C9C */ - JOB_CONTROL__JS9__COMMAND, /* (RW) 32-bit 0x1CA0 */ - JOB_CONTROL__JS9__STATUS, /* (RO) 32-bit 0x1CA4 */ - JOB_CONTROL__JS9__FLUSH_ID, /* (RO) 32-bit 0x1CB0 */ - JOB_CONTROL__JS9__EVENT_0, /* (RW) 32-bit 0x1CB4 */ - JOB_CONTROL__JS9__EVENT_1, /* (RW) 32-bit 0x1CB8 */ - JOB_CONTROL__JS9__EVENT_MASK, /* (RW) 32-bit 0x1CBC */ - JOB_CONTROL__JS9__HEAD_NEXT, /* (RW) 64-bit 0x1CC0 */ - JOB_CONTROL__JS9__TAIL_NEXT, /* (RW) 64-bit 0x1CC8 */ - JOB_CONTROL__JS9__AFFINITY_NEXT, /* (RW) 64-bit 0x1CD0 */ - JOB_CONTROL__JS9__CONFIG_NEXT, /* (RW) 32-bit 0x1CD8 */ - JOB_CONTROL__JS9__XAFFINITY_NEXT, /* (RW) 32-bit 0x1CDC */ - JOB_CONTROL__JS9__COMMAND_NEXT, /* (RW) 32-bit 0x1CE0 */ - JOB_CONTROL__JS9__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1CF0 */ - JOB_CONTROL__JS9__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1CFC */ - JOB_CONTROL__JS10__HEAD, /* (RO) 64-bit 0x1D00 */ - JOB_CONTROL__JS10__TAIL, /* (RO) 64-bit 0x1D08 */ - JOB_CONTROL__JS10__AFFINITY, /* (RO) 64-bit 0x1D10 */ - JOB_CONTROL__JS10__CONFIG, /* (RO) 32-bit 0x1D18 */ - JOB_CONTROL__JS10__XAFFINITY, /* (RO) 32-bit 0x1D1C */ - JOB_CONTROL__JS10__COMMAND, /* (RW) 32-bit 0x1D20 */ - JOB_CONTROL__JS10__STATUS, /* (RO) 32-bit 0x1D24 */ - JOB_CONTROL__JS10__FLUSH_ID, /* (RO) 32-bit 0x1D30 */ - JOB_CONTROL__JS10__EVENT_0, /* (RW) 32-bit 0x1D34 */ - JOB_CONTROL__JS10__EVENT_1, /* (RW) 32-bit 0x1D38 */ - JOB_CONTROL__JS10__EVENT_MASK, /* (RW) 32-bit 0x1D3C */ - JOB_CONTROL__JS10__HEAD_NEXT, /* (RW) 64-bit 0x1D40 */ - JOB_CONTROL__JS10__TAIL_NEXT, /* (RW) 64-bit 0x1D48 */ - JOB_CONTROL__JS10__AFFINITY_NEXT, /* (RW) 64-bit 0x1D50 */ - JOB_CONTROL__JS10__CONFIG_NEXT, /* (RW) 32-bit 0x1D58 */ - JOB_CONTROL__JS10__XAFFINITY_NEXT, /* (RW) 32-bit 0x1D5C */ - JOB_CONTROL__JS10__COMMAND_NEXT, /* (RW) 32-bit 0x1D60 */ - JOB_CONTROL__JS10__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1D70 */ - JOB_CONTROL__JS10__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1D7C */ - JOB_CONTROL__JS11__HEAD, /* (RO) 64-bit 0x1D80 */ - JOB_CONTROL__JS11__TAIL, /* (RO) 64-bit 0x1D88 */ - JOB_CONTROL__JS11__AFFINITY, /* (RO) 64-bit 0x1D90 */ - JOB_CONTROL__JS11__CONFIG, /* (RO) 32-bit 0x1D98 */ - JOB_CONTROL__JS11__XAFFINITY, /* (RO) 32-bit 0x1D9C */ - JOB_CONTROL__JS11__COMMAND, /* (RW) 32-bit 0x1DA0 */ - JOB_CONTROL__JS11__STATUS, /* (RO) 32-bit 0x1DA4 */ - JOB_CONTROL__JS11__FLUSH_ID, /* (RO) 32-bit 0x1DB0 */ - JOB_CONTROL__JS11__EVENT_0, /* (RW) 32-bit 0x1DB4 */ - JOB_CONTROL__JS11__EVENT_1, /* (RW) 32-bit 0x1DB8 */ - JOB_CONTROL__JS11__EVENT_MASK, /* (RW) 32-bit 0x1DBC */ - JOB_CONTROL__JS11__HEAD_NEXT, /* (RW) 64-bit 0x1DC0 */ - JOB_CONTROL__JS11__TAIL_NEXT, /* (RW) 64-bit 0x1DC8 */ - JOB_CONTROL__JS11__AFFINITY_NEXT, /* (RW) 64-bit 0x1DD0 */ - JOB_CONTROL__JS11__CONFIG_NEXT, /* (RW) 32-bit 0x1DD8 */ - JOB_CONTROL__JS11__XAFFINITY_NEXT, /* (RW) 32-bit 0x1DDC */ - JOB_CONTROL__JS11__COMMAND_NEXT, /* (RW) 32-bit 0x1DE0 */ - JOB_CONTROL__JS11__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1DF0 */ - JOB_CONTROL__JS11__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1DFC */ - JOB_CONTROL__JS12__HEAD, /* (RO) 64-bit 0x1E00 */ - JOB_CONTROL__JS12__TAIL, /* (RO) 64-bit 0x1E08 */ - JOB_CONTROL__JS12__AFFINITY, /* (RO) 64-bit 0x1E10 */ - JOB_CONTROL__JS12__CONFIG, /* (RO) 32-bit 0x1E18 */ - JOB_CONTROL__JS12__XAFFINITY, /* (RO) 32-bit 0x1E1C */ - JOB_CONTROL__JS12__COMMAND, /* (RW) 32-bit 0x1E20 */ - JOB_CONTROL__JS12__STATUS, /* (RO) 32-bit 0x1E24 */ - JOB_CONTROL__JS12__FLUSH_ID, /* (RO) 32-bit 0x1E30 */ - JOB_CONTROL__JS12__EVENT_0, /* (RW) 32-bit 0x1E34 */ - JOB_CONTROL__JS12__EVENT_1, /* (RW) 32-bit 0x1E38 */ - JOB_CONTROL__JS12__EVENT_MASK, /* (RW) 32-bit 0x1E3C */ - JOB_CONTROL__JS12__HEAD_NEXT, /* (RW) 64-bit 0x1E40 */ - JOB_CONTROL__JS12__TAIL_NEXT, /* (RW) 64-bit 0x1E48 */ - JOB_CONTROL__JS12__AFFINITY_NEXT, /* (RW) 64-bit 0x1E50 */ - JOB_CONTROL__JS12__CONFIG_NEXT, /* (RW) 32-bit 0x1E58 */ - JOB_CONTROL__JS12__XAFFINITY_NEXT, /* (RW) 32-bit 0x1E5C */ - JOB_CONTROL__JS12__COMMAND_NEXT, /* (RW) 32-bit 0x1E60 */ - JOB_CONTROL__JS12__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1E70 */ - JOB_CONTROL__JS12__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1E7C */ - JOB_CONTROL__JS13__HEAD, /* (RO) 64-bit 0x1E80 */ - JOB_CONTROL__JS13__TAIL, /* (RO) 64-bit 0x1E88 */ - JOB_CONTROL__JS13__AFFINITY, /* (RO) 64-bit 0x1E90 */ - JOB_CONTROL__JS13__CONFIG, /* (RO) 32-bit 0x1E98 */ - JOB_CONTROL__JS13__XAFFINITY, /* (RO) 32-bit 0x1E9C */ - JOB_CONTROL__JS13__COMMAND, /* (RW) 32-bit 0x1EA0 */ - JOB_CONTROL__JS13__STATUS, /* (RO) 32-bit 0x1EA4 */ - JOB_CONTROL__JS13__FLUSH_ID, /* (RO) 32-bit 0x1EB0 */ - JOB_CONTROL__JS13__EVENT_0, /* (RW) 32-bit 0x1EB4 */ - JOB_CONTROL__JS13__EVENT_1, /* (RW) 32-bit 0x1EB8 */ - JOB_CONTROL__JS13__EVENT_MASK, /* (RW) 32-bit 0x1EBC */ - JOB_CONTROL__JS13__HEAD_NEXT, /* (RW) 64-bit 0x1EC0 */ - JOB_CONTROL__JS13__TAIL_NEXT, /* (RW) 64-bit 0x1EC8 */ - JOB_CONTROL__JS13__AFFINITY_NEXT, /* (RW) 64-bit 0x1ED0 */ - JOB_CONTROL__JS13__CONFIG_NEXT, /* (RW) 32-bit 0x1ED8 */ - JOB_CONTROL__JS13__XAFFINITY_NEXT, /* (RW) 32-bit 0x1EDC */ - JOB_CONTROL__JS13__COMMAND_NEXT, /* (RW) 32-bit 0x1EE0 */ - JOB_CONTROL__JS13__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1EF0 */ - JOB_CONTROL__JS13__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1EFC */ - JOB_CONTROL__JS14__HEAD, /* (RO) 64-bit 0x1F00 */ - JOB_CONTROL__JS14__TAIL, /* (RO) 64-bit 0x1F08 */ - JOB_CONTROL__JS14__AFFINITY, /* (RO) 64-bit 0x1F10 */ - JOB_CONTROL__JS14__CONFIG, /* (RO) 32-bit 0x1F18 */ - JOB_CONTROL__JS14__XAFFINITY, /* (RO) 32-bit 0x1F1C */ - JOB_CONTROL__JS14__COMMAND, /* (RW) 32-bit 0x1F20 */ - JOB_CONTROL__JS14__STATUS, /* (RO) 32-bit 0x1F24 */ - JOB_CONTROL__JS14__FLUSH_ID, /* (RO) 32-bit 0x1F30 */ - JOB_CONTROL__JS14__EVENT_0, /* (RW) 32-bit 0x1F34 */ - JOB_CONTROL__JS14__EVENT_1, /* (RW) 32-bit 0x1F38 */ - JOB_CONTROL__JS14__EVENT_MASK, /* (RW) 32-bit 0x1F3C */ - JOB_CONTROL__JS14__HEAD_NEXT, /* (RW) 64-bit 0x1F40 */ - JOB_CONTROL__JS14__TAIL_NEXT, /* (RW) 64-bit 0x1F48 */ - JOB_CONTROL__JS14__AFFINITY_NEXT, /* (RW) 64-bit 0x1F50 */ - JOB_CONTROL__JS14__CONFIG_NEXT, /* (RW) 32-bit 0x1F58 */ - JOB_CONTROL__JS14__XAFFINITY_NEXT, /* (RW) 32-bit 0x1F5C */ - JOB_CONTROL__JS14__COMMAND_NEXT, /* (RW) 32-bit 0x1F60 */ - JOB_CONTROL__JS14__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1F70 */ - JOB_CONTROL__JS14__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1F7C */ - JOB_CONTROL__JS15__HEAD, /* (RO) 64-bit 0x1F80 */ - JOB_CONTROL__JS15__TAIL, /* (RO) 64-bit 0x1F88 */ - JOB_CONTROL__JS15__AFFINITY, /* (RO) 64-bit 0x1F90 */ - JOB_CONTROL__JS15__CONFIG, /* (RO) 32-bit 0x1F98 */ - JOB_CONTROL__JS15__XAFFINITY, /* (RO) 32-bit 0x1F9C */ - JOB_CONTROL__JS15__COMMAND, /* (RW) 32-bit 0x1FA0 */ - JOB_CONTROL__JS15__STATUS, /* (RO) 32-bit 0x1FA4 */ - JOB_CONTROL__JS15__FLUSH_ID, /* (RO) 32-bit 0x1FB0 */ - JOB_CONTROL__JS15__EVENT_0, /* (RW) 32-bit 0x1FB4 */ - JOB_CONTROL__JS15__EVENT_1, /* (RW) 32-bit 0x1FB8 */ - JOB_CONTROL__JS15__EVENT_MASK, /* (RW) 32-bit 0x1FBC */ - JOB_CONTROL__JS15__HEAD_NEXT, /* (RW) 64-bit 0x1FC0 */ - JOB_CONTROL__JS15__TAIL_NEXT, /* (RW) 64-bit 0x1FC8 */ - JOB_CONTROL__JS15__AFFINITY_NEXT, /* (RW) 64-bit 0x1FD0 */ - JOB_CONTROL__JS15__CONFIG_NEXT, /* (RW) 32-bit 0x1FD8 */ - JOB_CONTROL__JS15__XAFFINITY_NEXT, /* (RW) 32-bit 0x1FDC */ - JOB_CONTROL__JS15__COMMAND_NEXT, /* (RW) 32-bit 0x1FE0 */ - JOB_CONTROL__JS15__FLUSH_ID_NEXT, /* (RW) 32-bit 0x1FF0 */ - JOB_CONTROL__JS15__EVENT_MASK_NEXT, /* (RW) 32-bit 0x1FFC */ - MMU_STAGE1__ST1MMU__IRQ_RAWSTAT, /* (RW) 32-bit 0x2000 */ - MMU_STAGE1__ST1MMU__IRQ_CLEAR, /* (WO) 32-bit 0x2004 */ - MMU_STAGE1__ST1MMU__IRQ_MASK, /* (RW) 32-bit 0x2008 */ - MMU_STAGE1__ST1MMU__IRQ_STATUS, /* (RO) 32-bit 0x200C */ - MMU_STAGE1__ST1MMU__AS0__TRANSTAB, /* (RW) 64-bit 0x2400 */ - MMU_STAGE1__ST1MMU__AS0__MEMATTR, /* (RW) 64-bit 0x2408 */ - MMU_STAGE1__ST1MMU__AS0__LOCKADDR, /* (RW) 64-bit 0x2410 */ - MMU_STAGE1__ST1MMU__AS0__COMMAND, /* (WO) 32-bit 0x2418 */ - MMU_STAGE1__ST1MMU__AS0__FAULTSTATUS, /* (RO) 32-bit 0x241C */ - MMU_STAGE1__ST1MMU__AS0__FAULTADDRESS, /* (RO) 64-bit 0x2420 */ - MMU_STAGE1__ST1MMU__AS0__STATUS, /* (RO) 32-bit 0x2428 */ - MMU_STAGE1__ST1MMU__AS0__TRANSCFG, /* (RW) 64-bit 0x2430 */ - MMU_STAGE1__ST1MMU__AS0__FAULTEXTRA, /* (RO) 64-bit 0x2438 */ - MMU_STAGE1__ST1MMU__AS1__TRANSTAB, /* (RW) 64-bit 0x2440 */ - MMU_STAGE1__ST1MMU__AS1__MEMATTR, /* (RW) 64-bit 0x2448 */ - MMU_STAGE1__ST1MMU__AS1__LOCKADDR, /* (RW) 64-bit 0x2450 */ - MMU_STAGE1__ST1MMU__AS1__COMMAND, /* (WO) 32-bit 0x2458 */ - MMU_STAGE1__ST1MMU__AS1__FAULTSTATUS, /* (RO) 32-bit 0x245C */ - MMU_STAGE1__ST1MMU__AS1__FAULTADDRESS, /* (RO) 64-bit 0x2460 */ - MMU_STAGE1__ST1MMU__AS1__STATUS, /* (RO) 32-bit 0x2468 */ - MMU_STAGE1__ST1MMU__AS1__TRANSCFG, /* (RW) 64-bit 0x2470 */ - MMU_STAGE1__ST1MMU__AS1__FAULTEXTRA, /* (RO) 64-bit 0x2478 */ - MMU_STAGE1__ST1MMU__AS2__TRANSTAB, /* (RW) 64-bit 0x2480 */ - MMU_STAGE1__ST1MMU__AS2__MEMATTR, /* (RW) 64-bit 0x2488 */ - MMU_STAGE1__ST1MMU__AS2__LOCKADDR, /* (RW) 64-bit 0x2490 */ - MMU_STAGE1__ST1MMU__AS2__COMMAND, /* (WO) 32-bit 0x2498 */ - MMU_STAGE1__ST1MMU__AS2__FAULTSTATUS, /* (RO) 32-bit 0x249C */ - MMU_STAGE1__ST1MMU__AS2__FAULTADDRESS, /* (RO) 64-bit 0x24A0 */ - MMU_STAGE1__ST1MMU__AS2__STATUS, /* (RO) 32-bit 0x24A8 */ - MMU_STAGE1__ST1MMU__AS2__TRANSCFG, /* (RW) 64-bit 0x24B0 */ - MMU_STAGE1__ST1MMU__AS2__FAULTEXTRA, /* (RO) 64-bit 0x24B8 */ - MMU_STAGE1__ST1MMU__AS3__TRANSTAB, /* (RW) 64-bit 0x24C0 */ - MMU_STAGE1__ST1MMU__AS3__MEMATTR, /* (RW) 64-bit 0x24C8 */ - MMU_STAGE1__ST1MMU__AS3__LOCKADDR, /* (RW) 64-bit 0x24D0 */ - MMU_STAGE1__ST1MMU__AS3__COMMAND, /* (WO) 32-bit 0x24D8 */ - MMU_STAGE1__ST1MMU__AS3__FAULTSTATUS, /* (RO) 32-bit 0x24DC */ - MMU_STAGE1__ST1MMU__AS3__FAULTADDRESS, /* (RO) 64-bit 0x24E0 */ - MMU_STAGE1__ST1MMU__AS3__STATUS, /* (RO) 32-bit 0x24E8 */ - MMU_STAGE1__ST1MMU__AS3__TRANSCFG, /* (RW) 64-bit 0x24F0 */ - MMU_STAGE1__ST1MMU__AS3__FAULTEXTRA, /* (RO) 64-bit 0x24F8 */ - MMU_STAGE1__ST1MMU__AS4__TRANSTAB, /* (RW) 64-bit 0x2500 */ - MMU_STAGE1__ST1MMU__AS4__MEMATTR, /* (RW) 64-bit 0x2508 */ - MMU_STAGE1__ST1MMU__AS4__LOCKADDR, /* (RW) 64-bit 0x2510 */ - MMU_STAGE1__ST1MMU__AS4__COMMAND, /* (WO) 32-bit 0x2518 */ - MMU_STAGE1__ST1MMU__AS4__FAULTSTATUS, /* (RO) 32-bit 0x251C */ - MMU_STAGE1__ST1MMU__AS4__FAULTADDRESS, /* (RO) 64-bit 0x2520 */ - MMU_STAGE1__ST1MMU__AS4__STATUS, /* (RO) 32-bit 0x2528 */ - MMU_STAGE1__ST1MMU__AS4__TRANSCFG, /* (RW) 64-bit 0x2530 */ - MMU_STAGE1__ST1MMU__AS4__FAULTEXTRA, /* (RO) 64-bit 0x2538 */ - MMU_STAGE1__ST1MMU__AS5__TRANSTAB, /* (RW) 64-bit 0x2540 */ - MMU_STAGE1__ST1MMU__AS5__MEMATTR, /* (RW) 64-bit 0x2548 */ - MMU_STAGE1__ST1MMU__AS5__LOCKADDR, /* (RW) 64-bit 0x2550 */ - MMU_STAGE1__ST1MMU__AS5__COMMAND, /* (WO) 32-bit 0x2558 */ - MMU_STAGE1__ST1MMU__AS5__FAULTSTATUS, /* (RO) 32-bit 0x255C */ - MMU_STAGE1__ST1MMU__AS5__FAULTADDRESS, /* (RO) 64-bit 0x2560 */ - MMU_STAGE1__ST1MMU__AS5__STATUS, /* (RO) 32-bit 0x2568 */ - MMU_STAGE1__ST1MMU__AS5__TRANSCFG, /* (RW) 64-bit 0x2570 */ - MMU_STAGE1__ST1MMU__AS5__FAULTEXTRA, /* (RO) 64-bit 0x2578 */ - MMU_STAGE1__ST1MMU__AS6__TRANSTAB, /* (RW) 64-bit 0x2580 */ - MMU_STAGE1__ST1MMU__AS6__MEMATTR, /* (RW) 64-bit 0x2588 */ - MMU_STAGE1__ST1MMU__AS6__LOCKADDR, /* (RW) 64-bit 0x2590 */ - MMU_STAGE1__ST1MMU__AS6__COMMAND, /* (WO) 32-bit 0x2598 */ - MMU_STAGE1__ST1MMU__AS6__FAULTSTATUS, /* (RO) 32-bit 0x259C */ - MMU_STAGE1__ST1MMU__AS6__FAULTADDRESS, /* (RO) 64-bit 0x25A0 */ - MMU_STAGE1__ST1MMU__AS6__STATUS, /* (RO) 32-bit 0x25A8 */ - MMU_STAGE1__ST1MMU__AS6__TRANSCFG, /* (RW) 64-bit 0x25B0 */ - MMU_STAGE1__ST1MMU__AS6__FAULTEXTRA, /* (RO) 64-bit 0x25B8 */ - MMU_STAGE1__ST1MMU__AS7__TRANSTAB, /* (RW) 64-bit 0x25C0 */ - MMU_STAGE1__ST1MMU__AS7__MEMATTR, /* (RW) 64-bit 0x25C8 */ - MMU_STAGE1__ST1MMU__AS7__LOCKADDR, /* (RW) 64-bit 0x25D0 */ - MMU_STAGE1__ST1MMU__AS7__COMMAND, /* (WO) 32-bit 0x25D8 */ - MMU_STAGE1__ST1MMU__AS7__FAULTSTATUS, /* (RO) 32-bit 0x25DC */ - MMU_STAGE1__ST1MMU__AS7__FAULTADDRESS, /* (RO) 64-bit 0x25E0 */ - MMU_STAGE1__ST1MMU__AS7__STATUS, /* (RO) 32-bit 0x25E8 */ - MMU_STAGE1__ST1MMU__AS7__TRANSCFG, /* (RW) 64-bit 0x25F0 */ - MMU_STAGE1__ST1MMU__AS7__FAULTEXTRA, /* (RO) 64-bit 0x25F8 */ - MMU_STAGE1__ST1MMU__AS8__TRANSTAB, /* (RW) 64-bit 0x2600 */ - MMU_STAGE1__ST1MMU__AS8__MEMATTR, /* (RW) 64-bit 0x2608 */ - MMU_STAGE1__ST1MMU__AS8__LOCKADDR, /* (RW) 64-bit 0x2610 */ - MMU_STAGE1__ST1MMU__AS8__COMMAND, /* (WO) 32-bit 0x2618 */ - MMU_STAGE1__ST1MMU__AS8__FAULTSTATUS, /* (RO) 32-bit 0x261C */ - MMU_STAGE1__ST1MMU__AS8__FAULTADDRESS, /* (RO) 64-bit 0x2620 */ - MMU_STAGE1__ST1MMU__AS8__STATUS, /* (RO) 32-bit 0x2628 */ - MMU_STAGE1__ST1MMU__AS8__TRANSCFG, /* (RW) 64-bit 0x2630 */ - MMU_STAGE1__ST1MMU__AS8__FAULTEXTRA, /* (RO) 64-bit 0x2638 */ - MMU_STAGE1__ST1MMU__AS9__TRANSTAB, /* (RW) 64-bit 0x2640 */ - MMU_STAGE1__ST1MMU__AS9__MEMATTR, /* (RW) 64-bit 0x2648 */ - MMU_STAGE1__ST1MMU__AS9__LOCKADDR, /* (RW) 64-bit 0x2650 */ - MMU_STAGE1__ST1MMU__AS9__COMMAND, /* (WO) 32-bit 0x2658 */ - MMU_STAGE1__ST1MMU__AS9__FAULTSTATUS, /* (RO) 32-bit 0x265C */ - MMU_STAGE1__ST1MMU__AS9__FAULTADDRESS, /* (RO) 64-bit 0x2660 */ - MMU_STAGE1__ST1MMU__AS9__STATUS, /* (RO) 32-bit 0x2668 */ - MMU_STAGE1__ST1MMU__AS9__TRANSCFG, /* (RW) 64-bit 0x2670 */ - MMU_STAGE1__ST1MMU__AS9__FAULTEXTRA, /* (RO) 64-bit 0x2678 */ - MMU_STAGE1__ST1MMU__AS10__TRANSTAB, /* (RW) 64-bit 0x2680 */ - MMU_STAGE1__ST1MMU__AS10__MEMATTR, /* (RW) 64-bit 0x2688 */ - MMU_STAGE1__ST1MMU__AS10__LOCKADDR, /* (RW) 64-bit 0x2690 */ - MMU_STAGE1__ST1MMU__AS10__COMMAND, /* (WO) 32-bit 0x2698 */ - MMU_STAGE1__ST1MMU__AS10__FAULTSTATUS, /* (RO) 32-bit 0x269C */ - MMU_STAGE1__ST1MMU__AS10__FAULTADDRESS, /* (RO) 64-bit 0x26A0 */ - MMU_STAGE1__ST1MMU__AS10__STATUS, /* (RO) 32-bit 0x26A8 */ - MMU_STAGE1__ST1MMU__AS10__TRANSCFG, /* (RW) 64-bit 0x26B0 */ - MMU_STAGE1__ST1MMU__AS10__FAULTEXTRA, /* (RO) 64-bit 0x26B8 */ - MMU_STAGE1__ST1MMU__AS11__TRANSTAB, /* (RW) 64-bit 0x26C0 */ - MMU_STAGE1__ST1MMU__AS11__MEMATTR, /* (RW) 64-bit 0x26C8 */ - MMU_STAGE1__ST1MMU__AS11__LOCKADDR, /* (RW) 64-bit 0x26D0 */ - MMU_STAGE1__ST1MMU__AS11__COMMAND, /* (WO) 32-bit 0x26D8 */ - MMU_STAGE1__ST1MMU__AS11__FAULTSTATUS, /* (RO) 32-bit 0x26DC */ - MMU_STAGE1__ST1MMU__AS11__FAULTADDRESS, /* (RO) 64-bit 0x26E0 */ - MMU_STAGE1__ST1MMU__AS11__STATUS, /* (RO) 32-bit 0x26E8 */ - MMU_STAGE1__ST1MMU__AS11__TRANSCFG, /* (RW) 64-bit 0x26F0 */ - MMU_STAGE1__ST1MMU__AS11__FAULTEXTRA, /* (RO) 64-bit 0x26F8 */ - MMU_STAGE1__ST1MMU__AS12__TRANSTAB, /* (RW) 64-bit 0x2700 */ - MMU_STAGE1__ST1MMU__AS12__MEMATTR, /* (RW) 64-bit 0x2708 */ - MMU_STAGE1__ST1MMU__AS12__LOCKADDR, /* (RW) 64-bit 0x2710 */ - MMU_STAGE1__ST1MMU__AS12__COMMAND, /* (WO) 32-bit 0x2718 */ - MMU_STAGE1__ST1MMU__AS12__FAULTSTATUS, /* (RO) 32-bit 0x271C */ - MMU_STAGE1__ST1MMU__AS12__FAULTADDRESS, /* (RO) 64-bit 0x2720 */ - MMU_STAGE1__ST1MMU__AS12__STATUS, /* (RO) 32-bit 0x2728 */ - MMU_STAGE1__ST1MMU__AS12__TRANSCFG, /* (RW) 64-bit 0x2730 */ - MMU_STAGE1__ST1MMU__AS12__FAULTEXTRA, /* (RO) 64-bit 0x2738 */ - MMU_STAGE1__ST1MMU__AS13__TRANSTAB, /* (RW) 64-bit 0x2740 */ - MMU_STAGE1__ST1MMU__AS13__MEMATTR, /* (RW) 64-bit 0x2748 */ - MMU_STAGE1__ST1MMU__AS13__LOCKADDR, /* (RW) 64-bit 0x2750 */ - MMU_STAGE1__ST1MMU__AS13__COMMAND, /* (WO) 32-bit 0x2758 */ - MMU_STAGE1__ST1MMU__AS13__FAULTSTATUS, /* (RO) 32-bit 0x275C */ - MMU_STAGE1__ST1MMU__AS13__FAULTADDRESS, /* (RO) 64-bit 0x2760 */ - MMU_STAGE1__ST1MMU__AS13__STATUS, /* (RO) 32-bit 0x2768 */ - MMU_STAGE1__ST1MMU__AS13__TRANSCFG, /* (RW) 64-bit 0x2770 */ - MMU_STAGE1__ST1MMU__AS13__FAULTEXTRA, /* (RO) 64-bit 0x2778 */ - MMU_STAGE1__ST1MMU__AS14__TRANSTAB, /* (RW) 64-bit 0x2780 */ - MMU_STAGE1__ST1MMU__AS14__MEMATTR, /* (RW) 64-bit 0x2788 */ - MMU_STAGE1__ST1MMU__AS14__LOCKADDR, /* (RW) 64-bit 0x2790 */ - MMU_STAGE1__ST1MMU__AS14__COMMAND, /* (WO) 32-bit 0x2798 */ - MMU_STAGE1__ST1MMU__AS14__FAULTSTATUS, /* (RO) 32-bit 0x279C */ - MMU_STAGE1__ST1MMU__AS14__FAULTADDRESS, /* (RO) 64-bit 0x27A0 */ - MMU_STAGE1__ST1MMU__AS14__STATUS, /* (RO) 32-bit 0x27A8 */ - MMU_STAGE1__ST1MMU__AS14__TRANSCFG, /* (RW) 64-bit 0x27B0 */ - MMU_STAGE1__ST1MMU__AS14__FAULTEXTRA, /* (RO) 64-bit 0x27B8 */ - MMU_STAGE1__ST1MMU__AS15__TRANSTAB, /* (RW) 64-bit 0x27C0 */ - MMU_STAGE1__ST1MMU__AS15__MEMATTR, /* (RW) 64-bit 0x27C8 */ - MMU_STAGE1__ST1MMU__AS15__LOCKADDR, /* (RW) 64-bit 0x27D0 */ - MMU_STAGE1__ST1MMU__AS15__COMMAND, /* (WO) 32-bit 0x27D8 */ - MMU_STAGE1__ST1MMU__AS15__FAULTSTATUS, /* (RO) 32-bit 0x27DC */ - MMU_STAGE1__ST1MMU__AS15__FAULTADDRESS, /* (RO) 64-bit 0x27E0 */ - MMU_STAGE1__ST1MMU__AS15__STATUS, /* (RO) 32-bit 0x27E8 */ - MMU_STAGE1__ST1MMU__AS15__TRANSCFG, /* (RW) 64-bit 0x27F0 */ - MMU_STAGE1__ST1MMU__AS15__FAULTEXTRA, /* (RO) 64-bit 0x27F8 */ - MMU_STAGE2__ST2MMU__IRQ_RAWSTAT, /* (RW) 32-bit 0x10000 */ - MMU_STAGE2__ST2MMU__IRQ_CLEAR, /* (WO) 32-bit 0x10004 */ - MMU_STAGE2__ST2MMU__IRQ_MASK, /* (RW) 32-bit 0x10008 */ - MMU_STAGE2__ST2MMU__IRQ_STATUS, /* (RO) 32-bit 0x1000C */ - MMU_STAGE2__ST2MMU__AS0__TRANSTAB, /* (RW) 64-bit 0x10400 */ - MMU_STAGE2__ST2MMU__AS0__MEMATTR, /* (RW) 64-bit 0x10408 */ - MMU_STAGE2__ST2MMU__AS0__LOCKADDR, /* (RW) 64-bit 0x10410 */ - MMU_STAGE2__ST2MMU__AS0__COMMAND, /* (WO) 32-bit 0x10418 */ - MMU_STAGE2__ST2MMU__AS0__FAULTSTATUS, /* (RO) 32-bit 0x1041C */ - MMU_STAGE2__ST2MMU__AS0__FAULTADDRESS, /* (RO) 64-bit 0x10420 */ - MMU_STAGE2__ST2MMU__AS0__STATUS, /* (RO) 32-bit 0x10428 */ - MMU_STAGE2__ST2MMU__AS0__TRANSCFG, /* (RW) 64-bit 0x10430 */ - MMU_STAGE2__ST2MMU__AS0__FAULTEXTRA, /* (RO) 64-bit 0x10438 */ - MMU_STAGE2__ST2MMU__AS1__TRANSTAB, /* (RW) 64-bit 0x10440 */ - MMU_STAGE2__ST2MMU__AS1__MEMATTR, /* (RW) 64-bit 0x10448 */ - MMU_STAGE2__ST2MMU__AS1__LOCKADDR, /* (RW) 64-bit 0x10450 */ - MMU_STAGE2__ST2MMU__AS1__COMMAND, /* (WO) 32-bit 0x10458 */ - MMU_STAGE2__ST2MMU__AS1__FAULTSTATUS, /* (RO) 32-bit 0x1045C */ - MMU_STAGE2__ST2MMU__AS1__FAULTADDRESS, /* (RO) 64-bit 0x10460 */ - MMU_STAGE2__ST2MMU__AS1__STATUS, /* (RO) 32-bit 0x10468 */ - MMU_STAGE2__ST2MMU__AS1__TRANSCFG, /* (RW) 64-bit 0x10470 */ - MMU_STAGE2__ST2MMU__AS1__FAULTEXTRA, /* (RO) 64-bit 0x10478 */ - MMU_STAGE2__ST2MMU__AS2__TRANSTAB, /* (RW) 64-bit 0x10480 */ - MMU_STAGE2__ST2MMU__AS2__MEMATTR, /* (RW) 64-bit 0x10488 */ - MMU_STAGE2__ST2MMU__AS2__LOCKADDR, /* (RW) 64-bit 0x10490 */ - MMU_STAGE2__ST2MMU__AS2__COMMAND, /* (WO) 32-bit 0x10498 */ - MMU_STAGE2__ST2MMU__AS2__FAULTSTATUS, /* (RO) 32-bit 0x1049C */ - MMU_STAGE2__ST2MMU__AS2__FAULTADDRESS, /* (RO) 64-bit 0x104A0 */ - MMU_STAGE2__ST2MMU__AS2__STATUS, /* (RO) 32-bit 0x104A8 */ - MMU_STAGE2__ST2MMU__AS2__TRANSCFG, /* (RW) 64-bit 0x104B0 */ - MMU_STAGE2__ST2MMU__AS2__FAULTEXTRA, /* (RO) 64-bit 0x104B8 */ - MMU_STAGE2__ST2MMU__AS3__TRANSTAB, /* (RW) 64-bit 0x104C0 */ - MMU_STAGE2__ST2MMU__AS3__MEMATTR, /* (RW) 64-bit 0x104C8 */ - MMU_STAGE2__ST2MMU__AS3__LOCKADDR, /* (RW) 64-bit 0x104D0 */ - MMU_STAGE2__ST2MMU__AS3__COMMAND, /* (WO) 32-bit 0x104D8 */ - MMU_STAGE2__ST2MMU__AS3__FAULTSTATUS, /* (RO) 32-bit 0x104DC */ - MMU_STAGE2__ST2MMU__AS3__FAULTADDRESS, /* (RO) 64-bit 0x104E0 */ - MMU_STAGE2__ST2MMU__AS3__STATUS, /* (RO) 32-bit 0x104E8 */ - MMU_STAGE2__ST2MMU__AS3__TRANSCFG, /* (RW) 64-bit 0x104F0 */ - MMU_STAGE2__ST2MMU__AS3__FAULTEXTRA, /* (RO) 64-bit 0x104F8 */ - MMU_STAGE2__ST2MMU__AS4__TRANSTAB, /* (RW) 64-bit 0x10500 */ - MMU_STAGE2__ST2MMU__AS4__MEMATTR, /* (RW) 64-bit 0x10508 */ - MMU_STAGE2__ST2MMU__AS4__LOCKADDR, /* (RW) 64-bit 0x10510 */ - MMU_STAGE2__ST2MMU__AS4__COMMAND, /* (WO) 32-bit 0x10518 */ - MMU_STAGE2__ST2MMU__AS4__FAULTSTATUS, /* (RO) 32-bit 0x1051C */ - MMU_STAGE2__ST2MMU__AS4__FAULTADDRESS, /* (RO) 64-bit 0x10520 */ - MMU_STAGE2__ST2MMU__AS4__STATUS, /* (RO) 32-bit 0x10528 */ - MMU_STAGE2__ST2MMU__AS4__TRANSCFG, /* (RW) 64-bit 0x10530 */ - MMU_STAGE2__ST2MMU__AS4__FAULTEXTRA, /* (RO) 64-bit 0x10538 */ - MMU_STAGE2__ST2MMU__AS5__TRANSTAB, /* (RW) 64-bit 0x10540 */ - MMU_STAGE2__ST2MMU__AS5__MEMATTR, /* (RW) 64-bit 0x10548 */ - MMU_STAGE2__ST2MMU__AS5__LOCKADDR, /* (RW) 64-bit 0x10550 */ - MMU_STAGE2__ST2MMU__AS5__COMMAND, /* (WO) 32-bit 0x10558 */ - MMU_STAGE2__ST2MMU__AS5__FAULTSTATUS, /* (RO) 32-bit 0x1055C */ - MMU_STAGE2__ST2MMU__AS5__FAULTADDRESS, /* (RO) 64-bit 0x10560 */ - MMU_STAGE2__ST2MMU__AS5__STATUS, /* (RO) 32-bit 0x10568 */ - MMU_STAGE2__ST2MMU__AS5__TRANSCFG, /* (RW) 64-bit 0x10570 */ - MMU_STAGE2__ST2MMU__AS5__FAULTEXTRA, /* (RO) 64-bit 0x10578 */ - MMU_STAGE2__ST2MMU__AS6__TRANSTAB, /* (RW) 64-bit 0x10580 */ - MMU_STAGE2__ST2MMU__AS6__MEMATTR, /* (RW) 64-bit 0x10588 */ - MMU_STAGE2__ST2MMU__AS6__LOCKADDR, /* (RW) 64-bit 0x10590 */ - MMU_STAGE2__ST2MMU__AS6__COMMAND, /* (WO) 32-bit 0x10598 */ - MMU_STAGE2__ST2MMU__AS6__FAULTSTATUS, /* (RO) 32-bit 0x1059C */ - MMU_STAGE2__ST2MMU__AS6__FAULTADDRESS, /* (RO) 64-bit 0x105A0 */ - MMU_STAGE2__ST2MMU__AS6__STATUS, /* (RO) 32-bit 0x105A8 */ - MMU_STAGE2__ST2MMU__AS6__TRANSCFG, /* (RW) 64-bit 0x105B0 */ - MMU_STAGE2__ST2MMU__AS6__FAULTEXTRA, /* (RO) 64-bit 0x105B8 */ - MMU_STAGE2__ST2MMU__AS7__TRANSTAB, /* (RW) 64-bit 0x105C0 */ - MMU_STAGE2__ST2MMU__AS7__MEMATTR, /* (RW) 64-bit 0x105C8 */ - MMU_STAGE2__ST2MMU__AS7__LOCKADDR, /* (RW) 64-bit 0x105D0 */ - MMU_STAGE2__ST2MMU__AS7__COMMAND, /* (WO) 32-bit 0x105D8 */ - MMU_STAGE2__ST2MMU__AS7__FAULTSTATUS, /* (RO) 32-bit 0x105DC */ - MMU_STAGE2__ST2MMU__AS7__FAULTADDRESS, /* (RO) 64-bit 0x105E0 */ - MMU_STAGE2__ST2MMU__AS7__STATUS, /* (RO) 32-bit 0x105E8 */ - MMU_STAGE2__ST2MMU__AS7__TRANSCFG, /* (RW) 64-bit 0x105F0 */ - MMU_STAGE2__ST2MMU__AS7__FAULTEXTRA, /* (RO) 64-bit 0x105F8 */ - MMU_STAGE2__ST2MMU__AS8__TRANSTAB, /* (RW) 64-bit 0x10600 */ - MMU_STAGE2__ST2MMU__AS8__MEMATTR, /* (RW) 64-bit 0x10608 */ - MMU_STAGE2__ST2MMU__AS8__LOCKADDR, /* (RW) 64-bit 0x10610 */ - MMU_STAGE2__ST2MMU__AS8__COMMAND, /* (WO) 32-bit 0x10618 */ - MMU_STAGE2__ST2MMU__AS8__FAULTSTATUS, /* (RO) 32-bit 0x1061C */ - MMU_STAGE2__ST2MMU__AS8__FAULTADDRESS, /* (RO) 64-bit 0x10620 */ - MMU_STAGE2__ST2MMU__AS8__STATUS, /* (RO) 32-bit 0x10628 */ - MMU_STAGE2__ST2MMU__AS8__TRANSCFG, /* (RW) 64-bit 0x10630 */ - MMU_STAGE2__ST2MMU__AS8__FAULTEXTRA, /* (RO) 64-bit 0x10638 */ - MMU_STAGE2__ST2MMU__AS9__TRANSTAB, /* (RW) 64-bit 0x10640 */ - MMU_STAGE2__ST2MMU__AS9__MEMATTR, /* (RW) 64-bit 0x10648 */ - MMU_STAGE2__ST2MMU__AS9__LOCKADDR, /* (RW) 64-bit 0x10650 */ - MMU_STAGE2__ST2MMU__AS9__COMMAND, /* (WO) 32-bit 0x10658 */ - MMU_STAGE2__ST2MMU__AS9__FAULTSTATUS, /* (RO) 32-bit 0x1065C */ - MMU_STAGE2__ST2MMU__AS9__FAULTADDRESS, /* (RO) 64-bit 0x10660 */ - MMU_STAGE2__ST2MMU__AS9__STATUS, /* (RO) 32-bit 0x10668 */ - MMU_STAGE2__ST2MMU__AS9__TRANSCFG, /* (RW) 64-bit 0x10670 */ - MMU_STAGE2__ST2MMU__AS9__FAULTEXTRA, /* (RO) 64-bit 0x10678 */ - MMU_STAGE2__ST2MMU__AS10__TRANSTAB, /* (RW) 64-bit 0x10680 */ - MMU_STAGE2__ST2MMU__AS10__MEMATTR, /* (RW) 64-bit 0x10688 */ - MMU_STAGE2__ST2MMU__AS10__LOCKADDR, /* (RW) 64-bit 0x10690 */ - MMU_STAGE2__ST2MMU__AS10__COMMAND, /* (WO) 32-bit 0x10698 */ - MMU_STAGE2__ST2MMU__AS10__FAULTSTATUS, /* (RO) 32-bit 0x1069C */ - MMU_STAGE2__ST2MMU__AS10__FAULTADDRESS, /* (RO) 64-bit 0x106A0 */ - MMU_STAGE2__ST2MMU__AS10__STATUS, /* (RO) 32-bit 0x106A8 */ - MMU_STAGE2__ST2MMU__AS10__TRANSCFG, /* (RW) 64-bit 0x106B0 */ - MMU_STAGE2__ST2MMU__AS10__FAULTEXTRA, /* (RO) 64-bit 0x106B8 */ - MMU_STAGE2__ST2MMU__AS11__TRANSTAB, /* (RW) 64-bit 0x106C0 */ - MMU_STAGE2__ST2MMU__AS11__MEMATTR, /* (RW) 64-bit 0x106C8 */ - MMU_STAGE2__ST2MMU__AS11__LOCKADDR, /* (RW) 64-bit 0x106D0 */ - MMU_STAGE2__ST2MMU__AS11__COMMAND, /* (WO) 32-bit 0x106D8 */ - MMU_STAGE2__ST2MMU__AS11__FAULTSTATUS, /* (RO) 32-bit 0x106DC */ - MMU_STAGE2__ST2MMU__AS11__FAULTADDRESS, /* (RO) 64-bit 0x106E0 */ - MMU_STAGE2__ST2MMU__AS11__STATUS, /* (RO) 32-bit 0x106E8 */ - MMU_STAGE2__ST2MMU__AS11__TRANSCFG, /* (RW) 64-bit 0x106F0 */ - MMU_STAGE2__ST2MMU__AS11__FAULTEXTRA, /* (RO) 64-bit 0x106F8 */ - MMU_STAGE2__ST2MMU__AS12__TRANSTAB, /* (RW) 64-bit 0x10700 */ - MMU_STAGE2__ST2MMU__AS12__MEMATTR, /* (RW) 64-bit 0x10708 */ - MMU_STAGE2__ST2MMU__AS12__LOCKADDR, /* (RW) 64-bit 0x10710 */ - MMU_STAGE2__ST2MMU__AS12__COMMAND, /* (WO) 32-bit 0x10718 */ - MMU_STAGE2__ST2MMU__AS12__FAULTSTATUS, /* (RO) 32-bit 0x1071C */ - MMU_STAGE2__ST2MMU__AS12__FAULTADDRESS, /* (RO) 64-bit 0x10720 */ - MMU_STAGE2__ST2MMU__AS12__STATUS, /* (RO) 32-bit 0x10728 */ - MMU_STAGE2__ST2MMU__AS12__TRANSCFG, /* (RW) 64-bit 0x10730 */ - MMU_STAGE2__ST2MMU__AS12__FAULTEXTRA, /* (RO) 64-bit 0x10738 */ - MMU_STAGE2__ST2MMU__AS13__TRANSTAB, /* (RW) 64-bit 0x10740 */ - MMU_STAGE2__ST2MMU__AS13__MEMATTR, /* (RW) 64-bit 0x10748 */ - MMU_STAGE2__ST2MMU__AS13__LOCKADDR, /* (RW) 64-bit 0x10750 */ - MMU_STAGE2__ST2MMU__AS13__COMMAND, /* (WO) 32-bit 0x10758 */ - MMU_STAGE2__ST2MMU__AS13__FAULTSTATUS, /* (RO) 32-bit 0x1075C */ - MMU_STAGE2__ST2MMU__AS13__FAULTADDRESS, /* (RO) 64-bit 0x10760 */ - MMU_STAGE2__ST2MMU__AS13__STATUS, /* (RO) 32-bit 0x10768 */ - MMU_STAGE2__ST2MMU__AS13__TRANSCFG, /* (RW) 64-bit 0x10770 */ - MMU_STAGE2__ST2MMU__AS13__FAULTEXTRA, /* (RO) 64-bit 0x10778 */ - MMU_STAGE2__ST2MMU__AS14__TRANSTAB, /* (RW) 64-bit 0x10780 */ - MMU_STAGE2__ST2MMU__AS14__MEMATTR, /* (RW) 64-bit 0x10788 */ - MMU_STAGE2__ST2MMU__AS14__LOCKADDR, /* (RW) 64-bit 0x10790 */ - MMU_STAGE2__ST2MMU__AS14__COMMAND, /* (WO) 32-bit 0x10798 */ - MMU_STAGE2__ST2MMU__AS14__FAULTSTATUS, /* (RO) 32-bit 0x1079C */ - MMU_STAGE2__ST2MMU__AS14__FAULTADDRESS, /* (RO) 64-bit 0x107A0 */ - MMU_STAGE2__ST2MMU__AS14__STATUS, /* (RO) 32-bit 0x107A8 */ - MMU_STAGE2__ST2MMU__AS14__TRANSCFG, /* (RW) 64-bit 0x107B0 */ - MMU_STAGE2__ST2MMU__AS14__FAULTEXTRA, /* (RO) 64-bit 0x107B8 */ - MMU_STAGE2__ST2MMU__AS15__TRANSTAB, /* (RW) 64-bit 0x107C0 */ - MMU_STAGE2__ST2MMU__AS15__MEMATTR, /* (RW) 64-bit 0x107C8 */ - MMU_STAGE2__ST2MMU__AS15__LOCKADDR, /* (RW) 64-bit 0x107D0 */ - MMU_STAGE2__ST2MMU__AS15__COMMAND, /* (WO) 32-bit 0x107D8 */ - MMU_STAGE2__ST2MMU__AS15__FAULTSTATUS, /* (RO) 32-bit 0x107DC */ - MMU_STAGE2__ST2MMU__AS15__FAULTADDRESS, /* (RO) 64-bit 0x107E0 */ - MMU_STAGE2__ST2MMU__AS15__STATUS, /* (RO) 32-bit 0x107E8 */ - MMU_STAGE2__ST2MMU__AS15__TRANSCFG, /* (RW) 64-bit 0x107F0 */ - MMU_STAGE2__ST2MMU__AS15__FAULTEXTRA, /* (RO) 64-bit 0x107F8 */ - NR_V6_0_REGS, -}; - -enum kbase_regmap_enum_v6_2 { - GPU_CONTROL__REVIDR = NR_V6_0_REGS, /* (RO) 32-bit 0x280 */ - GPU_CONTROL__STACK_PRESENT, /* (RO) 64-bit 0xE00 */ - GPU_CONTROL__STACK_PWROFF, /* (WO) 64-bit 0xE30 */ - GPU_CONTROL__STACK_PWRON, /* (WO) 64-bit 0xE20 */ - GPU_CONTROL__STACK_PWRTRANS, /* (RO) 64-bit 0xE40 */ - GPU_CONTROL__STACK_READY, /* (RO) 64-bit 0xE10 */ - NR_V6_2_REGS, -}; - -enum kbase_regmap_enum_v7_0 { - GPU_CONTROL__TEXTURE_FEATURES_3 = NR_V6_2_REGS, /* (RO) 32-bit 0xBC */ - NR_V7_0_REGS, -}; - -enum kbase_regmap_enum_v7_2 { - GPU_CONTROL__CORE_FEATURES = NR_V7_0_REGS, /* (RO) 32-bit 0x8 */ - GPU_CONTROL__THREAD_TLS_ALLOC, /* (RO) 32-bit 0x310 */ - NR_V7_2_REGS, -}; - -enum kbase_regmap_enum_v9_0 { - NR_V9_0_REGS = NR_V7_2_REGS, -}; - -/* - * V9_0_REMOVED_REGS: - * GPU_CONTROL__CORE_FEATURES - * GPU_CONTROL__THREAD_TLS_ALLOC - * JOB_CONTROL__JOB_IRQ_THROTTLE - */ - -enum kbase_regmap_enum_v9_2 { - GPU_CONTROL__L2_CONFIG = NR_V9_0_REGS, /* (RW) 32-bit 0x48 */ - NR_V9_2_REGS, -}; - -enum kbase_regmap_enum_v9_14 { - PTM_AW_IRQ_CLEAR = NR_V9_2_REGS, /* (RW) 32-bit 0x1FFC8 */ - PTM_AW_IRQ_INJECTION, /* (RW) 32-bit 0x1FFD4 */ - PTM_AW_IRQ_MASK, /* (RW) 32-bit 0x1FFCC */ - PTM_AW_IRQ_RAWSTAT, /* (RO) 32-bit 0x1FFC4 */ - PTM_AW_IRQ_STATUS, /* (RO) 32-bit 0x1FFD0 */ - PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE0, /* (RO) 32-bit 0x1FFD8 */ - PTM_AW_MESSAGE__PTM_INCOMING_MESSAGE1, /* (RO) 32-bit 0x1FFDC */ - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE0, /* (RW) 32-bit 0x1FFE4 */ - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE1, /* (RW) 32-bit 0x1FFE8 */ - PTM_AW_MESSAGE__PTM_OUTGOING_MESSAGE_STATUS, /* (RO) 32-bit 0x1FFE0 */ - PTM_ID, /* (RO) 32-bit 0x1FFC0 */ - NR_V9_14_REGS, -}; - -#endif /* _MALI_KBASE_REGMAP_JM_ENUMS_H_ */ diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_macros.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_macros.h deleted file mode 100644 index 27d2702a06ce..000000000000 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_jm_macros.h +++ /dev/null @@ -1,308 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _MALI_KBASE_REGMAP_JM_MACROS_H_ -#define _MALI_KBASE_REGMAP_JM_MACROS_H_ - -#if MALI_USE_CSF -#error "Cannot be compiled with CSF" -#endif - -#define ENUM_OFFSET(_index, _base, _next) (_base + _index * (_next - _base)) - -#define GPU_CONTROL_ENUM(regname) GPU_CONTROL__##regname -#define GPU_TEXTURE_FEATURES_ENUM(n) GPU_CONTROL_ENUM(TEXTURE_FEATURES_##n) -#define GPU_TEXTURE_FEATURES_OFFSET(n) (GPU_TEXTURE_FEATURES_ENUM(0) + n) -#define GPU_JS_FEATURES_ENUM(n) GPU_CONTROL_ENUM(JS##n##_FEATURES) -#define GPU_JS_FEATURES_OFFSET(n) (GPU_JS_FEATURES_ENUM(0) + n) - -#define JOB_CONTROL_ENUM(regname) JOB_CONTROL__##regname -#define JOB_SLOT_ENUM(n, regname) JOB_CONTROL_ENUM(JS##n##__##regname) -#define JOB_SLOT_BASE_ENUM(n) JOB_SLOT_ENUM(n, HEAD) -#define JOB_SLOT_OFFSET(n, regname) \ - ENUM_OFFSET(n, JOB_SLOT_ENUM(0, regname), JOB_SLOT_ENUM(1, regname)) -#define JOB_SLOT_BASE_OFFSET(n) JOB_SLOT_OFFSET(n, HEAD) - -#define MMU_CONTROL_ENUM(regname) MMU_STAGE1__ST1MMU__##regname -#define MMU_AS_ENUM(n, regname) MMU_CONTROL_ENUM(AS##n##__##regname) -#define MMU_AS_BASE_ENUM(n) MMU_AS_ENUM(n, TRANSTAB) -#define MMU_AS_OFFSET(n, regname) ENUM_OFFSET(n, MMU_AS_ENUM(0, regname), MMU_AS_ENUM(1, regname)) -#define MMU_AS_BASE_OFFSET(n) MMU_AS_OFFSET(n, TRANSTAB) - -#define PTM_AW_ENUM(regname) PTM_AW__##regname -#define PTM_AW_MESSAGE_ENUM(regname) PTM_AW_MESSAGE__##regname - -/* register value macros */ -/* GPU_STATUS values */ -#define GPU_STATUS_PRFCNT_ACTIVE (1 << 2) /* Set if the performance counters are active. */ -#define GPU_STATUS_CYCLE_COUNT_ACTIVE (1 << 6) /* Set if the cycle counter is active. */ - -/* PRFCNT_CONFIG register values */ -#define PRFCNT_CONFIG_MODE_SHIFT 0 /* Counter mode position. */ -#define PRFCNT_CONFIG_AS_SHIFT 4 /* Address space bitmap position. */ -#define PRFCNT_CONFIG_SETSELECT_SHIFT 8 /* Set select position. */ - -/* The performance counters are disabled. */ -#define PRFCNT_CONFIG_MODE_OFF 0 -/* The performance counters are enabled, but are only written out when a - * PRFCNT_SAMPLE command is issued using the GPU_COMMAND register. - */ -#define PRFCNT_CONFIG_MODE_MANUAL 1 -/* The performance counters are enabled, and are written out each time a tile - * finishes rendering. - */ -#define PRFCNT_CONFIG_MODE_TILE 2 - -/* - * Begin AARCH64 MMU TRANSTAB register values - */ -#define AS_TRANSTAB_BASE_SHIFT GPU_U(4) -#define AS_TRANSTAB_BASE_MASK (GPU_ULL(0xFFFFFFFFFFFFFFF) << AS_TRANSTAB_BASE_SHIFT) -#define AS_TRANSTAB_BASE_GET(reg_val) (((reg_val)&AS_TRANSTAB_BASE_MASK) >> AS_TRANSTAB_BASE_SHIFT) -#define AS_TRANSTAB_BASE_SET(reg_val, value) \ - (~(~(reg_val) | AS_TRANSTAB_BASE_MASK) | \ - (((uint64_t)(value) << AS_TRANSTAB_BASE_SHIFT) & AS_TRANSTAB_BASE_MASK)) - -#define AS_FAULTSTATUS_EXCEPTION_TYPE_OK 0x0 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_DONE 0x1 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_STOPPED 0x3 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TERMINATED 0x4 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_KABOOM 0x5 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_EUREKA 0x6 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ACTIVE 0x8 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_CONFIG_FAULT 0x40 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_POWER_FAULT 0x41 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_READ_FAULT 0x42 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_WRITE_FAULT 0x43 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_AFFINITY_FAULT 0x44 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_JOB_BUS_FAULT 0x48 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_INSTR_INVALID_PC 0x50 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_INSTR_INVALID_ENC 0x51 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_INSTR_BARRIER_FAULT 0x55 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_DATA_INVALID_FAULT 0x58 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TILE_RANGE_FAULT 0x59 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDR_RANGE_FAULT 0x5A -#define AS_FAULTSTATUS_EXCEPTION_TYPE_IMPRECISE_FAULT 0x5B -#define AS_FAULTSTATUS_EXCEPTION_TYPE_OUT_OF_MEMORY 0x60 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_UNKNOWN 0x7F -#define AS_FAULTSTATUS_EXCEPTION_TYPE_DELAYED_BUS_FAULT 0x80 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_GPU_SHAREABILITY_FAULT 0x88 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_SYSTEM_SHAREABILITY_FAULT 0x89 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_GPU_CACHEABILITY_FAULT 0x8A -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_0 0xC0 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_1 0xC1 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_2 0xC2 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_3 0xC3 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_4 0xC4 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_IDENTITY 0xC7 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_PERMISSION_FAULT_0 0xC8 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_PERMISSION_FAULT_1 0xC9 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_PERMISSION_FAULT_2 0xCA -#define AS_FAULTSTATUS_EXCEPTION_TYPE_PERMISSION_FAULT_3 0xCB -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_0 0xD0 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_1 0xD1 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_2 0xD2 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_3 0xD3 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_0 0xD8 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_1 0xD9 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_2 0xDA -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_3 0xDB -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN0 0xE0 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN1 0xE1 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN2 0xE2 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN3 0xE3 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT0 0xE4 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT1 0xE5 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT2 0xE6 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT3 0xE7 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_0 0xE8 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_1 0xE9 -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_2 0xEA -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_3 0xEB -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_0 0xEC -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_1 0xED -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_2 0xEE -#define AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_3 0xEF - -/* No JM-specific MMU control registers */ -/* No JM-specific MMU address space control registers */ - -/* JS_COMMAND register commands */ -#define JS_COMMAND_NOP 0x00 /* NOP Operation. Writing this value is ignored */ -#define JS_COMMAND_START 0x01 /* Start processing a job chain. Writing this value is ignored */ -#define JS_COMMAND_SOFT_STOP 0x02 /* Gently stop processing a job chain */ -#define JS_COMMAND_HARD_STOP 0x03 /* Rudely stop processing a job chain */ -#define JS_COMMAND_SOFT_STOP_0 0x04 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 0 */ -#define JS_COMMAND_HARD_STOP_0 0x05 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 0 */ -#define JS_COMMAND_SOFT_STOP_1 0x06 /* Execute SOFT_STOP if JOB_CHAIN_FLAG is 1 */ -#define JS_COMMAND_HARD_STOP_1 0x07 /* Execute HARD_STOP if JOB_CHAIN_FLAG is 1 */ - -#define JS_COMMAND_MASK 0x07 /* Mask of bits currently in use by the HW */ - -/* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */ -#define JS_CONFIG_START_FLUSH_NO_ACTION (0u << 0) -#define JS_CONFIG_START_FLUSH_CLEAN (1u << 8) -#define JS_CONFIG_START_FLUSH_INV_SHADER_OTHER (2u << 8) -#define JS_CONFIG_START_FLUSH_CLEAN_INVALIDATE (3u << 8) -#define JS_CONFIG_START_MMU (1u << 10) -#define JS_CONFIG_JOB_CHAIN_FLAG (1u << 11) -#define JS_CONFIG_END_FLUSH_NO_ACTION JS_CONFIG_START_FLUSH_NO_ACTION -#define JS_CONFIG_END_FLUSH_CLEAN (1u << 12) -#define JS_CONFIG_END_FLUSH_CLEAN_INVALIDATE (3u << 12) -#define JS_CONFIG_ENABLE_FLUSH_REDUCTION (1u << 14) -#define JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK (1u << 15) -#define JS_CONFIG_THREAD_PRI(n) ((n) << 16) - -/* JS_XAFFINITY register values */ -#define JS_XAFFINITY_XAFFINITY_ENABLE (1u << 0) -#define JS_XAFFINITY_TILER_ENABLE (1u << 8) -#define JS_XAFFINITY_CACHE_ENABLE (1u << 16) - -/* JS_STATUS register values */ - -/* NOTE: Please keep this values in sync with enum base_jd_event_code in mali_base_kernel.h. - * The values are separated to avoid dependency of userspace and kernel code. - */ - -/* Group of values representing the job status instead of a particular fault */ -#define JS_STATUS_NO_EXCEPTION_BASE 0x00 -#define JS_STATUS_INTERRUPTED (JS_STATUS_NO_EXCEPTION_BASE + 0x02) /* 0x02 means INTERRUPTED */ -#define JS_STATUS_STOPPED (JS_STATUS_NO_EXCEPTION_BASE + 0x03) /* 0x03 means STOPPED */ -#define JS_STATUS_TERMINATED (JS_STATUS_NO_EXCEPTION_BASE + 0x04) /* 0x04 means TERMINATED */ - -/* General fault values */ -#define JS_STATUS_FAULT_BASE 0x40 -#define JS_STATUS_CONFIG_FAULT (JS_STATUS_FAULT_BASE) /* 0x40 means CONFIG FAULT */ -#define JS_STATUS_POWER_FAULT (JS_STATUS_FAULT_BASE + 0x01) /* 0x41 means POWER FAULT */ -#define JS_STATUS_READ_FAULT (JS_STATUS_FAULT_BASE + 0x02) /* 0x42 means READ FAULT */ -#define JS_STATUS_WRITE_FAULT (JS_STATUS_FAULT_BASE + 0x03) /* 0x43 means WRITE FAULT */ -#define JS_STATUS_AFFINITY_FAULT (JS_STATUS_FAULT_BASE + 0x04) /* 0x44 means AFFINITY FAULT */ -#define JS_STATUS_BUS_FAULT (JS_STATUS_FAULT_BASE + 0x08) /* 0x48 means BUS FAULT */ - -/* Instruction or data faults */ -#define JS_STATUS_INSTRUCTION_FAULT_BASE 0x50 -#define JS_STATUS_INSTR_INVALID_PC \ - (JS_STATUS_INSTRUCTION_FAULT_BASE) /* 0x50 means INSTR INVALID PC */ -#define JS_STATUS_INSTR_INVALID_ENC \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x01) /* 0x51 means INSTR INVALID ENC */ -#define JS_STATUS_INSTR_TYPE_MISMATCH \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x02) /* 0x52 means INSTR TYPE MISMATCH */ -#define JS_STATUS_INSTR_OPERAND_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x03) /* 0x53 means INSTR OPERAND FAULT */ -#define JS_STATUS_INSTR_TLS_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x04) /* 0x54 means INSTR TLS FAULT */ -#define JS_STATUS_INSTR_BARRIER_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x05) /* 0x55 means INSTR BARRIER FAULT */ -#define JS_STATUS_INSTR_ALIGN_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x06) /* 0x56 means INSTR ALIGN FAULT */ -/* NOTE: No fault with 0x57 code defined in spec. */ -#define JS_STATUS_DATA_INVALID_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x08) /* 0x58 means DATA INVALID FAULT */ -#define JS_STATUS_TILE_RANGE_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x09) /* 0x59 means TILE RANGE FAULT */ -#define JS_STATUS_ADDRESS_RANGE_FAULT \ - (JS_STATUS_INSTRUCTION_FAULT_BASE + 0x0A) /* 0x5A means ADDRESS RANGE FAULT */ - -/* Other faults */ -#define JS_STATUS_MEMORY_FAULT_BASE 0x60 -#define JS_STATUS_OUT_OF_MEMORY (JS_STATUS_MEMORY_FAULT_BASE) /* 0x60 means OUT OF MEMORY */ -#define JS_STATUS_UNKNOWN 0x7F /* 0x7F means UNKNOWN */ - -/* JS_FEATURES register */ -#define JS_FEATURE_NULL_JOB (1u << 1) -#define JS_FEATURE_SET_VALUE_JOB (1u << 2) -#define JS_FEATURE_CACHE_FLUSH_JOB (1u << 3) -#define JS_FEATURE_COMPUTE_JOB (1u << 4) -#define JS_FEATURE_VERTEX_JOB (1u << 5) -#define JS_FEATURE_GEOMETRY_JOB (1u << 6) -#define JS_FEATURE_TILER_JOB (1u << 7) -#define JS_FEATURE_FUSED_JOB (1u << 8) -#define JS_FEATURE_FRAGMENT_JOB (1u << 9) - -/* JM_CONFIG register */ -#define JM_TIMESTAMP_OVERRIDE (1ul << 0) -#define JM_CLOCK_GATE_OVERRIDE (1ul << 1) -#define JM_JOB_THROTTLE_ENABLE (1ul << 2) -#define JM_JOB_THROTTLE_LIMIT_SHIFT (3) -#define JM_MAX_JOB_THROTTLE_LIMIT (0x3F) -#define JM_FORCE_COHERENCY_FEATURES_SHIFT (2) - -/* GPU_COMMAND values */ -#define GPU_COMMAND_NOP 0x00 /* No operation, nothing happens */ -#define GPU_COMMAND_SOFT_RESET \ - 0x01 /* Stop all external bus interfaces, and then reset the entire GPU. */ -#define GPU_COMMAND_HARD_RESET 0x02 /* Immediately reset the entire GPU. */ -#define GPU_COMMAND_PRFCNT_CLEAR \ - 0x03 /* Clear all performance counters, setting them all to zero. */ -#define GPU_COMMAND_PRFCNT_SAMPLE \ - 0x04 /* Sample all performance counters, writing them out to memory */ -#define GPU_COMMAND_CYCLE_COUNT_START \ - 0x05 /* Starts the cycle counter, and system timestamp propagation */ -#define GPU_COMMAND_CYCLE_COUNT_STOP \ - 0x06 /* Stops the cycle counter, and system timestamp propagation */ -#define GPU_COMMAND_CLEAN_CACHES 0x07 /* Clean all caches */ -#define GPU_COMMAND_CLEAN_INV_CACHES 0x08 /* Clean and invalidate all caches */ -#define GPU_COMMAND_SET_PROTECTED_MODE 0x09 /* Places the GPU in protected mode */ - -/* GPU_COMMAND cache flush alias to CSF command payload */ -#define GPU_COMMAND_CACHE_CLN_INV_L2 GPU_COMMAND_CLEAN_INV_CACHES -#define GPU_COMMAND_CACHE_CLN_INV_L2_LSC GPU_COMMAND_CLEAN_INV_CACHES -#define GPU_COMMAND_CACHE_CLN_INV_FULL GPU_COMMAND_CLEAN_INV_CACHES -#define GPU_COMMAND_CACHE_CLN_INV_LSC GPU_COMMAND_CLEAN_INV_CACHES - -/* Merge cache flush commands */ -#define GPU_COMMAND_FLUSH_CACHE_MERGE(cmd1, cmd2) ((cmd1) > (cmd2) ? (cmd1) : (cmd2)) - -/* IRQ flags */ -#define GPU_FAULT (1U << 0) /* A GPU Fault has occurred */ -#define MULTIPLE_GPU_FAULTS (1U << 7) /* More than one GPU Fault occurred. */ -#define RESET_COMPLETED (1U << 8) /* Set when a reset has completed. */ -#define POWER_CHANGED_SINGLE \ - (1U << 9) /* Set when a single core has finished powering up or down. */ -#define POWER_CHANGED_ALL (1U << 10) /* Set when all cores have finished powering up or down. */ -#define PRFCNT_SAMPLE_COMPLETED (1U << 16) /* Set when a performance count sample has completed. */ -#define CLEAN_CACHES_COMPLETED (1U << 17) /* Set when a cache clean operation has completed. */ -#define FLUSH_PA_RANGE_COMPLETED \ - (1 << 20) /* Set when a physical range cache clean operation has completed. */ - -/* - * In Debug build, - * GPU_IRQ_REG_COMMON | POWER_CHANGED_SINGLE is used to clear and enable - * interrupts sources of GPU_IRQ by writing it onto GPU_IRQ_CLEAR/MASK registers. - * - * In Release build, - * GPU_IRQ_REG_COMMON is used. - * - * Note: - * CLEAN_CACHES_COMPLETED - Used separately for cache operation. - */ -#define GPU_IRQ_REG_COMMON \ - (GPU_FAULT | MULTIPLE_GPU_FAULTS | RESET_COMPLETED | POWER_CHANGED_ALL | \ - PRFCNT_SAMPLE_COMPLETED) - -#define WINDOW_IRQ_MESSAGE (1U << 0) -#define WINDOW_IRQ_INVALID_ACCESS (1U << 1) -#define WINDOW_IRQ_GPU (1U << 2) -#define WINDOW_IRQ_JOB (1U << 3) -#define WINDOW_IRQ_MMU (1U << 4) -#define WINDOW_IRQ_EVENT (1U << 5) - -#endif /* _MALI_KBASE_REGMAP_JM_MACROS_H_ */ diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_csf.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_csf.h index 0e3a56e9d664..0678cf76fc0a 100644 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_csf.h +++ b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_csf.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -22,9 +22,6 @@ #ifndef _MALI_KBASE_REGMAP_LEGACY_CSF_H_ #define _MALI_KBASE_REGMAP_LEGACY_CSF_H_ -#if !MALI_USE_CSF && defined(__KERNEL__) -#error "Cannot be compiled with JM" -#endif /* GPU control registers */ #define MCU_CONTROL 0x700 diff --git a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_jm.h b/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_jm.h deleted file mode 100644 index c1a54991f4c6..000000000000 --- a/drivers/gpu/arm/valhall/hw_access/regmap/mali_kbase_regmap_legacy_jm.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _MALI_KBASE_REGMAP_LEGACY_JM_H_ -#define _MALI_KBASE_REGMAP_LEGACY_JM_H_ - -#if MALI_USE_CSF && defined(__KERNEL__) -#error "Cannot be compiled with CSF" -#endif - -/* GPU control registers */ -#define CORE_FEATURES 0x008 /* (RO) Shader Core Features */ -#define JS_PRESENT 0x01C /* (RO) Job slots present */ -#define LATEST_FLUSH 0x038 /* (RO) Flush ID of latest clean-and-invalidate operation */ -#define PRFCNT_BASE_LO 0x060 /* (RW) Performance counter memory region base address, low word */ -#define PRFCNT_BASE_HI 0x064 /* (RW) Performance counter memory region base address, high word */ -#define PRFCNT_CONFIG 0x068 /* (RW) Performance counter configuration */ -#define PRFCNT_JM_EN 0x06C /* (RW) Performance counter enable flags for Job Manager */ -#define PRFCNT_SHADER_EN 0x070 /* (RW) Performance counter enable flags for shader cores */ -#define PRFCNT_TILER_EN 0x074 /* (RW) Performance counter enable flags for tiler */ -#define PRFCNT_MMU_L2_EN 0x07C /* (RW) Performance counter enable flags for MMU/L2 cache */ - -#define JS0_FEATURES 0x0C0 /* (RO) Features of job slot 0 */ -#define JS1_FEATURES 0x0C4 /* (RO) Features of job slot 1 */ -#define JS2_FEATURES 0x0C8 /* (RO) Features of job slot 2 */ -#define JS3_FEATURES 0x0CC /* (RO) Features of job slot 3 */ -#define JS4_FEATURES 0x0D0 /* (RO) Features of job slot 4 */ -#define JS5_FEATURES 0x0D4 /* (RO) Features of job slot 5 */ -#define JS6_FEATURES 0x0D8 /* (RO) Features of job slot 6 */ -#define JS7_FEATURES 0x0DC /* (RO) Features of job slot 7 */ -#define JS8_FEATURES 0x0E0 /* (RO) Features of job slot 8 */ -#define JS9_FEATURES 0x0E4 /* (RO) Features of job slot 9 */ -#define JS10_FEATURES 0x0E8 /* (RO) Features of job slot 10 */ -#define JS11_FEATURES 0x0EC /* (RO) Features of job slot 11 */ -#define JS12_FEATURES 0x0F0 /* (RO) Features of job slot 12 */ -#define JS13_FEATURES 0x0F4 /* (RO) Features of job slot 13 */ -#define JS14_FEATURES 0x0F8 /* (RO) Features of job slot 14 */ -#define JS15_FEATURES 0x0FC /* (RO) Features of job slot 15 */ - -#define JS_FEATURES_REG(n) GPU_CONTROL_REG(JS0_FEATURES + ((n) << 2)) - -#define JM_CONFIG 0xF00 /* (RW) Job manager configuration (implementation-specific) */ - -/* Job control registers */ -/* status==active and _next == busy snapshot from last JOB_IRQ_CLEAR */ -#define JOB_IRQ_JS_STATE 0x010 -/* cycles to delay delivering an interrupt externally. The JOB_IRQ_STATUS - * is NOT affected by this, just the delivery of the interrupt. - */ -#define JOB_IRQ_THROTTLE 0x014 - -#define JOB_SLOT0 0x800 /* Configuration registers for job slot 0 */ -#define JOB_SLOT_REG(n, r) (JOB_CONTROL_REG(JOB_SLOT0 + ((n) << 7)) + (r)) -#define JOB_SLOT1 0x880 /* Configuration registers for job slot 1 */ -#define JOB_SLOT2 0x900 /* Configuration registers for job slot 2 */ -#define JOB_SLOT3 0x980 /* Configuration registers for job slot 3 */ -#define JOB_SLOT4 0xA00 /* Configuration registers for job slot 4 */ -#define JOB_SLOT5 0xA80 /* Configuration registers for job slot 5 */ -#define JOB_SLOT6 0xB00 /* Configuration registers for job slot 6 */ -#define JOB_SLOT7 0xB80 /* Configuration registers for job slot 7 */ -#define JOB_SLOT8 0xC00 /* Configuration registers for job slot 8 */ -#define JOB_SLOT9 0xC80 /* Configuration registers for job slot 9 */ -#define JOB_SLOT10 0xD00 /* Configuration registers for job slot 10 */ -#define JOB_SLOT11 0xD80 /* Configuration registers for job slot 11 */ -#define JOB_SLOT12 0xE00 /* Configuration registers for job slot 12 */ -#define JOB_SLOT13 0xE80 /* Configuration registers for job slot 13 */ -#define JOB_SLOT14 0xF00 /* Configuration registers for job slot 14 */ -#define JOB_SLOT15 0xF80 /* Configuration registers for job slot 15 */ - -/* JM Job control register definitions for mali_kbase_debug_job_fault */ -#define JS_HEAD_LO 0x00 /* (RO) Job queue head pointer for job slot n, low word */ -#define JS_HEAD_HI 0x04 /* (RO) Job queue head pointer for job slot n, high word */ -#define JS_TAIL_LO 0x08 /* (RO) Job queue tail pointer for job slot n, low word */ -#define JS_TAIL_HI 0x0C /* (RO) Job queue tail pointer for job slot n, high word */ -#define JS_AFFINITY_LO 0x10 /* (RO) Core affinity mask for job slot n, low word */ -#define JS_AFFINITY_HI 0x14 /* (RO) Core affinity mask for job slot n, high word */ -#define JS_CONFIG 0x18 /* (RO) Configuration settings for job slot n */ -#define JS_XAFFINITY 0x1C /* (RO) Extended affinity mask for job slot n*/ -#define JS_COMMAND 0x20 /* (WO) Command register for job slot n */ -#define JS_STATUS 0x24 /* (RO) Status register for job slot n */ -#define JS_HEAD_NEXT_LO 0x40 /* (RW) Next job queue head pointer for job slot n, low word */ -#define JS_HEAD_NEXT_HI 0x44 /* (RW) Next job queue head pointer for job slot n, high word */ -#define JS_AFFINITY_NEXT_LO 0x50 /* (RW) Next core affinity mask for job slot n, low word */ -#define JS_AFFINITY_NEXT_HI 0x54 /* (RW) Next core affinity mask for job slot n, high word */ -#define JS_CONFIG_NEXT 0x58 /* (RW) Next configuration settings for job slot n */ -#define JS_XAFFINITY_NEXT 0x5C /* (RW) Next extended affinity mask for job slot n */ -#define JS_COMMAND_NEXT 0x60 /* (RW) Next command register for job slot n */ -#define JS_FLUSH_ID_NEXT 0x70 /* (RW) Next job slot n cache flush ID */ - -#endif /* _MALI_KBASE_REGMAP_LEGACY_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/hwcnt/Kbuild b/drivers/gpu/arm/valhall/hwcnt/Kbuild index f26717e92e0f..2bd5848984f3 100644 --- a/drivers/gpu/arm/valhall/hwcnt/Kbuild +++ b/drivers/gpu/arm/valhall/hwcnt/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2022 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2022, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -23,14 +23,6 @@ valhall_kbase-y += \ hwcnt/mali_kbase_hwcnt_gpu.o \ hwcnt/mali_kbase_hwcnt_types.o \ hwcnt/mali_kbase_hwcnt_virtualizer.o \ - hwcnt/mali_kbase_hwcnt_watchdog_if_timer.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += \ - hwcnt/backend/mali_kbase_hwcnt_backend_csf.o \ - hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.o -else - valhall_kbase-y += \ - hwcnt/backend/mali_kbase_hwcnt_backend_jm.o \ - hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.o -endif + hwcnt/mali_kbase_hwcnt_watchdog_if_timer.o \ + hwcnt/backend/mali_kbase_hwcnt_backend_csf.o \ + hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.o diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c index 723ae207070e..7f33aa6e3942 100644 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c +++ b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.c @@ -39,6 +39,9 @@ /* Used to check for a sample in which all counters in the block are disabled */ #define HWCNT_BLOCK_EMPTY_SAMPLE (2) +#define RING_BUF_REFCNT_MAX 2 +#define RING_BUF_REFCNT_MIN 0 + /** * enum kbase_hwcnt_backend_csf_dump_state - HWC CSF backend dumping states. * @@ -99,17 +102,26 @@ enum kbase_hwcnt_backend_csf_dump_state { * @KBASE_HWCNT_BACKEND_CSF_DISABLED: Initial state, and the state when backend * is disabled. * - * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED: Enable request is in - * progress, waiting for firmware acknowledgment. + * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ: Backend is + * being enabled, pending to send enable REQ to firmware. + * + * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK: Enable REQ + * has been sent to FW, waiting for firmware acknowledgment. * * @KBASE_HWCNT_BACKEND_CSF_ENABLED: Enable request has been acknowledged, * enable is done. * - * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED: Disable request is in - * progress, waiting for firmware acknowledgment. + * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ: Backend is + * being disabled, pending to send disable REQ to firmware. + * + * @KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK: Disable REQ + * has been sent to FW, waiting for firmware acknowledgment. * * @KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: Disable request has been * acknowledged, waiting for dump workers to be finished. + * Note: This is mainly used when recovering from a recoverable error. During a + * clean disable procedure, backend will transition directly to DISABLED state + * after being ACKed. * * @KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: An * unrecoverable error happened, waiting for dump workers to be finished. @@ -118,26 +130,52 @@ enum kbase_hwcnt_backend_csf_dump_state { * happened, and dump workers have finished, waiting for reset. * * Valid state transitions: - * DISABLED -> TRANSITIONING_TO_ENABLED (on enable) - * TRANSITIONING_TO_ENABLED -> ENABLED (on enable ack) - * ENABLED -> TRANSITIONING_TO_DISABLED (on disable) - * TRANSITIONING_TO_DISABLED -> DISABLED_WAIT_FOR_WORKER (on disable ack) - * DISABLED_WAIT_FOR_WORKER -> DISABLED (after workers are flushed) - * DISABLED -> UNRECOVERABLE_ERROR (on unrecoverable error) - * ANY but DISABLED -> UNRECOVERABLE_ERROR_WAIT_FOR_WORKER (on unrecoverable - * error) - * UNRECOVERABLE_ERROR -> DISABLED (on before reset) + * - DISABLED -> TRANSITIONING_TO_ENABLED_PENDING_REQ (on enable before sending REQ) + * - TRANSITIONING_TO_ENABLED_PENDING_REQ -> + * TRANSITIONING_TO_ENABLED_PENDING_ACK (on sending enable REQ) + * - TRANSITIONING_TO_ENABLED_PENDING_ACK -> ENABLED (on enable ack) + * - ENABLED -> TRANSITIONING_TO_DISABLED_PENDING_REQ (on disable before sending REQ) + * - TRANSITIONING_TO_DISABLED_PENDING_REQ -> + * TRANSITIONING_TO_DISABLED_PENDING_ACK (on sending disable REQ) + * - TRANSITIONING_TO_DISABLED_PENDING_ACK -> DISABLED (on disable ack) + * - TRANSITIONING_TO_DISABLED_PENDING_ACK -> DISABLED_WAIT_FOR_WORKER (on disable ack + * after a recoverable error) + * - DISABLED_WAIT_FOR_WORKER -> DISABLED (after workers are flushed) + * - UNRECOVERABLE_ERROR_WAIT_FOR_WORKER -> UNRECOVERABLE_ERROR (after workers are flushed) + * - DISABLED -> UNRECOVERABLE_ERROR (on unrecoverable error) + * - ANY but DISABLED -> UNRECOVERABLE_ERROR_WAIT_FOR_WORKER (on unrecoverable error) + * - UNRECOVERABLE_ERROR -> DISABLED (on before reset) + * + * More valid state transitions due to MCU being powered off: + * - TRANSITIONING_TO_ENABLED_PENDING_* -> + * TRANSITIONING_TO_DISABLED_PENDING_* (backend needs to be disabled + * but enable REQ hasn't been sent or ACK not received + * due to MCU being OFF) + * - TRANSITIONING_TO_DISABLED_PENDING_* -> + * TRANSITIONING_TO_ENABLED_PENDING_* (opposite case to the previous one) */ enum kbase_hwcnt_backend_csf_enable_state { KBASE_HWCNT_BACKEND_CSF_DISABLED, - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK, KBASE_HWCNT_BACKEND_CSF_ENABLED, - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK, KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR, }; +enum kbase_hwcnt_backend_block_type { + KBASE_HWCNT_BLOCK_METADATA, + KBASE_HWCNT_BLOCK_FW, + KBASE_HWCNT_BLOCK_CSHW, + KBASE_HWCNT_BLOCK_TILER, + KBASE_HWCNT_BLOCK_MEMSYS, + KBASE_HWCNT_BLOCK_SHADER, + KBASE_HWCNT_BLOCK_NEURAL +}; + /** * struct kbase_hwcnt_backend_csf_info - Information used to create an instance * of a CSF hardware counter backend. @@ -153,6 +191,19 @@ enum kbase_hwcnt_backend_csf_enable_state { * @prfcnt_info: Performance counter information. * @watchdog_if: Watchdog interface object pointer. * @watchdog_timer_interval_ms: Watchdog timer interval + * @last_transition: Last backend state transition obtained + * from the metadata block. + * @mcu_on: True if MCU is powered on. + * @ring_buf: Opaque pointer for ring buffer object. + * @ring_buf_cpu_base: CPU base address of the allocated ring buffer. + * @ring_buf_refcnt: Reference counter for ring buffer, used to control + * its allocation across MCU power cycles. + * @hwc_deferred_op_workq: Workqueue for deferred operations on the backend, + * e.g. due to MCU power cycle. + * @hwc_dump_reenable_work: Worker for re-enabling the backend after MCU ON notification. + * @hwc_ring_buf_free_work: Worker for freeing the ring buffer. + * @ring_buf_cleanup: Pointer to the ring buffer that needs to be freed. + * @pending_disable_req: True if disable REQ is pending to be sent when MCU is powered on. */ struct kbase_hwcnt_backend_csf_info { struct kbase_hwcnt_backend_csf *backend; @@ -165,6 +216,19 @@ struct kbase_hwcnt_backend_csf_info { struct kbase_hwcnt_backend_csf_if_prfcnt_info prfcnt_info; struct kbase_hwcnt_watchdog_interface *watchdog_if; u32 watchdog_timer_interval_ms; + enum kbase_hwcnt_backend_sample_reason last_transition; + bool mcu_on; + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf; + void *ring_buf_cpu_base; + struct kbasep_hwcnt_ring_buf_refcnt { + int val; + bool incremented_on_mcu_off; + } ring_buf_refcnt; + struct workqueue_struct *hwc_deferred_op_workq; + struct work_struct hwc_dump_reenable_work; + struct work_struct hwc_ring_buf_free_work; + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf_cleanup; + bool pending_disable_req; }; /** @@ -179,7 +243,10 @@ struct kbase_hwcnt_backend_csf_info { * @hw_block_cnt: Total number of hardware counter blocks. The hw counters blocks are * sub-categorized into 4 classes: front-end, tiler, memory system, and shader. * hw_block_cnt = fe_cnt + tiler_cnt + mmu_l2_cnt + shader_cnt. - * @block_cnt: Total block count (sum of all counter blocks: hw_block_cnt + fw_block_cnt). + * @md_block_cnt: Total number of metadata counter blocks. + * @ringbuf_block_cnt: Total block count (sum of all counter blocks: hw_block_cnt + fw_block_cnt + * + md_block_cnt). + * @payload_block_cnt: Total number of payload counter blocks: hw_block_cnt + fw_block_cnt. * @shader_avail_mask: Bitmap of all shader cores in the system. * @enable_mask_offset: Offset in array elements of enable mask in each block * starting from the beginning of block. @@ -195,7 +262,9 @@ struct kbase_hwcnt_csf_physical_layout { u8 shader_cnt; u8 fw_block_cnt; u8 hw_block_cnt; - u8 block_cnt; + u8 md_block_cnt; + u8 ringbuf_block_cnt; + u8 payload_block_cnt; u64 shader_avail_mask; size_t enable_mask_offset; size_t headers_per_block; @@ -229,8 +298,6 @@ struct kbase_hwcnt_csf_physical_layout { * seen, to check any new firmware automatic * samples generated during the watchdog * period. - * @ring_buf: Opaque pointer for ring buffer object. - * @ring_buf_cpu_base: CPU base address of the allocated ring buffer. * @clk_enable_map: The enable map specifying enabled clock domains. * @cycle_count_elapsed: Cycle count elapsed for a given sample period. * @prev_cycle_count: Previous cycle count to calculate the cycle @@ -258,6 +325,13 @@ struct kbase_hwcnt_csf_physical_layout { * is converted from the TIMESTAMP of a dump to CPU MONOTONIC * time. Then it's returned to the caller via 'dump_time_ns' * parameter of dump_get function. + * @last_enable_map: Record of the last requested enable map. + * Used to reapply dump enable request on MCU ON notification. + * @dump_reenable_in_progress: True if backend reenable procedure is in progress. + * @flush_on_disable_in_progress: True when the dump workers are being flushed during dump + * disable procedure. This is needed to prevent the backend + * from being enabled. + * @flush_workers_needed: True when the dump workers need to be flushed. */ struct kbase_hwcnt_backend_csf { struct kbase_hwcnt_backend_csf_info *info; @@ -272,8 +346,6 @@ struct kbase_hwcnt_backend_csf { blk_stt_t *block_states; blk_stt_t *to_user_block_states; u32 watchdog_last_seen_insert_idx; - struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf; - void *ring_buf_cpu_base; u64 clk_enable_map; u64 cycle_count_elapsed[BASE_MAX_NR_CLOCKS_REGULATORS]; u64 prev_cycle_count[BASE_MAX_NR_CLOCKS_REGULATORS]; @@ -286,8 +358,36 @@ struct kbase_hwcnt_backend_csf { size_t num_l2_slices; u64 powered_shader_core_mask; u64 dump_time_ns; + struct kbase_hwcnt_enable_map last_enable_map; + bool dump_reenable_in_progress; + bool flush_on_disable_in_progress; + bool flush_workers_needed; }; +/* Forward declarations. */ +static void +kbasep_hwcnt_backend_csf_handle_unrecoverable_error(struct kbase_hwcnt_backend_csf *backend_csf); + +static inline bool +kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(enum kbase_hwcnt_backend_csf_enable_state state) +{ + return (state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ) || + (state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK); +} + +static inline bool +kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(enum kbase_hwcnt_backend_csf_enable_state state) +{ + return (state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ) || + (state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK); +} + +static inline bool +kbasep_hwcnt_backend_csf_is_error_state(enum kbase_hwcnt_backend_csf_enable_state state) +{ + return (state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER) || + (state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); +} static bool kbasep_hwcnt_backend_csf_backend_exists(struct kbase_hwcnt_backend_csf_info *csf_info) { if (WARN_ON(!csf_info)) @@ -338,7 +438,8 @@ void kbase_hwcnt_backend_csf_set_hw_availability(struct kbase_hwcnt_backend_inte norm_shader_present = virtual_core_mask; } - if (WARN_ON(csf_info->backend->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED)) + /* MCU needs to be powered off. */ + if (WARN_ON(csf_info->mcu_on)) return; if (WARN_ON(num_l2_slices > csf_info->backend->phys_layout.mmu_l2_cnt) || @@ -448,6 +549,7 @@ static void kbasep_hwcnt_backend_csf_init_layout( size_t values_per_block; size_t fw_block_cnt; size_t hw_block_cnt; + size_t md_block_cnt; size_t core_cnt; size_t ne_core_cnt; @@ -458,6 +560,7 @@ static void kbasep_hwcnt_backend_csf_init_layout( values_per_block = prfcnt_info->prfcnt_block_size / KBASE_HWCNT_VALUE_HW_BYTES; fw_block_cnt = div_u64(prfcnt_info->prfcnt_fw_size, prfcnt_info->prfcnt_block_size); hw_block_cnt = div_u64(prfcnt_info->prfcnt_hw_size, prfcnt_info->prfcnt_block_size); + md_block_cnt = div_u64(prfcnt_info->metadata_size, prfcnt_info->prfcnt_block_size); core_cnt = shader_core_cnt; /* In the presence of heterogeneous NE, the SCs that don't have dedicated @@ -479,7 +582,9 @@ static void kbasep_hwcnt_backend_csf_init_layout( .shader_cnt = shader_core_cnt, .fw_block_cnt = fw_block_cnt, .hw_block_cnt = hw_block_cnt, - .block_cnt = fw_block_cnt + hw_block_cnt, + .md_block_cnt = md_block_cnt, + .ringbuf_block_cnt = fw_block_cnt + hw_block_cnt + md_block_cnt, + .payload_block_cnt = fw_block_cnt + hw_block_cnt, .shader_avail_mask = prfcnt_info->sc_core_mask, .headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK, .values_per_block = values_per_block, @@ -493,7 +598,7 @@ static void kbasep_hwcnt_backend_csf_reset_internal_buffers(struct kbase_hwcnt_backend_csf *backend_csf) { size_t user_buf_bytes = backend_csf->info->metadata->dump_buf_bytes; - size_t block_state_bytes = backend_csf->phys_layout.block_cnt * + size_t block_state_bytes = backend_csf->phys_layout.payload_block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; memset(backend_csf->accum_buf, 0, user_buf_bytes); @@ -506,7 +611,7 @@ static void kbasep_hwcnt_backend_csf_reset_consumed_buffers(struct kbase_hwcnt_backend_csf *backend_csf) { size_t user_buf_bytes = backend_csf->info->metadata->dump_buf_bytes; - size_t block_state_bytes = backend_csf->phys_layout.block_cnt * + size_t block_state_bytes = backend_csf->phys_layout.payload_block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; memset(backend_csf->to_user_buf, 0, user_buf_bytes); @@ -523,7 +628,7 @@ kbasep_hwcnt_backend_csf_zero_sample_prfcnt_en_header(struct kbase_hwcnt_backend phys_layout = &backend_csf->phys_layout; - for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) { + for (block_idx = 0; block_idx < phys_layout->ringbuf_block_cnt; block_idx++) { block_buf = sample + block_idx * phys_layout->values_per_block; block_buf[phys_layout->enable_mask_offset] = 0; } @@ -537,7 +642,9 @@ kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(struct kbase_hwcnt_backend_cs char *cpu_dump_base; size_t dump_bytes = backend_csf->info->prfcnt_info.dump_bytes; - cpu_dump_base = (char *)backend_csf->ring_buf_cpu_base; + cpu_dump_base = (char *)backend_csf->info->ring_buf_cpu_base; + if (WARN_ON(!cpu_dump_base)) + return; for (idx = 0; idx < backend_csf->info->ring_buf_cnt; idx++) { sample = (u32 *)&cpu_dump_base[idx * dump_bytes]; @@ -548,18 +655,18 @@ kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(struct kbase_hwcnt_backend_cs static void kbasep_hwcnt_backend_csf_update_user_sample(struct kbase_hwcnt_backend_csf *backend_csf) { const size_t user_buf_bytes = backend_csf->info->metadata->dump_buf_bytes; - const size_t block_cnt = backend_csf->phys_layout.block_cnt; + const size_t payload_block_cnt = backend_csf->phys_layout.payload_block_cnt; const size_t block_state_bytes = - block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; + payload_block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; size_t i; /* Copy the data into the sample and wait for the user to get it. */ memcpy(backend_csf->to_user_buf, backend_csf->accum_buf, user_buf_bytes); - for (i = 0; i < block_cnt; i++) + for (i = 0; i < payload_block_cnt; i++) kbase_hwcnt_block_state_append(&backend_csf->to_user_block_states[i], backend_csf->block_states[i]); - /* After copied data into user sample, clear the accumulator values to + /* After copying data into user sample, clear the accumulator values to * prepare for the next accumulator, such as the next request or * threshold. */ @@ -568,45 +675,99 @@ static void kbasep_hwcnt_backend_csf_update_user_sample(struct kbase_hwcnt_backe memset(backend_csf->block_states, 0, block_state_bytes); } -void kbasep_hwcnt_backend_csf_update_block_state(struct kbase_hwcnt_backend_csf *backend, - const u32 enable_mask, bool exiting_protm, - size_t block_idx, blk_stt_t *const block_state, - bool fw_in_protected_mode) +static enum kbase_hwcnt_backend_block_type kbase_hwcnt_backend_csf_identify_block_type( + const struct kbase_hwcnt_csf_physical_layout *phys_layout, size_t block_idx, + size_t *const block_in_type_idx) { - const struct kbase_hwcnt_csf_physical_layout *phys_layout = &backend->phys_layout; - /* Offset of shader core blocks from the start of the HW blocks in the sample */ - size_t shader_core_block_offset = - (size_t)(phys_layout->block_cnt - phys_layout->shader_cnt); - bool is_shader_core_block; + const size_t fw_block_offset = phys_layout->md_block_cnt; + const size_t cshw_block_offset = fw_block_offset + phys_layout->fw_block_cnt; + const size_t tiler_block_offset = cshw_block_offset + phys_layout->fe_cnt; + const size_t memsys_block_offset = tiler_block_offset + phys_layout->tiler_cnt; + const size_t shader_core_block_offset = memsys_block_offset + phys_layout->mmu_l2_cnt; + const size_t neural_core_block_offset = shader_core_block_offset + phys_layout->shader_cnt; - size_t neural_core_block_offset = phys_layout->block_cnt - phys_layout->ne_cnt; - bool is_neural_core_block = (block_idx >= neural_core_block_offset); - shader_core_block_offset -= phys_layout->ne_cnt; - is_shader_core_block = - ((block_idx >= shader_core_block_offset) && (block_idx < neural_core_block_offset)); + if (block_idx < fw_block_offset) { + *block_in_type_idx = block_idx; + + return KBASE_HWCNT_BLOCK_METADATA; + } + + if ((fw_block_offset <= block_idx) && (block_idx < cshw_block_offset)) { + *block_in_type_idx = block_idx - fw_block_offset; + + return KBASE_HWCNT_BLOCK_FW; + } + + if ((cshw_block_offset <= block_idx) && (block_idx < tiler_block_offset)) { + *block_in_type_idx = block_idx - cshw_block_offset; + + return KBASE_HWCNT_BLOCK_CSHW; + } + + if ((tiler_block_offset <= block_idx) && (block_idx < memsys_block_offset)) { + *block_in_type_idx = block_idx - tiler_block_offset; + + return KBASE_HWCNT_BLOCK_TILER; + } + + if ((memsys_block_offset <= block_idx) && (block_idx < shader_core_block_offset)) { + *block_in_type_idx = block_idx - memsys_block_offset; + + return KBASE_HWCNT_BLOCK_MEMSYS; + } + if ((shader_core_block_offset <= block_idx) && (block_idx < neural_core_block_offset)) { + *block_in_type_idx = block_idx - shader_core_block_offset; + + return KBASE_HWCNT_BLOCK_SHADER; + } + + if ((neural_core_block_offset <= block_idx) && + (block_idx < phys_layout->ringbuf_block_cnt)) { + *block_in_type_idx = block_idx - neural_core_block_offset; + + return KBASE_HWCNT_BLOCK_NEURAL; + } + + WARN(1, "Unknown block index %zu", block_idx); + *block_in_type_idx = 0; + return KBASE_HWCNT_BLOCK_CSHW; +} + +void kbasep_hwcnt_backend_csf_update_block_state( + struct kbase_hwcnt_backend_csf *backend, const u32 enable_mask, size_t block_idx, + blk_stt_t *const block_state, enum kbase_hwcnt_backend_sample_reason prev_sample_reason, + enum kbase_hwcnt_backend_sample_reason curr_sample_reason) +{ + size_t idx_in_block_type = 0; + enum kbase_hwcnt_backend_block_type type = kbase_hwcnt_backend_csf_identify_block_type( + &backend->phys_layout, block_idx, &idx_in_block_type); + + bool sample_in_protected_mode = (curr_sample_reason == SAMPLE_REASON_BEFORE_PROTM); + bool sample_exiting_protm = (prev_sample_reason == SAMPLE_REASON_BEFORE_PROTM); + bool is_block_on = false; /* Set power bits for the block state for the block, for the sample */ switch (backend->enable_state) { /* Disabled states */ case KBASE_HWCNT_BACKEND_CSF_DISABLED: - case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK: case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: - kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_OFF); + /* Nothing to do */ break; /* Enabled states */ case KBASE_HWCNT_BACKEND_CSF_ENABLED: - case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED: - if (!is_shader_core_block) - kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_ON); - else if (!exiting_protm) { + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK: + if (type != KBASE_HWCNT_BLOCK_SHADER) + is_block_on = true; + else if (!sample_exiting_protm) { /* When not exiting protected mode, a zero enable mask on a shader core * counter block indicates the block was powered off for the sample, and * a non-zero counter enable mask indicates the block was powered on for * the sample. */ - kbase_hwcnt_block_state_append(block_state, - (enable_mask ? KBASE_HWCNT_STATE_ON : - KBASE_HWCNT_STATE_OFF)); + is_block_on = !!enable_mask; } break; /* Error states */ @@ -617,6 +778,12 @@ void kbasep_hwcnt_backend_csf_update_block_state(struct kbase_hwcnt_backend_csf break; } + if (curr_sample_reason == SAMPLE_REASON_BEFORE_SLEEP) + is_block_on = false; + + kbase_hwcnt_block_state_append(block_state, + is_block_on ? KBASE_HWCNT_STATE_ON : KBASE_HWCNT_STATE_OFF); + /* The following four cases apply to a block state in either normal mode or protected mode: * 1. GPU executing in normal mode: Only set normal mode bit. * 2. First sample request after GPU enters protected mode: Set both normal mode and @@ -629,7 +796,7 @@ void kbasep_hwcnt_backend_csf_update_block_state(struct kbase_hwcnt_backend_csf * 4. Samples requested after GPU exits protected mode: Set both protected mode and normal * mode bits. */ - if (exiting_protm || fw_in_protected_mode) + if (sample_exiting_protm || sample_in_protected_mode) kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_PROTECTED | KBASE_HWCNT_STATE_NORMAL); else @@ -639,30 +806,54 @@ void kbasep_hwcnt_backend_csf_update_block_state(struct kbase_hwcnt_backend_csf * the shader present and the debug core mask, so explicit checking of the * core mask is not required here. */ - if (is_shader_core_block) { - u64 current_shader_core = 1ULL << (block_idx - shader_core_block_offset); + switch (type) { + case KBASE_HWCNT_BLOCK_METADATA: + case KBASE_HWCNT_BLOCK_FW: + case KBASE_HWCNT_BLOCK_CSHW: + case KBASE_HWCNT_BLOCK_TILER: + case KBASE_HWCNT_BLOCK_MEMSYS: + if (curr_sample_reason == SAMPLE_REASON_BEFORE_YIELD) + kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_UNAVAILABLE); + else + kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_AVAILABLE); + break; + case KBASE_HWCNT_BLOCK_SHADER: { + u64 current_shader_core = 1ULL << idx_in_block_type; - WARN_ON_ONCE(backend->phys_layout.shader_cnt > 64); + WARN_ONCE(backend->phys_layout.shader_cnt > 64, + "More than 64 SCs will cause an overflow!"); - if (current_shader_core & backend->info->backend->powered_shader_core_mask) + if (curr_sample_reason == SAMPLE_REASON_BEFORE_YIELD) + kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_UNAVAILABLE); + else if (current_shader_core & backend->info->backend->powered_shader_core_mask) kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_AVAILABLE); else if (current_shader_core & ~backend->info->backend->powered_shader_core_mask) kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_UNAVAILABLE); else - WARN_ON_ONCE(true); - } else if (is_neural_core_block) { - u64 current_neural_core = 1ULL << (block_idx - neural_core_block_offset); + WARN_ONCE(true, "Unknown SC availability state!"); + break; + } + case KBASE_HWCNT_BLOCK_NEURAL: { + u64 current_neural_core = 1ULL << idx_in_block_type; - WARN_ON_ONCE(backend->phys_layout.ne_cnt > 64); + WARN_ONCE(backend->phys_layout.ne_cnt > 64, + "More than 64 NE cores may cause an overflow!"); - if (current_neural_core & backend->info->prfcnt_info.ne_core_mask) + if (curr_sample_reason == SAMPLE_REASON_BEFORE_YIELD) + kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_UNAVAILABLE); + else if (current_neural_core & backend->info->prfcnt_info.ne_core_mask) kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_AVAILABLE); else if (current_neural_core & ~backend->info->prfcnt_info.ne_core_mask) kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_UNAVAILABLE); else - WARN_ON_ONCE(true); - } else - kbase_hwcnt_block_state_append(block_state, KBASE_HWCNT_STATE_AVAILABLE); + WARN_ONCE(true, "Unknown NE core availability state!"); + break; + } + default: + WARN_ONCE(true, "Unknown block type returned (type = %u)", + type); /* This shouldn't happen */ + break; + } } static void kbasep_hwcnt_backend_csf_accumulate_sample(struct kbase_hwcnt_backend_csf *backend, @@ -670,35 +861,40 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample(struct kbase_hwcnt_backen const u32 *new_sample_buf) { const struct kbase_hwcnt_csf_physical_layout *phys_layout = &backend->phys_layout; - const size_t dump_bytes = backend->info->prfcnt_info.dump_bytes; + struct kbase_hwcnt_backend_csf_if_prfcnt_info *prfcnt_info = &backend->info->prfcnt_info; + const size_t dump_bytes = prfcnt_info->dump_bytes; const size_t values_per_block = phys_layout->values_per_block; blk_stt_t *const block_states = backend->block_states; - const bool fw_in_protected_mode = backend->info->fw_in_protected_mode; - const bool clearing_samples = backend->info->prfcnt_info.clearing_samples; + enum kbase_hwcnt_backend_sample_reason prev_sample_reason = backend->info->last_transition; + enum kbase_hwcnt_backend_sample_reason curr_sample_reason = SAMPLE_REASON_NONE; + const bool clearing_samples = prfcnt_info->clearing_samples; u64 *accum_buf = backend->accum_buf; size_t block_idx; + const size_t metadata_size = prfcnt_info->metadata_size; const u32 *old_block = old_sample_buf; const u32 *new_block = new_sample_buf; u64 *acc_block = accum_buf; - /* Flag to indicate whether current sample is exiting protected mode. */ - bool exiting_protm = false; - /* The block pointers now point to the first HW block, which is always a CSHW/front-end - * block. The counter enable mask for this block can be checked to determine whether this - * sample is taken after leaving protected mode - this is the only scenario where the CSHW - * block counter enable mask has only the first bit set, and no others. In this case, - * the values in this sample would not be meaningful, so they don't need to be accumulated. - */ - exiting_protm = (new_block[phys_layout->enable_mask_offset] == 1); + size_t num_meta_blocks = prfcnt_info->metadata_size / prfcnt_info->prfcnt_block_size; + size_t num_meta_counters = num_meta_blocks * values_per_block; - for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) { + const unsigned int METADATA_SAMPLE_REASON_OFFSET = 3; + + if (backend->phys_layout.md_block_cnt) + curr_sample_reason = new_block[METADATA_SAMPLE_REASON_OFFSET]; + + old_block += num_meta_counters; + new_block += num_meta_counters; + + for (block_idx = 0; block_idx < phys_layout->payload_block_cnt; block_idx++) { const u32 old_enable_mask = old_block[phys_layout->enable_mask_offset]; const u32 new_enable_mask = new_block[phys_layout->enable_mask_offset]; /* Update block state with information of the current sample */ - kbasep_hwcnt_backend_csf_update_block_state(backend, new_enable_mask, exiting_protm, - block_idx, &block_states[block_idx], - fw_in_protected_mode); + kbasep_hwcnt_backend_csf_update_block_state(backend, new_enable_mask, + block_idx + phys_layout->md_block_cnt, + &block_states[block_idx], + prev_sample_reason, curr_sample_reason); if (!(new_enable_mask & HWCNT_BLOCK_EMPTY_SAMPLE)) { /* Hardware block was unavailable or we didn't turn on @@ -728,8 +924,8 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample(struct kbase_hwcnt_backen * request samples without interfering with each other. * * However some early HW may not support wrapping - * counters, for these GPUs counters must be cleared on - * sample to avoid loss of data due to counters + * counters. For these GPUs, counters must be cleared + * on sample to avoid loss of data due to counters * saturating at their maximum value. */ if (!clearing_samples) { @@ -769,8 +965,12 @@ static void kbasep_hwcnt_backend_csf_accumulate_sample(struct kbase_hwcnt_backen } WARN_ON(old_block != old_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); WARN_ON(new_block != new_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); - WARN_ON(acc_block != accum_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); + WARN_ON(acc_block != + accum_buf + ((dump_bytes - metadata_size) / KBASE_HWCNT_VALUE_HW_BYTES)); (void)dump_bytes; + + if (backend->phys_layout.md_block_cnt) + backend->info->last_transition = curr_sample_reason; } static void kbasep_hwcnt_backend_csf_accumulate_samples(struct kbase_hwcnt_backend_csf *backend_csf, @@ -779,33 +979,39 @@ static void kbasep_hwcnt_backend_csf_accumulate_samples(struct kbase_hwcnt_backe { u32 raw_idx; unsigned long flags = 0UL; - u8 *cpu_dump_base = (u8 *)backend_csf->ring_buf_cpu_base; + u8 *cpu_dump_base = (u8 *)backend_csf->info->ring_buf_cpu_base; const size_t ring_buf_cnt = backend_csf->info->ring_buf_cnt; const size_t buf_dump_bytes = backend_csf->info->prfcnt_info.dump_bytes; u32 *old_sample_buf = backend_csf->old_sample_buf; u32 *new_sample_buf = old_sample_buf; - const struct kbase_hwcnt_csf_physical_layout *phys_layout = &backend_csf->phys_layout; if (extract_index_to_start == insert_index_to_stop) { /* No samples to accumulate but block states need to be updated for dump. */ size_t block_idx; - for (block_idx = 0; block_idx < phys_layout->block_cnt; block_idx++) { + /* We cannot use the last sample reason here, because the sequencing with the + * previous dump is not entirely clear and the required flag may not be set + * at that time. + */ + blk_stt_t stt = backend_csf->info->fw_in_protected_mode ? + KBASE_HWCNT_STATE_PROTECTED : + KBASE_HWCNT_STATE_NORMAL; + + for (block_idx = 0; block_idx < backend_csf->phys_layout.payload_block_cnt; + block_idx++) { /* Set protected mode bit for block state if GPU is in protected mode, * otherwise set the normal mode bit. */ - kbase_hwcnt_block_state_append(&backend_csf->block_states[block_idx], - backend_csf->info->fw_in_protected_mode ? - KBASE_HWCNT_STATE_PROTECTED : - KBASE_HWCNT_STATE_NORMAL); + kbase_hwcnt_block_state_append(&backend_csf->block_states[block_idx], stt); } return; } /* Sync all the buffers to CPU side before read the data. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, extract_index_to_start, - insert_index_to_stop, true); + backend_csf->info->ring_buf, + extract_index_to_start, insert_index_to_stop, + true); /* Consider u32 wrap case, '!=' is used here instead of '<' operator */ for (raw_idx = extract_index_to_start; raw_idx != insert_index_to_stop; raw_idx++) { @@ -834,8 +1040,9 @@ static void kbasep_hwcnt_backend_csf_accumulate_samples(struct kbase_hwcnt_backe /* Sync zeroed buffers to avoid coherency issues on future use. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, extract_index_to_start, - insert_index_to_stop, false); + backend_csf->info->ring_buf, + extract_index_to_start, insert_index_to_stop, + false); /* After consuming all samples between extract_idx and insert_idx, * set the raw extract index to insert_idx so that the sample buffers @@ -858,6 +1065,7 @@ static void kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); if (backend_csf->enable_state != new_state) { + pr_debug("%s %d -> %d", __func__, backend_csf->enable_state, new_state); backend_csf->enable_state = new_state; wake_up(&backend_csf->enable_state_waitq); @@ -872,7 +1080,8 @@ static void kbasep_hwcnt_backend_watchdog_timer_cb(void *info) csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); - if (WARN_ON(!kbasep_hwcnt_backend_csf_backend_exists(csf_info))) { + /* Early-exit if backend doesn't exist. */ + if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) { csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); return; } @@ -882,9 +1091,11 @@ static void kbasep_hwcnt_backend_watchdog_timer_cb(void *info) /* Only do watchdog request when all conditions are met: */ if (/* 1. Backend is enabled. */ (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) && - /* 2. FW is not in protected mode. */ + /* 2. MCU is ON. */ + csf_info->mcu_on && + /* 3. FW is not in protected mode. */ (!csf_info->fw_in_protected_mode) && - /* 3. dump state indicates no other dumping is in progress. */ + /* 4. dump state indicates no other dumping is in progress. */ ((backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE) || (backend_csf->dump_state == KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED))) { u32 extract_index = 0U; @@ -905,13 +1116,19 @@ static void kbasep_hwcnt_backend_watchdog_timer_cb(void *info) } } - /* Must schedule another callback when in the transitional state because - * this function can be called for the first time before the performance - * counter enabled interrupt. + /* Reschedule the next callback when watchdog is enabled (i.e. backend states ENABLED + * and KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK). + * + * Keep in mind that this function can be called for the first time + * before the performance counter enabled interrupt. + * + * Do not reschedule if MCU is off. */ - if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) || - (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED)) { - /* Reschedule the timer for next watchdog callback. */ + if (((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) || + (backend_csf->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK)) && + csf_info->mcu_on) { + /* Reschedule the timer for next watchdog callback.*/ csf_info->watchdog_if->modify(csf_info->watchdog_if->timer, csf_info->watchdog_timer_interval_ms); } @@ -935,7 +1152,9 @@ static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work) u32 extract_index = 0U; u32 insert_index = 0U; u64 ts_gpu, ts_dump_raw, ts_dump, ts_dump_request, ts_now; + u32 *ts_gpu_ptr; bool sample_accumulated; + size_t ts_offset_in_sample_buf; WARN_ON(!work); backend_csf = container_of(work, struct kbase_hwcnt_backend_csf, hwc_dump_work); @@ -982,7 +1201,11 @@ static void kbasep_hwcnt_backend_csf_dump_worker(struct work_struct *work) WARN_ON(backend_csf != backend_csf->info->backend); /* TIMESTAMP_LO/HI of the newest dump */ - ts_gpu = *(u64 *)backend_csf->old_sample_buf; + ts_offset_in_sample_buf = (backend_csf->phys_layout.md_block_cnt * + backend_csf->info->prfcnt_info.prfcnt_block_size) / + KBASE_HWCNT_VALUE_HW_BYTES; + ts_gpu_ptr = backend_csf->old_sample_buf + ts_offset_in_sample_buf; + ts_gpu = *(u64 *)ts_gpu_ptr; /* Convert TIMESTAMP_LO/HI of a newest dump into a CPU timestamp. */ ts_dump_raw = backend_csf->info->csf_if->time_convert_gpu_to_cpu( @@ -1170,17 +1393,53 @@ kbasep_hwcnt_backend_csf_append_block_states(struct kbase_hwcnt_backend_csf *bac { size_t i; - for (i = 0; i < backend_csf->phys_layout.block_cnt; i++) + for (i = 0; i < backend_csf->phys_layout.payload_block_cnt; i++) kbase_hwcnt_block_state_append(&backend_csf->to_user_block_states[i], block_state); } +static int kbasep_hwcnt_backend_csf_do_dump_enable(struct kbase_hwcnt_backend_csf *backend_csf, + const struct kbase_hwcnt_enable_map *enable_map) +{ + struct kbase_hwcnt_backend_csf_if_enable enable; + int err; + + if (!backend_csf || !enable_map || (enable_map->metadata != backend_csf->info->metadata) || + WARN_ON(!backend_csf->info->ring_buf)) + return -EINVAL; + + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); + WARN_ON(backend_csf->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ); + + if (!backend_csf->info->mcu_on) + return 0; + + err = backend_csf->info->watchdog_if->enable(backend_csf->info->watchdog_if->timer, + backend_csf->info->watchdog_timer_interval_ms, + kbasep_hwcnt_backend_watchdog_timer_cb, + backend_csf->info); + if (err) + return err; + + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK); + + kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map, &enable); + + backend_csf->info->csf_if->dump_enable(backend_csf->info->csf_if->ctx, + backend_csf->info->ring_buf, &enable); + kbasep_hwcnt_backend_csf_cc_initial_sample(backend_csf, enable_map); + + return 0; +} + /* CSF backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */ static int kbasep_hwcnt_backend_csf_dump_enable_nolock(struct kbase_hwcnt_backend *backend, const struct kbase_hwcnt_enable_map *enable_map) { struct kbase_hwcnt_backend_csf *backend_csf = (struct kbase_hwcnt_backend_csf *)backend; - struct kbase_hwcnt_backend_csf_if_enable enable; + int err; if (!backend_csf || !enable_map || (enable_map->metadata != backend_csf->info->metadata)) @@ -1200,28 +1459,35 @@ kbasep_hwcnt_backend_csf_dump_enable_nolock(struct kbase_hwcnt_backend *backend, */ kbasep_hwcnt_backend_csf_append_block_states(backend_csf, KBASE_HWCNT_STATE_OFF); - kbasep_hwcnt_backend_csf_get_physical_enable(backend_csf, enable_map, &enable); - - /* enable_state should be DISABLED before we transfer it to enabled */ - if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) + /* enable_state should be (or be transitioning to) DISABLED before we transfer it + * to enabled. In addition to that, there shouldn't be a concurrent dump worker flush during + * dump_disable() procedure (the lock is released then). + */ + if (backend_csf->flush_on_disable_in_progress || + (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED && + !kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(backend_csf->enable_state))) return -EIO; - err = backend_csf->info->watchdog_if->enable(backend_csf->info->watchdog_if->timer, - backend_csf->info->watchdog_timer_interval_ms, - kbasep_hwcnt_backend_watchdog_timer_cb, - backend_csf->info); - if (err) - return err; - backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; WARN_ON(!completion_done(&backend_csf->dump_completed)); + + /* Save the enable_map. It will be used e.g. when handling the deferred enable REQ + * or during cold_boot procedure. + */ + kbase_hwcnt_enable_map_copy(&backend_csf->last_enable_map, enable_map); + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED); + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ); - backend_csf->info->csf_if->dump_enable(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, &enable); - - kbasep_hwcnt_backend_csf_cc_initial_sample(backend_csf, enable_map); + /* If MCU is powered off, backend will stay in TRANSITIONING_TO_ENABLED_PENDING_REQ. + * Enable REQ will be sent during MCU ON notification. + */ + if (backend_csf->info->mcu_on) { + err = kbasep_hwcnt_backend_csf_do_dump_enable(backend_csf, + &backend_csf->last_enable_map); + if (err) + return err; + } return 0; } @@ -1243,25 +1509,60 @@ static int kbasep_hwcnt_backend_csf_dump_enable(struct kbase_hwcnt_backend *back return errcode; } -static void kbasep_hwcnt_backend_csf_wait_enable_transition_complete( - struct kbase_hwcnt_backend_csf *backend_csf, unsigned long *lock_flags) +static void +kbasep_hwcnt_backend_csf_wait_state_transition_complete(struct kbase_hwcnt_backend_csf *backend_csf, + unsigned long *lock_flags) { backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); - while ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) || - (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)) { + /* The wait loop ends when backend gets out of a transitioning state or MCU + * is powered off. + */ + while ((kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(backend_csf->enable_state) || + kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(backend_csf->enable_state)) && + backend_csf->info->mcu_on) { backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, *lock_flags); wait_event(backend_csf->enable_state_waitq, - (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) && - (backend_csf->enable_state != - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED)); + (!kbasep_hwcnt_backend_csf_is_state_trans_to_enabled( + backend_csf->enable_state) && + !kbasep_hwcnt_backend_csf_is_state_trans_to_disabled( + backend_csf->enable_state)) || + !backend_csf->info->mcu_on); backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, lock_flags); } } +static void kbasep_hwcnt_backend_csf_send_disable_req(struct kbase_hwcnt_backend_csf_info *csf_info) +{ + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + + /* Send the disable REQ and mark that we don't have any pending disable REQ. */ + csf_info->csf_if->dump_disable(csf_info->csf_if->ctx); + csf_info->pending_disable_req = false; +} + +static void +kbasep_hwcnt_backend_csf_resolve_wait_for_worker_state(struct kbase_hwcnt_backend_csf *backend_csf) +{ + backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); + + switch (backend_csf->enable_state) { + case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED); + break; + case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); + break; + default: + /* Do nothing */ + break; + } +} + /* CSF backend implementation of kbase_hwcnt_backend_dump_disable_fn */ static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *backend, struct kbase_hwcnt_dump_buffer *dump_buffer, @@ -1277,12 +1578,19 @@ static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *ba (dump_buffer && !enable_map))) return; + /* Cancel any pending reenable worker so we can disable the backend cleanly. */ + cancel_work_sync(&backend_csf->info->hwc_dump_reenable_work); + backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); /* Make sure we wait until any previous enable or disable have completed * before doing anything. + * + * Note: Backend might still be in a transitioning state after + * kbasep_hwcnt_backend_csf_wait_state_transition_complete() if MCU was + * powered off. */ - kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, &flags); + kbasep_hwcnt_backend_csf_wait_state_transition_complete(backend_csf, &flags); if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED || backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) { @@ -1293,27 +1601,36 @@ static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *ba return; } - if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) { + /* Send disable REQ if the backend was previously either enabled or was transitioning + * to enabled state but it was never REQed/ACKed due to MCU being powered off. + * + * In any other state the disable REQ have already been sent. + */ + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED || + kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(backend_csf->enable_state)) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ); backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; complete_all(&backend_csf->dump_completed); - /* Only disable if we were previously enabled - in all other - * cases the call to disable will have already been made. - */ do_disable = true; } WARN_ON(backend_csf->dump_state != KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE); WARN_ON(!completion_done(&backend_csf->dump_completed)); + /* Mark that we are going to flush the workers (hence we are releasing the lock). + * This is needed to prevent any potential concurrent attempts to enable the backend. + */ + backend_csf->flush_on_disable_in_progress = true; + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); /* Deregister the timer and block until any timer callback has completed. * We've transitioned out of the ENABLED state so we can guarantee it * won't reschedule itself. */ - backend_csf->info->watchdog_if->disable(backend_csf->info->watchdog_if->timer); + backend_csf->info->watchdog_if->disable(backend_csf->info->watchdog_if->timer, + KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_BLOCK); /* Block until any async work has completed. We have transitioned out of * the ENABLED state so we can guarantee no new work will concurrently @@ -1322,26 +1639,49 @@ static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *ba flush_workqueue(backend_csf->hwc_dump_workq); backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); + backend_csf->flush_on_disable_in_progress = false; - if (do_disable) - backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); - - kbasep_hwcnt_backend_csf_wait_enable_transition_complete(backend_csf, &flags); - - switch (backend_csf->enable_state) { - case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: - kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED); - break; - case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: - kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR); - break; - default: - WARN_ON(true); - break; + if (!backend_csf->info->mcu_on) { + /* Stay in TRANSITIONING_TO_DISABLED_PENDING_REQ state. + * Record that we wanted to disable HWC but the disable REQ hasn't reached MCU. + * We need to save this in a backend instance-independent structure, + * to be able to send the disable REQ at MCU ON notification even if the backend + * has been destroyed/recreated. + */ + backend_csf->info->pending_disable_req = true; + goto skip_disable_req; } + if (do_disable) { + /* Check if we have entered an error state while we released the lock. + * If yes, don't leave the error state. + */ + if (!kbasep_hwcnt_backend_csf_is_error_state(backend_csf->enable_state)) + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK); + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); + } + + if (!kbasep_hwcnt_backend_csf_is_error_state(backend_csf->enable_state)) + kbasep_hwcnt_backend_csf_wait_state_transition_complete(backend_csf, &flags); + + kbasep_hwcnt_backend_csf_resolve_wait_for_worker_state(backend_csf); + + /* At this point the correct states are : + * - KBASE_HWCNT_BACKEND_CSF_DISABLED + * - KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR + * - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK (only if MCU + * is powered off). + */ + + WARN_ON((backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) && + (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) && + ((backend_csf->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK) || + backend_csf->info->mcu_on)); + +skip_disable_req: backend_csf->user_requested = false; backend_csf->watchdog_last_seen_insert_idx = 0; @@ -1354,7 +1694,7 @@ static void kbasep_hwcnt_backend_csf_dump_disable(struct kbase_hwcnt_backend *ba /* Sync zeroed buffers to avoid coherency issues on future use. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, 0, + backend_csf->info->ring_buf, 0, backend_csf->info->ring_buf_cnt, false); /* Disabling HWCNT is an indication that blocks have been powered off. This is important to @@ -1408,12 +1748,19 @@ static int kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *bac return -EINVAL; backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); - - /* If we're transitioning to enabled there's nothing to accumulate, and + /* If we're transitioning to enabled, then there's nothing to accumulate, and * the user dump buffer is already zeroed. We can just short circuit to * the DUMP_COMPLETED state. + * + * We can also early exit in case of an ongoing reenable procedure + * (dump_reenable_in_progress). It means that we must have disabled the backend + * first so there is nothing to accumulate. */ - if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { + if (kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(backend_csf->enable_state) || + (backend_csf->dump_reenable_in_progress && + ((backend_csf->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK) || + (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED)))) { backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_COMPLETED; backend_csf->dump_time_ns = kbasep_hwcnt_backend_csf_timestamp_ns(backend); kbasep_hwcnt_backend_csf_cc_update(backend_csf); @@ -1421,12 +1768,11 @@ static int kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *bac * during multiple dumps, hence append the OFF state. */ kbasep_hwcnt_backend_csf_append_block_states(backend_csf, KBASE_HWCNT_STATE_OFF); - backend_csf->user_requested = true; + WARN_ON(!completion_done(&backend_csf->dump_completed)); backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return 0; } - /* Otherwise, make sure we're already enabled. */ if (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_ENABLED) { backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); @@ -1461,9 +1807,9 @@ static int kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *bac watchdog_dumping = true; if ((backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) && - !backend_csf->info->fw_in_protected_mode) { - /* Only do the request if we are fully enabled and not in - * protected mode. + !backend_csf->info->fw_in_protected_mode && backend_csf->info->mcu_on) { + /* Do the request only if the MCU is on, we are fully enabled + * and not in protected mode. */ backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_REQUESTED; do_request = true; @@ -1496,13 +1842,16 @@ static int kbasep_hwcnt_backend_csf_dump_request(struct kbase_hwcnt_backend *bac } else kbase_hwcnt_backend_csf_submit_dump_worker(backend_csf->info); - backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); - /* Modify watchdog timer to delay the regular check time since - * just requested. + * just requested (only if MCU is ON). */ - backend_csf->info->watchdog_if->modify(backend_csf->info->watchdog_if->timer, - backend_csf->info->watchdog_timer_interval_ms); + if (backend_csf->info->mcu_on) { + backend_csf->info->watchdog_if->modify( + backend_csf->info->watchdog_if->timer, + backend_csf->info->watchdog_timer_interval_ms); + } + + backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); return 0; } @@ -1613,8 +1962,7 @@ static void kbasep_hwcnt_backend_csf_destroy(struct kbase_hwcnt_backend_csf *bac destroy_workqueue(backend_csf->hwc_dump_workq); - backend_csf->info->csf_if->ring_buf_free(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf); + kbase_hwcnt_enable_map_free(&backend_csf->last_enable_map); kfree(backend_csf->accum_buf); backend_csf->accum_buf = NULL; @@ -1650,8 +1998,8 @@ static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info * int errcode = -ENOMEM; size_t block_state_bytes; - WARN_ON(!csf_info); - WARN_ON(!out_backend); + if (WARN_ON(!out_backend || !csf_info || !csf_info->ring_buf)) + return -EINVAL; backend_csf = kzalloc(sizeof(*backend_csf), GFP_KERNEL); if (!backend_csf) @@ -1674,8 +2022,8 @@ static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info * goto err_alloc_user_sample_buf; /* Allocate space to store block state values for each block */ - block_state_bytes = backend_csf->phys_layout.block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * - KBASE_HWCNT_BLOCK_STATE_STRIDE; + block_state_bytes = backend_csf->phys_layout.payload_block_cnt * + KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; backend_csf->block_states = kzalloc(block_state_bytes, GFP_KERNEL); if (!backend_csf->block_states) goto err_alloc_block_states_buf; @@ -1684,11 +2032,14 @@ static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info * if (!backend_csf->to_user_block_states) goto err_alloc_user_block_state_buf; - errcode = csf_info->csf_if->ring_buf_alloc(csf_info->csf_if->ctx, csf_info->ring_buf_cnt, - &backend_csf->ring_buf_cpu_base, - &backend_csf->ring_buf); + /* Allocate a local version of the enable_map to avoid a situation where the backend's + * caller frees the map when it's still required for the backend (e.g. enable_map + * being reapplied after MCU power on). + */ + errcode = kbase_hwcnt_enable_map_alloc(csf_info->metadata, &backend_csf->last_enable_map); if (errcode) - goto err_ring_buf_alloc; + goto err_alloc_last_enable_map; + errcode = -ENOMEM; /* Zero all performance enable header to prepare for first enable. */ @@ -1696,7 +2047,7 @@ static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info * /* Sync zeroed buffers to avoid coherency issues on use. */ backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf, 0, + backend_csf->info->ring_buf, 0, backend_csf->info->ring_buf_cnt, false); init_completion(&backend_csf->dump_completed); @@ -1724,9 +2075,8 @@ static int kbasep_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_info * return 0; err_alloc_workqueue: - backend_csf->info->csf_if->ring_buf_free(backend_csf->info->csf_if->ctx, - backend_csf->ring_buf); -err_ring_buf_alloc: + kbase_hwcnt_enable_map_free(&backend_csf->last_enable_map); +err_alloc_last_enable_map: kfree(backend_csf->to_user_block_states); backend_csf->to_user_block_states = NULL; err_alloc_user_block_state_buf: @@ -1747,6 +2097,85 @@ alloc_error: return errcode; } +enum kbasep_hwcnt_backend_ring_buf_free_type { + KBASEP_RING_BUF_FREE_NORMAL, + KBASEP_RING_BUF_FREE_DEFERRED, +}; + +static inline void +kbasep_hwcnt_backend_csf_ring_buf_free_deferred(struct kbase_hwcnt_backend_csf_info *csf_info) +{ + if (WARN_ON(!csf_info)) + return; + + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + + csf_info->ring_buf_cleanup = csf_info->ring_buf; + queue_work(csf_info->hwc_deferred_op_workq, &csf_info->hwc_ring_buf_free_work); + csf_info->ring_buf = NULL; +} + +static inline void kbasep_hwcnt_backend_csf_ring_buf_refcnt_increment_nolock( + struct kbase_hwcnt_backend_csf_info *csf_info) +{ + if (WARN_ON(!csf_info)) + return; + + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + + csf_info->ring_buf_refcnt.val++; + WARN_ON(csf_info->ring_buf_refcnt.val > RING_BUF_REFCNT_MAX); +} + +static void kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement_nolock( + struct kbase_hwcnt_backend_csf_info *csf_info, unsigned long *lock_flags, + enum kbasep_hwcnt_backend_ring_buf_free_type type) +{ + if (WARN_ON(!csf_info)) + return; + + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + + csf_info->ring_buf_refcnt.val--; + WARN_ON(csf_info->ring_buf_refcnt.val < RING_BUF_REFCNT_MIN); + + if (!csf_info->ring_buf_refcnt.val) { + struct kbase_hwcnt_backend_csf_if_ring_buf *tmp_ring_buf = csf_info->ring_buf; + + WARN_ON(!csf_info->ring_buf); + + switch (type) { + case KBASEP_RING_BUF_FREE_NORMAL: + if (WARN_ON(!lock_flags)) + break; + csf_info->ring_buf = NULL; + csf_info->csf_if->unlock(csf_info->csf_if->ctx, *lock_flags); + csf_info->csf_if->ring_buf_free(csf_info->csf_if->ctx, tmp_ring_buf); + csf_info->csf_if->lock(csf_info->csf_if->ctx, lock_flags); + break; + case KBASEP_RING_BUF_FREE_DEFERRED: + kbasep_hwcnt_backend_csf_ring_buf_free_deferred(csf_info); + break; + default: + break; + } + } +} + +static void kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement( + struct kbase_hwcnt_backend_csf_info *csf_info, + enum kbasep_hwcnt_backend_ring_buf_free_type type) +{ + unsigned long flags = 0UL; + + if (WARN_ON(!csf_info)) + return; + + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement_nolock(csf_info, &flags, type); + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + /* CSF backend implementation of kbase_hwcnt_backend_init_fn */ static int kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info *info, struct kbase_hwcnt_backend **out_backend) @@ -1760,10 +2189,35 @@ static int kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info * if (!info || !out_backend) return -EINVAL; + /* Ring buffer allocation. */ + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + kbasep_hwcnt_backend_csf_ring_buf_refcnt_increment_nolock(csf_info); + if (csf_info->ring_buf_refcnt.val == 1) { + WARN_ON(csf_info->ring_buf); + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); + + /* Flush any pending ring_buf_free_worker before allocating a new ring buffer. */ + flush_workqueue(csf_info->hwc_deferred_op_workq); + + errcode = csf_info->csf_if->ring_buf_alloc(csf_info->csf_if->ctx, + csf_info->ring_buf_cnt, + &csf_info->ring_buf_cpu_base, + &csf_info->ring_buf); + if (errcode) { + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement( + csf_info, KBASEP_RING_BUF_FREE_NORMAL); + return errcode; + } + } else + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); + /* Create the backend. */ errcode = kbasep_hwcnt_backend_csf_create(csf_info, &backend_csf); - if (errcode) + if (errcode) { + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement(csf_info, + KBASEP_RING_BUF_FREE_NORMAL); return errcode; + } /* If it was not created before, attach it to csf_info. * Use spin lock to avoid concurrent initialization. @@ -1783,6 +2237,8 @@ static int kbasep_hwcnt_backend_csf_init(const struct kbase_hwcnt_backend_info * * function properly. */ if (!success) { + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement(backend_csf->info, + KBASEP_RING_BUF_FREE_NORMAL); kbasep_hwcnt_backend_csf_destroy(backend_csf); return -EBUSY; } @@ -1806,6 +2262,8 @@ static void kbasep_hwcnt_backend_csf_term(struct kbase_hwcnt_backend *backend) */ backend_csf->info->csf_if->lock(backend_csf->info->csf_if->ctx, &flags); backend_csf->info->backend = NULL; + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement_nolock(backend_csf->info, &flags, + KBASEP_RING_BUF_FREE_NORMAL); backend_csf->info->csf_if->unlock(backend_csf->info->csf_if->ctx, flags); kbasep_hwcnt_backend_csf_destroy(backend_csf); @@ -1827,6 +2285,141 @@ static void kbasep_hwcnt_backend_csf_release(const struct kbase_hwcnt_backend *b csf_info->csf_if->release(csf_info->csf_if->ctx); } +static inline bool +kbasep_hwcnt_backend_csf_abort_dump_reenable(struct kbase_hwcnt_backend_csf_info *csf_info) +{ + if (WARN_ON(!csf_info)) + return true; + + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + /* Check if the dump reenabling is still valid. + * + * dump_reenable_in_progress can be set to false by a cold_boot procedure, + * which is a signal to abort the reenable work. + */ + return (!kbasep_hwcnt_backend_csf_backend_exists(csf_info) || + !csf_info->backend->dump_reenable_in_progress || + (csf_info->backend->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK && + csf_info->backend->enable_state != + KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER && + csf_info->backend->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED)); +} + +/** + * kbasep_hwcnt_backend_csf_dump_reenable_worker() - HWC backend reenable worker. + * + * @work: Work structure. + * + * Called when a HWC backend needs a disable-enable cycle, e.g. when we want to enable the backend, + * but the previous disable hasn't been performed due to MCU being powered off. + * + * This procedure assumes that the disable REQ has been already sent in the atomic context, + * and this worker waits for the disable ACK, and later sends an enable REQ. + */ +static void kbasep_hwcnt_backend_csf_dump_reenable_worker(struct work_struct *work) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + unsigned long flags = 0ULL; + int err; + + WARN_ON(!work); + + csf_info = container_of(work, struct kbase_hwcnt_backend_csf_info, hwc_dump_reenable_work); + + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + /* Check if the re-enabling is still valid. + * + * The thread that enqueued this worker has already sent the disable REQ, so we either wait + * for the disable ACK, or it was already ACKed. Any other state (or a destroyed backend) + * means that the re-enabling should be aborted. + */ + if (kbasep_hwcnt_backend_csf_abort_dump_reenable(csf_info)) + goto exit; + + /* Wait for the disable ACK. */ + kbasep_hwcnt_backend_csf_wait_state_transition_complete(csf_info->backend, &flags); + + /* kbasep_hwcnt_backend_csf_wait_state_transition_complete releases the lock, so we need to + * recheck if reenabling is still valid. + */ + if (kbasep_hwcnt_backend_csf_abort_dump_reenable(csf_info)) + goto exit; + + /* We are re-enabling the backend, so we must have already waited for the workers + * to complete while disabling the backend. It is safe to transition out of + * *_WAIT_FOR_WORKER states. + */ + kbasep_hwcnt_backend_csf_resolve_wait_for_worker_state(csf_info->backend); + + if (csf_info->backend->enable_state == KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR) + goto exit; + + /* The disabling part of the worker has concluded. + * + * Note that it is fine to be in TRANSITIONING_TO_DISABLED_PENDING_ACK at this point. + * It means that we have already sent disable REQ while the MCU was on, but the MCU + * was powered off while kbasep_hwcnt_backend_csf_wait_state_transition_complete was called + * previously. + * + * We can proceed with the re-enabling procedure because: + * - the pending disable will be ACKed at the following MCU power on, + * - enable REQ will be sent at the next MCU power on, because this reenable worker + * will set the TRANSITIONING_TO_ENABLED_PENDING_REQ state. + */ + WARN_ON(!(csf_info->backend->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED || + csf_info->backend->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK)); + + /* Proceed to enabling part of the worker. */ + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + csf_info->backend, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ); + + /* If MCU is powered off, backend will stay in TRANSITIONING_TO_ENABLED_PENDING_REQ. + * Enable REQ will be sent during MCU ON notification. + */ + if (csf_info->mcu_on) { + err = kbasep_hwcnt_backend_csf_do_dump_enable(csf_info->backend, + &csf_info->backend->last_enable_map); + if (err) + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(csf_info->backend); + } + +exit: + if (kbasep_hwcnt_backend_csf_backend_exists(csf_info)) + csf_info->backend->dump_reenable_in_progress = false; + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + +/** + * kbasep_hwcnt_backend_csf_ring_buf_free_worker() - Ring buffer freeing worker. + * + * @work: Work structure. + * + * Called when a ring buffer needs to be freed. + */ +static void kbasep_hwcnt_backend_csf_ring_buf_free_worker(struct work_struct *work) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + struct kbase_hwcnt_backend_csf_if_ring_buf *ring_buf; + unsigned long flags = 0UL; + + WARN_ON(!work); + + csf_info = container_of(work, struct kbase_hwcnt_backend_csf_info, hwc_ring_buf_free_work); + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + + if (WARN_ON(!csf_info->ring_buf_cleanup)) { + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); + return; + } + ring_buf = csf_info->ring_buf_cleanup; + csf_info->ring_buf_cleanup = NULL; + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); + + csf_info->csf_if->ring_buf_free(csf_info->csf_if->ctx, ring_buf); +} + /** * kbasep_hwcnt_backend_csf_info_destroy() - Destroy a CSF backend info. * @info: Pointer to info to destroy. @@ -1839,12 +2432,18 @@ static void kbasep_hwcnt_backend_csf_info_destroy(const struct kbase_hwcnt_backe if (!info) return; + destroy_workqueue(info->hwc_deferred_op_workq); + /* The backend should be destroyed before the info object destroy. */ WARN_ON(info->backend != NULL); /* The metadata should be destroyed before the info object destroy. */ WARN_ON(info->metadata != NULL); + /* Ring buffer should be freed either during backend destruction or device termination.*/ + WARN_ON(info->ring_buf != NULL); + WARN_ON(info->ring_buf_cleanup != NULL); + kfree(info); } @@ -1892,7 +2491,19 @@ kbasep_hwcnt_backend_csf_info_create(struct kbase_hwcnt_backend_csf_if *csf_if, .fw_in_protected_mode = false, .unrecoverable_error_happened = false, .watchdog_if = watchdog_if, .watchdog_timer_interval_ms = watchdog_timer_interval_ms, + .last_transition = SAMPLE_REASON_NONE, .mcu_on = false, }; + + info->hwc_deferred_op_workq = + alloc_workqueue("mali_hwc_deferred_op_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!info->hwc_deferred_op_workq) { + kfree(info); + return -ENOMEM; + } + + INIT_WORK(&info->hwc_dump_reenable_work, kbasep_hwcnt_backend_csf_dump_reenable_worker); + INIT_WORK(&info->hwc_ring_buf_free_work, kbasep_hwcnt_backend_csf_ring_buf_free_worker); + *out_info = info; return 0; @@ -1913,10 +2524,13 @@ kbasep_hwcnt_backend_csf_metadata(const struct kbase_hwcnt_backend_info *info) static void kbasep_hwcnt_backend_csf_handle_unrecoverable_error(struct kbase_hwcnt_backend_csf *backend_csf) { - bool do_disable = false; + bool send_disable_req = false; backend_csf->info->csf_if->assert_lock_held(backend_csf->info->csf_if->ctx); + /* Cancel any pending backend reenabling procedure. */ + backend_csf->dump_reenable_in_progress = false; + /* We are already in or transitioning to the unrecoverable error state. * Early out. */ @@ -1934,12 +2548,12 @@ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(struct kbase_hwcnt_backend_c return; } - /* Trigger a disable only if we are not already transitioning to - * disabled, we don't want to disable twice if an unrecoverable error + /* Send a disable REQ only if we are not already transitioning to + * disabled. We don't want to send disable REQ twice if an unrecoverable error * happens while we are disabling. */ - do_disable = - (backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); + send_disable_req = + !kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(backend_csf->enable_state); kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( backend_csf, KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER); @@ -1950,12 +2564,8 @@ kbasep_hwcnt_backend_csf_handle_unrecoverable_error(struct kbase_hwcnt_backend_c backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; complete_all(&backend_csf->dump_completed); - /* Trigger a disable only if we are not already transitioning to - * disabled, - we don't want to disable twice if an unrecoverable error - * happens while we are disabling. - */ - if (do_disable) - backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); + if (send_disable_req) + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); } static void @@ -1966,14 +2576,16 @@ kbasep_hwcnt_backend_csf_handle_recoverable_error(struct kbase_hwcnt_backend_csf switch (backend_csf->enable_state) { case KBASE_HWCNT_BACKEND_CSF_DISABLED: case KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER: - case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK: case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR: case KBASE_HWCNT_BACKEND_CSF_UNRECOVERABLE_ERROR_WAIT_FOR_WORKER: /* Already disabled or disabling, or in an unrecoverable error. * Nothing to be done to handle the error. */ return; - case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ: + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK: /* A seemingly recoverable error that occurs while we are * transitioning to enabled is probably unrecoverable. */ @@ -1986,14 +2598,15 @@ kbasep_hwcnt_backend_csf_handle_recoverable_error(struct kbase_hwcnt_backend_csf * disable(). */ kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED); - /* Transition the dump to the IDLE state and unblock any - * waiters. The IDLE state signifies an error. + backend_csf, KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK); + /* Transition the dump to the IDLE state and unblock any waiters. The IDLE state + * signifies an error. Mark that dump workers need to be flushed. */ + backend_csf->flush_workers_needed = true; backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; complete_all(&backend_csf->dump_completed); - backend_csf->info->csf_if->dump_disable(backend_csf->info->csf_if->ctx); + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); return; } } @@ -2015,7 +2628,6 @@ void kbase_hwcnt_backend_csf_protm_entered(struct kbase_hwcnt_backend_interface void kbase_hwcnt_backend_csf_protm_exited(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; - csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); @@ -2057,6 +2669,7 @@ void kbase_hwcnt_backend_csf_on_before_reset(struct kbase_hwcnt_backend_interfac csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); return; } + backend_csf = csf_info->backend; if ((backend_csf->enable_state != KBASE_HWCNT_BACKEND_CSF_DISABLED) && @@ -2164,15 +2777,22 @@ void kbase_hwcnt_backend_csf_on_prfcnt_enable(struct kbase_hwcnt_backend_interfa /* Early out if the backend does not exist. */ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) return; + backend_csf = csf_info->backend; - if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED) { + if (backend_csf->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK) { kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( backend_csf, KBASE_HWCNT_BACKEND_CSF_ENABLED); } else if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED) { /* Unexpected, but we are already in the right state so just * ignore it. */ + } else if (kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(backend_csf->enable_state)) { + /* We might already be in the TRANSITION_TO_DISABLED_* states and + * the MCU is handling outstanding ACKs due to MCU power cycle, + * so just ignore it. + */ } else { /* Unexpected state change, assume everything is broken until * we reset. @@ -2189,17 +2809,45 @@ void kbase_hwcnt_backend_csf_on_prfcnt_disable(struct kbase_hwcnt_backend_interf csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + /* We received a disable ACK, so we can decrement the ring buffer refcounter. */ + if (csf_info->ring_buf_refcnt.incremented_on_mcu_off) { + csf_info->ring_buf_refcnt.incremented_on_mcu_off = false; + kbasep_hwcnt_backend_csf_ring_buf_refcnt_decrement_nolock( + csf_info, NULL, KBASEP_RING_BUF_FREE_DEFERRED); + } + /* Early out if the backend does not exist. */ if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) return; + backend_csf = csf_info->backend; - if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED) { - kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( - backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER); + if (backend_csf->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK) { + /* If the disable REQ was deferred due to MCU being off, we have already waited + * for the workers to complete. Hence it's safe to transition directly to + * DISABLED state. + * + * In any other case + * (e.g. KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK + * was set due to an recoverable error), we need to wait for workers to be flushed + * at the next dump_disable() call. + */ + enum kbase_hwcnt_backend_csf_enable_state new_state = + backend_csf->flush_workers_needed ? + KBASE_HWCNT_BACKEND_CSF_DISABLED_WAIT_FOR_WORKER : + KBASE_HWCNT_BACKEND_CSF_DISABLED; + backend_csf->flush_workers_needed = false; + + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters(backend_csf, new_state); + } else if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_DISABLED) { - /* Unexpected, but we are already in the right state so just - * ignore it. + /* This might be expected if we are aligning the backend state with MCU state. + * We are already in the right state so just ignore it. + */ + } else if (kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(backend_csf->enable_state)) { + /* We might already be in the TRANSITION_TO_ENABLED_* states and the MCU is handling + * outstanding ACKs due to MCU power cycle, so just ignore it. */ } else { /* Unexpected state change, assume everything is broken until @@ -2209,6 +2857,272 @@ void kbase_hwcnt_backend_csf_on_prfcnt_disable(struct kbase_hwcnt_backend_interf } } +static void +kbasep_hwcnt_backend_csf_on_after_mcu_off_nolock(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + struct kbase_hwcnt_backend_csf *backend_csf; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + + csf_info->csf_if->assert_lock_held(csf_info->csf_if->ctx); + + WARN_ON(!csf_info->mcu_on); + csf_info->mcu_on = false; + /* Early out if the backend does not exist. */ + if (!kbasep_hwcnt_backend_csf_backend_exists(csf_info)) + return; + + backend_csf = csf_info->backend; + + /* Notify about the MCU OFF event. */ + wake_up(&backend_csf->enable_state_waitq); + + /* Ring buffer refcount makes sure the ring buffer is only freed when FW has ACKed + * any outstanding HWC disable REQs. This means that the refcount should be incremented + * on MCU_OFF event when the backend is enabled (or about to be enabled) from + * FW perspective, i.e. states: + * - KBASE_HWCNT_BACKEND_CSF_ENABLED, + * - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_*, because the disable + * is not yet ACKed, + * - KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK, to prevent + * a race condition between enable ACK IRQ and the ring buffer freeing + * after MCU ON notification. + * + * It's safe to free the ring buffer (i.e. to not increase the refcount) while MCU is OFF + * if the backend disable has been ACKed by FW or the enabling REQ never reached FW + * (e.g. KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ). + * + * Do not increase the refcnt again if FW still hasn't ACKed the backend disable since + * the last MCU power cycle. + */ + if (!backend_csf->info->ring_buf_refcnt.incremented_on_mcu_off && + (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED || + kbasep_hwcnt_backend_csf_is_state_trans_to_disabled(backend_csf->enable_state) || + backend_csf->enable_state == + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK)) { + kbasep_hwcnt_backend_csf_ring_buf_refcnt_increment_nolock(csf_info); + backend_csf->info->ring_buf_refcnt.incremented_on_mcu_off = true; + } + + kbasep_hwcnt_backend_csf_append_block_states(backend_csf, KBASE_HWCNT_STATE_OFF); + + /* ACK the sample */ + kbase_hwcnt_backend_csf_on_prfcnt_sample(iface); +} + +void kbase_hwcnt_backend_csf_on_after_mcu_off(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + unsigned long flags = 0UL; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + kbasep_hwcnt_backend_csf_on_after_mcu_off_nolock(iface); + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + +void kbase_hwcnt_backend_csf_on_after_mcu_off_reset(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + unsigned long flags = 0UL; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + + /* It's uncertain at which MCU state reset was called. + * Hence, only notify the backend about MCU_OFF if it hasn't been done yet. + */ + if (csf_info->mcu_on) + kbasep_hwcnt_backend_csf_on_after_mcu_off_nolock(iface); + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + +void kbase_hwcnt_backend_csf_on_after_mcu_on(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + struct kbase_hwcnt_backend_csf *backend_csf; + const enum kbase_hwcnt_backend_csf_enable_state trans_to_disabled_pending_ack = + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK; + + unsigned long flags = 0UL; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + + WARN_ON(csf_info->mcu_on); + csf_info->mcu_on = true; + + if (kbasep_hwcnt_backend_csf_backend_exists(csf_info)) { + backend_csf = (struct kbase_hwcnt_backend_csf *)csf_info->backend; + + kbasep_hwcnt_backend_csf_append_block_states(backend_csf, KBASE_HWCNT_STATE_ON); + + switch (backend_csf->enable_state) { + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ: + /* pending_disable_req means that prior to enabling, we need to disable + * the backend first. + */ + if (backend_csf->info->pending_disable_req) { + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, trans_to_disabled_pending_ack); + /* Send the disable REQ now. */ + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); + + backend_csf->dump_reenable_in_progress = true; + /* Queue a worker to wait for disable ACK and to send enable REQ. */ + queue_work(backend_csf->info->hwc_deferred_op_workq, + &backend_csf->info->hwc_dump_reenable_work); + /* Exit the backend state handling. */ + break; + } + + /* At this point we are sure that the previous disable was ACKed by FW, + * so we can proceed directly to the enable REQ. + */ + if (kbasep_hwcnt_backend_csf_do_dump_enable(backend_csf, + &backend_csf->last_enable_map)) + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(backend_csf); + break; + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_ACK: + case KBASE_HWCNT_BACKEND_CSF_ENABLED: + /* Resume the timer. */ + csf_info->watchdog_if->modify(csf_info->watchdog_if->timer, + csf_info->watchdog_timer_interval_ms); + break; + case KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_REQ: + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_DISABLED_PENDING_ACK); + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); + + break; + case KBASE_HWCNT_BACKEND_CSF_DISABLED: + /* Here we handle a case where the backend was recreated (but not yet + * desired to be enabled) while MCU was off. If the disable REQ + * never reached MCU, we need to apply it now to align the HWC state + * in MCU and in the kbase. + * The disable ACK should be ignored. + */ + if (backend_csf->info->pending_disable_req) + kbasep_hwcnt_backend_csf_send_disable_req(backend_csf->info); + + break; + default: + /* Do nothing. */ + break; + } + + /* Notify about the MCU ON event. */ + wake_up(&backend_csf->enable_state_waitq); + + } else { + /* Backend has been already destroyed. */ + if (csf_info->pending_disable_req) { + /* Finish the backend destruction by sending the disable REQ to FW. */ + kbasep_hwcnt_backend_csf_send_disable_req(csf_info); + } + } + + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + +void kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + struct kbase_hwcnt_backend_csf *backend_csf; + unsigned long flags = 0UL; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + csf_info->csf_if->lock(csf_info->csf_if->ctx, &flags); + + WARN_ON(csf_info->mcu_on); + + /* Reset the internal variables to match the cold-booted FW state.*/ + csf_info->pending_disable_req = false; + + if (kbasep_hwcnt_backend_csf_backend_exists(csf_info)) { + bool do_reenable = false; + + backend_csf = (struct kbase_hwcnt_backend_csf *)csf_info->backend; + + if (backend_csf->enable_state == KBASE_HWCNT_BACKEND_CSF_ENABLED || + kbasep_hwcnt_backend_csf_is_state_trans_to_enabled(backend_csf->enable_state)) { + /* If the backend was enabled (or was transitioning to) prior to the + * cold boot, we need to reenable it so it can continue to process + * dump requests after the boot. + */ + do_reenable = true; + + /* Disable watchdog in a non-blocking manner. Pending watchdog callback will + * safely early-exit when called. + * + * Exclude TRANSITIONING_TO_ENABLED_PENDING_REQ state because watchdog + * is disabled in this state. + */ + if (backend_csf->enable_state != + KBASE_HWCNT_BACKEND_CSF_TRANSITIONING_TO_ENABLED_PENDING_REQ) + backend_csf->info->watchdog_if->disable( + backend_csf->info->watchdog_if->timer, + KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_NOT_BLOCK); + } + + backend_csf->flush_workers_needed = false; + /* Cancel any reenable work in progress. */ + backend_csf->dump_reenable_in_progress = false; + /* Set backend state to DISABLED and cancel any pending dump work + * by resetting dump-related variables. + * + * Do not leave an error state. A dump_disable and a subsequent reset is the only + * way to leave the error state. + */ + if (!kbasep_hwcnt_backend_csf_is_error_state(backend_csf->enable_state)) { + kbasep_hwcnt_backend_csf_change_es_and_wake_waiters( + backend_csf, KBASE_HWCNT_BACKEND_CSF_DISABLED); + backend_csf->dump_state = KBASE_HWCNT_BACKEND_CSF_DUMP_IDLE; + complete_all(&backend_csf->dump_completed); + } + + if (WARN_ON(backend_csf->info->ring_buf == NULL)) + goto unlock; + + /* Keep using the allocated ring buffer. Reset its refcount to 1. */ + csf_info->ring_buf_refcnt = (struct kbasep_hwcnt_ring_buf_refcnt){ .val = 1 }; + /* Zero all performance enable header to prepare for first enable + * after a cold boot. + */ + kbasep_hwcnt_backend_csf_zero_all_prfcnt_en_header(backend_csf); + /* Sync zeroed buffers to avoid coherency issues on future use. */ + backend_csf->info->csf_if->ring_buf_sync(backend_csf->info->csf_if->ctx, + backend_csf->info->ring_buf, 0, + backend_csf->info->ring_buf_cnt, false); + + if (do_reenable) { + int errcode; + + errcode = kbasep_hwcnt_backend_csf_dump_enable_nolock( + (struct kbase_hwcnt_backend *)backend_csf, + &backend_csf->last_enable_map); + if (errcode) { + kbasep_hwcnt_backend_csf_handle_unrecoverable_error(backend_csf); + goto unlock; + } + } + } else { + csf_info->ring_buf_refcnt = (struct kbasep_hwcnt_ring_buf_refcnt){ 0 }; + if (csf_info->ring_buf) { + /* It's safe to ignore ring buffer's refcounter because HWC is disabled + * during the cold boot. + */ + kbasep_hwcnt_backend_csf_ring_buf_free_deferred(csf_info); + } + } + +unlock: + csf_info->csf_if->unlock(csf_info->csf_if->ctx, flags); +} + int kbase_hwcnt_backend_csf_metadata_init(struct kbase_hwcnt_backend_interface *iface) { struct kbase_hwcnt_backend_csf_info *csf_info; @@ -2268,6 +3182,29 @@ void kbase_hwcnt_backend_csf_metadata_term(struct kbase_hwcnt_backend_interface } } +void kbase_hwcnt_backend_csf_ring_buf_term(struct kbase_hwcnt_backend_interface *iface) +{ + struct kbase_hwcnt_backend_csf_info *csf_info; + + if (!iface) + return; + + csf_info = (struct kbase_hwcnt_backend_csf_info *)iface->info; + + /* Wait for any ring_buf_free worker to finish. */ + flush_workqueue(csf_info->hwc_deferred_op_workq); + + /* Free ring buffer, if not yet freed. + * It's safe to ignore ring buffer's refcounter because firmware is being terminated, + * hence MCU will not be booted again. + * Needs to be done before firmware is terminated. + */ + if (csf_info->ring_buf != NULL) { + csf_info->csf_if->ring_buf_free(csf_info->csf_if->ctx, csf_info->ring_buf); + csf_info->ring_buf = NULL; + } +} + int kbase_hwcnt_backend_csf_create(struct kbase_hwcnt_backend_csf_if *csf_if, u32 ring_buf_cnt, struct kbase_hwcnt_watchdog_interface *watchdog_if, struct kbase_hwcnt_backend_interface *iface, diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h index 171b28deb6bc..5e3b96fa3d61 100644 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h +++ b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf.h @@ -31,10 +31,35 @@ #include "hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h" #include "hwcnt/mali_kbase_hwcnt_watchdog_if.h" #include "hwcnt/mali_kbase_hwcnt_types.h" +#include struct kbase_hwcnt_physical_enable_map; struct kbase_hwcnt_backend_csf; +/** + * enum kbase_hwcnt_backend_sample_reason - HWC CSF metadata block sample + * reasons. + * + * @SAMPLE_REASON_NONE: No metadata was enabled or available. + * @SAMPLE_REASON_BEFORE_PROTM: The sample was taken just before the GPU enters protected mode. + * @SAMPLE_REASON_BEFORE_HALT: The sample was taken just before the GPU enters the HALT state. + * @SAMPLE_REASON_BEFORE_SLEEP: The sample was taken just before the GPU enters the SLEEP state. + * @SAMPLE_REASON_BEFORE_SUSPEND: The sample was taken just before the GPU enters the SUSPEND + * state. + * @SAMPLE_REASON_BEFORE_YIELD: The sample was taken just before GPU subinstance yields the + * access window. + * @SAMPLE_REASON_AFTER_WARM_BOOT: The sample taken after GPU subinstance completed a warm boot. + */ +enum kbase_hwcnt_backend_sample_reason { + SAMPLE_REASON_NONE, + SAMPLE_REASON_BEFORE_PROTM, + SAMPLE_REASON_BEFORE_HALT, + SAMPLE_REASON_BEFORE_SLEEP, + SAMPLE_REASON_BEFORE_SUSPEND, + SAMPLE_REASON_BEFORE_YIELD, + SAMPLE_REASON_AFTER_WARM_BOOT +}; + /** * kbase_hwcnt_backend_csf_create() - Create a CSF hardware counter backend * interface, with set timer interval. @@ -72,6 +97,18 @@ int kbase_hwcnt_backend_csf_metadata_init(struct kbase_hwcnt_backend_interface * */ void kbase_hwcnt_backend_csf_metadata_term(struct kbase_hwcnt_backend_interface *iface); +/** + * kbase_hwcnt_backend_csf_ring_buf_term() - Terminate the ring buffers for a CSF + * hardware counter backend. Must be called while + * FW is still loaded. + * + * @iface: Non-NULL pointer to backend interface structure. + * + * If the ring buffer was not freed while HWC backend was present + * (e.g. due to MCU being powered off), this function will free it. + */ +void kbase_hwcnt_backend_csf_ring_buf_term(struct kbase_hwcnt_backend_interface *iface); + /** * kbase_hwcnt_backend_csf_destroy() - Destroy a CSF hardware counter backend * interface. @@ -123,8 +160,8 @@ void kbase_hwcnt_backend_csf_on_before_reset(struct kbase_hwcnt_backend_interfac /** * kbase_hwcnt_backend_csf_set_hw_availability() - CSF HWC backend function to * set current HW configuration. - * HWC must be disabled before - * this function is called. + * Can only be called when the MCU is off. + * * @iface: Non-NULL pointer to HWC backend interface. * @num_l2_slices: Current number of L2 slices allocated to the GPU. * @shader_present: Shader_present of the current configuration. @@ -179,21 +216,61 @@ void kbase_hwcnt_backend_csf_on_prfcnt_enable(struct kbase_hwcnt_backend_interfa */ void kbase_hwcnt_backend_csf_on_prfcnt_disable(struct kbase_hwcnt_backend_interface *iface); +/** + * kbase_hwcnt_backend_csf_on_after_mcu_off() - CSF HWC backend function to be called immediately + * after the MCU shut down process is completed, + * informing the backend that it is no longer valid + * to send commands to the MCU and that any + * outstanding commands will not be ACKed. + * @iface: Non-NULL pointer to HWC backend interface. + */ +void kbase_hwcnt_backend_csf_on_after_mcu_off(struct kbase_hwcnt_backend_interface *iface); + +/** + * kbase_hwcnt_backend_csf_on_after_mcu_off_reset() - Similar to + * kbase_hwcnt_backend_csf_on_after_mcu_off(). + * To be called only after a completed reset. + * This function will notify backend about MCU + * being powered off only if it hasn't been + * done yet. This is due to the fact that it's + * uncertain if the MCU_OFF notification was + * raised prior to the reset. + * @iface: Non-NULL pointer to HWC backend interface. + */ +void kbase_hwcnt_backend_csf_on_after_mcu_off_reset(struct kbase_hwcnt_backend_interface *iface); + +/** + * kbase_hwcnt_backend_csf_on_after_mcu_on() - CSF HWC backend function to be called immediately + * after the MCU has booted, informing the backend + * that it is now valid to send commands to the MCU. + * @iface: Non-NULL pointer to HWC backend interface. + */ +void kbase_hwcnt_backend_csf_on_after_mcu_on(struct kbase_hwcnt_backend_interface *iface); + +/** + * kbase_hwcnt_backend_csf_on_before_mcu_cold_boot() - CSF HWC backend function to be called + * immediately before a cold MCU boot, + * allowing the backend to reset its internal + * state machine to match the cold-booted + * FW state. + * @iface: Non-NULL pointer to HWC backend interface. + */ +void kbase_hwcnt_backend_csf_on_before_mcu_cold_boot(struct kbase_hwcnt_backend_interface *iface); + /** * kbasep_hwcnt_backend_csf_update_block_state - Update block state of a block instance with * information from a sample. * @backend: CSF hardware counter backend. * @enable_mask: Counter enable mask for the block whose state is being updated. - * @exiting_protm: Whether or not the sample is taken when the GPU is exiting - * protected mode. - * @block_idx: Index of block within the ringbuffer. + * @block_idx: Index of the block in the dump. * @block_state: Pointer to existing block state of the block whose state is being * updated. - * @fw_in_protected_mode: Whether or not GPU is in protected mode during sampling. + * @prev_sample_reason: The previous sample reason + * @curr_sample_reason: The current sample reason */ -void kbasep_hwcnt_backend_csf_update_block_state(struct kbase_hwcnt_backend_csf *backend, - const u32 enable_mask, bool exiting_protm, - size_t block_idx, blk_stt_t *const block_state, - bool fw_in_protected_mode); +void kbasep_hwcnt_backend_csf_update_block_state( + struct kbase_hwcnt_backend_csf *backend, const u32 enable_mask, size_t block_idx, + blk_stt_t *const block_state, enum kbase_hwcnt_backend_sample_reason prev_sample_reason, + enum kbase_hwcnt_backend_sample_reason curr_sample_reason); #endif /* _KBASE_HWCNT_BACKEND_CSF_H_ */ diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h index 220a63de779a..f8ba2acb4b67 100644 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h +++ b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if.h @@ -61,15 +61,16 @@ struct kbase_hwcnt_backend_csf_if_enable { /** * struct kbase_hwcnt_backend_csf_if_prfcnt_info - Performance counter * information. - * @prfcnt_hw_size: Total length in bytes of all the hardware counters data. The hardware - * counters are sub-divided into 4 classes: front-end, shader, tiler, and - * memory system (l2 cache + MMU). - * @prfcnt_fw_size: Total length in bytes of all the firmware counters data. - * @dump_bytes: Bytes of GPU memory required to perform a performance - * counter dump. dump_bytes = prfcnt_hw_size + prfcnt_fw_size. - * @prfcnt_block_size: Bytes of each performance counter block. - * @l2_count: The MMU L2 cache count. - * @csg_count: The total number of CSGs in the system + * @prfcnt_hw_size: Total length in bytes of all the hardware counters data. The hardware + * counters are sub-divided into 4 classes: front-end, shader, tiler, and + * memory system (l2 cache + MMU). + * @prfcnt_fw_size: Total length in bytes of all the firmware counters data. + * @metadata_size: Total length in bytes of the dedicated metadata block. + * @dump_bytes: Bytes of GPU memory required to perform a performance counter dump. + * dump_bytes = prfcnt_metadata_size + prfcnt_hw_size + prfcnt_fw_size. + * @prfcnt_block_size: Bytes of each performance counter block. + * @l2_count: The MMU L2 cache count. + * @csg_count: The total number of CSGs in the system * @sc_core_mask: Shader core mask. * @clk_cnt: Clock domain count in the system. * @clearing_samples: Indicates whether counters are cleared after each sample @@ -81,6 +82,7 @@ struct kbase_hwcnt_backend_csf_if_enable { struct kbase_hwcnt_backend_csf_if_prfcnt_info { size_t prfcnt_hw_size; size_t prfcnt_fw_size; + size_t metadata_size; size_t dump_bytes; size_t prfcnt_block_size; size_t l2_count; diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c index 15f5ff4987f0..93d6f0d656d4 100644 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c +++ b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_csf_if_fw.c @@ -303,6 +303,7 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( KBASE_DUMMY_MODEL_MAX_NUM_HARDWARE_BLOCKS * KBASE_DUMMY_MODEL_BLOCK_SIZE, .prfcnt_fw_size = KBASE_DUMMY_MODEL_MAX_FIRMWARE_BLOCKS * KBASE_DUMMY_MODEL_BLOCK_SIZE, + .metadata_size = 0, .dump_bytes = KBASE_DUMMY_MODEL_MAX_SAMPLE_SIZE, .prfcnt_block_size = KBASE_DUMMY_MODEL_BLOCK_SIZE, .clk_cnt = 1, @@ -317,6 +318,8 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( u32 prfcnt_size; u32 prfcnt_hw_size; u32 prfcnt_fw_size; + u32 prfcnt_features; + u32 metadata_size; u32 csg_count; u32 fw_block_count = 0; u32 prfcnt_block_size = @@ -330,8 +333,10 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( kbdev = fw_ctx->kbdev; csg_count = kbdev->csf.global_iface.group_num; prfcnt_size = kbdev->csf.global_iface.prfcnt_size; + prfcnt_features = kbdev->csf.global_iface.prfcnt_features; prfcnt_hw_size = GLB_PRFCNT_SIZE_HARDWARE_SIZE_GET(prfcnt_size); prfcnt_fw_size = GLB_PRFCNT_SIZE_FIRMWARE_SIZE_GET(prfcnt_size); + metadata_size = GLB_PRFCNT_FEATURES_METADATA_SIZE_GET(prfcnt_features); has_virtual_core_ids = kbdev->gpu_props.gpu_id.arch_id >= GPU_ID_ARCH_MAKE(14, 8, 4); /* Read the block size if the GPU has the register PRFCNT_FEATURES @@ -355,10 +360,11 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( else WARN_ON_ONCE(true); - fw_ctx->buf_bytes = prfcnt_hw_size + prfcnt_fw_size; + fw_ctx->buf_bytes = prfcnt_hw_size + prfcnt_fw_size + metadata_size; *prfcnt_info = (struct kbase_hwcnt_backend_csf_if_prfcnt_info){ .prfcnt_hw_size = prfcnt_hw_size, .prfcnt_fw_size = prfcnt_fw_size, + .metadata_size = metadata_size, .dump_bytes = fw_ctx->buf_bytes, .prfcnt_block_size = prfcnt_block_size, .l2_count = kbdev->gpu_props.num_l2_slices, @@ -380,10 +386,17 @@ static void kbasep_hwcnt_backend_csf_if_fw_get_prfcnt_info( else WARN_ON(prfcnt_info->ne_core_mask != 0); + WARN((metadata_size % prfcnt_info->prfcnt_block_size) != 0, + "Metadata block size is not aligned to block size (metadata size %u, block size %zu)", + metadata_size, prfcnt_info->prfcnt_block_size); /* Block size must be multiple of counter size. */ - WARN_ON((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_HW_BYTES) != 0); + WARN((prfcnt_info->prfcnt_block_size % KBASE_HWCNT_VALUE_HW_BYTES) != 0, + "Block size is not a multiple of counter size (block size %zu, counter size %lu)", + prfcnt_info->prfcnt_block_size, (unsigned long)KBASE_HWCNT_VALUE_HW_BYTES); /* Total size must be multiple of block size. */ - WARN_ON((prfcnt_info->dump_bytes % prfcnt_info->prfcnt_block_size) != 0); + WARN((prfcnt_info->dump_bytes % prfcnt_info->prfcnt_block_size) != 0, + "Total size should be a multiple of block size (total size %zu, block size %zu)", + prfcnt_info->dump_bytes, prfcnt_info->prfcnt_block_size); #endif } @@ -440,8 +453,7 @@ static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( goto page_list_alloc_error; /* Get physical page for the buffer */ - ret = kbase_mem_pool_alloc_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, - phys, false, NULL); + ret = kbase_mem_pool_alloc_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, NULL); if ((size_t)ret != num_pages) goto phys_mem_pool_alloc_error; @@ -484,8 +496,7 @@ static int kbasep_hwcnt_backend_csf_if_fw_ring_buf_alloc( mmu_insert_failed: vunmap(cpu_addr); vmap_error: - kbase_mem_pool_free_pages(&kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], num_pages, phys, - false, false); + kbase_mem_pool_free_pages(&kbdev->fw_mem_pools.small, num_pages, phys, false, false); phys_mem_pool_alloc_error: kfree(page_list); page_list_alloc_error: @@ -604,7 +615,7 @@ kbasep_hwcnt_backend_csf_if_fw_ring_buf_free(struct kbase_hwcnt_backend_csf_if_c /* After zeroing, the ring_buf pages are dirty so need to pass the 'dirty' flag * as true when freeing the pages to the Global pool. */ - kbase_mem_pool_free_pages(&fw_ctx->kbdev->mem_pools.small[KBASE_MEM_GROUP_CSF_FW], + kbase_mem_pool_free_pages(&fw_ctx->kbdev->fw_mem_pools.small, fw_ring_buf->num_pages, fw_ring_buf->phys, true, false); kfree(fw_ring_buf->phys); @@ -640,6 +651,7 @@ kbasep_hwcnt_backend_csf_if_fw_dump_enable(struct kbase_hwcnt_backend_csf_if_ctx /* Configure */ prfcnt_config = GLB_PRFCNT_CONFIG_SIZE_SET(0, fw_ring_buf->buf_count); prfcnt_config = GLB_PRFCNT_CONFIG_SET_SELECT_SET(prfcnt_config, enable->counter_set); + prfcnt_config = GLB_PRFCNT_CONFIG_METADATA_ENABLE_SET(prfcnt_config, 1); /* Configure the ring buffer base address */ kbase_csf_fw_io_global_write(&kbdev->csf.fw_io, GLB_PRFCNT_JASID, fw_ring_buf->as_nr); @@ -808,15 +820,27 @@ kbasep_hwcnt_backend_csf_if_fw_get_gpu_cycle_count(struct kbase_hwcnt_backend_cs if (!(clk_enable_map & (1ull << clk))) continue; - if (clk == KBASE_CLOCK_DOMAIN_TOP) { + /* Collect cycle count from GPU register. + * If GPU is unavailable, fall back to a SW estimation. + */ + if (clk == KBASE_CLOCK_DOMAIN_TOP && kbase_io_has_gpu(fw_ctx->kbdev)) { /* Read cycle count for top clock domain. */ kbase_backend_get_gpu_time_norequest(fw_ctx->kbdev, &cycle_counts[clk], NULL, NULL); - } else { - /* Estimate cycle count for non-top clock domain. */ - cycle_counts[clk] = - kbase_ccswe_cycle_at(&fw_ctx->ccswe_shader_cores, timestamp_ns); + + /* Check again if the device is lost. + * If we still have GPU, then the value is correct and we can continue with + * the next loop iteration. + * If it's lost, we can't guarantee we have read good data out + * from CYCLE_COUNT, so fall back to the SW estimated cycle count. + */ + if (kbase_io_has_gpu(fw_ctx->kbdev)) + continue; } + /* Estimate cycle count for non-top clock domain or for the top clock domain while + * the device is lost. + */ + cycle_counts[clk] = kbase_ccswe_cycle_at(&fw_ctx->ccswe_shader_cores, timestamp_ns); } } diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c deleted file mode 100644 index 3467c5fd4d8b..000000000000 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.c +++ /dev/null @@ -1,981 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2018-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include "hwcnt/backend/mali_kbase_hwcnt_backend_jm.h" -#include "hwcnt/mali_kbase_hwcnt_gpu.h" -#include "hwcnt/mali_kbase_hwcnt_types.h" -#include "mali_kbase.h" -#include "mali_kbase_mem_flags.h" -#include "backend/gpu/mali_kbase_pm_ca.h" -#include "mali_kbase_hwaccess_instr.h" -#include "mali_kbase_hwaccess_time.h" -#include "mali_kbase_ccswe.h" -#include "backend/gpu/mali_kbase_model_linux.h" -#include "backend/gpu/mali_kbase_clk_rate_trace_mgr.h" - -#include "backend/gpu/mali_kbase_pm_internal.h" - -/** - * struct kbase_hwcnt_backend_jm_info - Information used to create an instance - * of a JM hardware counter backend. - * @kbdev: KBase device. - * @counter_set: The performance counter set to use. - * @metadata: Hardware counter metadata. - * @dump_bytes: Bytes of GPU memory required to perform a - * hardware counter dump. - * @hwcnt_gpu_info: Hardware counter block information. - */ -struct kbase_hwcnt_backend_jm_info { - struct kbase_device *kbdev; - enum kbase_hwcnt_set counter_set; - const struct kbase_hwcnt_metadata *metadata; - size_t dump_bytes; - struct kbase_hwcnt_gpu_info hwcnt_gpu_info; -}; - -/** - * struct kbase_hwcnt_jm_physical_layout - HWC sample memory physical layout - * information. - * @fe_cnt: Front end block count. - * @tiler_cnt: Tiler block count. - * @mmu_l2_cnt: Memory system(MMU and L2 cache) block count. - * @shader_cnt: Shader Core block count. - * @block_cnt: Total block count (sum of all other block counts). - * @shader_avail_mask: Bitmap of all shader cores in the system. - * @enable_mask_offset: Offset in array elements of enable mask in each block - * starting from the beginning of block. - * @headers_per_block: Header size per block. - * @counters_per_block: Counters size per block. - * @values_per_block: Total size per block. - */ -struct kbase_hwcnt_jm_physical_layout { - u8 fe_cnt; - u8 tiler_cnt; - u8 mmu_l2_cnt; - u8 shader_cnt; - u8 block_cnt; - u64 shader_avail_mask; - size_t enable_mask_offset; - size_t headers_per_block; - size_t counters_per_block; - size_t values_per_block; -}; - -/** - * struct kbase_hwcnt_backend_jm - Instance of a JM hardware counter backend. - * @info: Info used to create the backend. - * @kctx: KBase context used for GPU memory allocation and - * counter dumping. - * @gpu_dump_va: GPU hardware counter dump buffer virtual address. - * @cpu_dump_va: CPU mapping of gpu_dump_va. - * @vmap: Dump buffer vmap. - * @to_user_buf: HWC sample buffer for client user, size - * metadata.dump_buf_bytes. - * @to_user_block_states: HWC sample block states for client user. - * @enabled: True if dumping has been enabled, else false. - * @debug_core_mask: User-set mask of shader cores that can be used. - * @pm_core_mask: PM state sync-ed shaders core mask for the enabled - * dumping. - * @curr_config: Current allocated hardware resources to correctly map the - * source raw dump buffer to the destination dump buffer. - * @max_core_mask: Core mask of all cores allocated to the GPU (non - * virtualized platforms) or resource group (virtualized - * platforms). - * @max_l2_slices: Maximum number of L2 slices allocated to the GPU (non - * virtualized platforms) or resource group (virtualized - * platforms). - * @clk_enable_map: The enable map specifying enabled clock domains. - * @cycle_count_elapsed: Cycle count elapsed for a given sample period. - * The top clock cycle, index 0, is read directly from - * hardware, but the other clock domains need to be - * calculated with software estimation. - * @prev_cycle_count: Previous cycle count to calculate the cycle count for - * sample period. - * @rate_listener: Clock rate listener callback state. - * @ccswe_shader_cores: Shader cores cycle count software estimator. - * @phys_layout: Physical memory layout information of HWC sample buffer. - * @dump_time_ns: Holds the CPU timestamp captured at the time of - * dump_request(). - */ -struct kbase_hwcnt_backend_jm { - const struct kbase_hwcnt_backend_jm_info *info; - struct kbase_context *kctx; - u64 gpu_dump_va; - void *cpu_dump_va; - struct kbase_vmap_struct *vmap; - u64 *to_user_buf; - blk_stt_t *to_user_block_states; - bool enabled; - u64 debug_core_mask; - u64 pm_core_mask; - struct kbase_hwcnt_curr_config curr_config; - u64 max_core_mask; - size_t max_l2_slices; - u64 clk_enable_map; - u64 cycle_count_elapsed[BASE_MAX_NR_CLOCKS_REGULATORS]; - u64 prev_cycle_count[BASE_MAX_NR_CLOCKS_REGULATORS]; - struct kbase_clk_rate_listener rate_listener; - struct kbase_ccswe ccswe_shader_cores; - struct kbase_hwcnt_jm_physical_layout phys_layout; - u64 dump_time_ns; -}; - -/** - * kbasep_hwcnt_backend_jm_gpu_info_init() - Initialise an info structure used - * to create the hwcnt metadata. - * @kbdev: Non-NULL pointer to kbase device. - * @info: Non-NULL pointer to data structure to be filled in. - * - * The initialised info struct will only be valid for use while kbdev is valid. - * - * Return: 0 on success, else error code. - */ -static int kbasep_hwcnt_backend_jm_gpu_info_init(struct kbase_device *kbdev, - struct kbase_hwcnt_gpu_info *info) -{ - size_t clk, l2_count, core_mask; - - if (!kbdev || !info) - return -EINVAL; - -#if IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) - l2_count = KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS; - core_mask = (1ull << KBASE_DUMMY_MODEL_MAX_SHADER_CORES) - 1; -#else - l2_count = kbdev->gpu_props.num_l2_slices; - core_mask = kbdev->gpu_props.coherency_info.group.core_mask; -#endif - - info->l2_count = l2_count; - info->sc_core_mask = core_mask; - info->prfcnt_values_per_block = KBASE_HWCNT_V5_DEFAULT_VALUES_PER_BLOCK; - - /* Determine the number of available clock domains. */ - for (clk = 0; clk < BASE_MAX_NR_CLOCKS_REGULATORS; clk++) { - if (kbdev->pm.clk_rtm.clks[clk] == NULL) - break; - } - info->clk_cnt = clk; - - return 0; -} - -static void kbasep_hwcnt_backend_jm_init_layout(const struct kbase_hwcnt_gpu_info *gpu_info, - struct kbase_hwcnt_jm_physical_layout *phys_layout) -{ - u8 shader_core_cnt; - - WARN_ON(!gpu_info); - WARN_ON(!phys_layout); - - shader_core_cnt = fls64(gpu_info->sc_core_mask); - - *phys_layout = (struct kbase_hwcnt_jm_physical_layout){ - .fe_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT, - .tiler_cnt = KBASE_HWCNT_V5_TILER_BLOCK_COUNT, - .mmu_l2_cnt = gpu_info->l2_count, - .shader_cnt = shader_core_cnt, - .block_cnt = KBASE_HWCNT_V5_FE_BLOCK_COUNT + KBASE_HWCNT_V5_TILER_BLOCK_COUNT + - gpu_info->l2_count + shader_core_cnt, - .shader_avail_mask = gpu_info->sc_core_mask, - .headers_per_block = KBASE_HWCNT_V5_HEADERS_PER_BLOCK, - .values_per_block = gpu_info->prfcnt_values_per_block, - .counters_per_block = - gpu_info->prfcnt_values_per_block - KBASE_HWCNT_V5_HEADERS_PER_BLOCK, - .enable_mask_offset = KBASE_HWCNT_V5_PRFCNT_EN_HEADER, - }; -} - -static void -kbasep_hwcnt_backend_jm_dump_sample(const struct kbase_hwcnt_backend_jm *const backend_jm) -{ - size_t block_idx; - const u32 *new_sample_buf = backend_jm->cpu_dump_va; - const u32 *new_block = new_sample_buf; - u64 *dst_buf = backend_jm->to_user_buf; - u64 *dst_block = dst_buf; - const size_t values_per_block = backend_jm->phys_layout.values_per_block; - const size_t dump_bytes = backend_jm->info->dump_bytes; - - for (block_idx = 0; block_idx < backend_jm->phys_layout.block_cnt; block_idx++) { - size_t ctr_idx; - - for (ctr_idx = 0; ctr_idx < values_per_block; ctr_idx++) - dst_block[ctr_idx] = new_block[ctr_idx]; - - new_block += values_per_block; - dst_block += values_per_block; - } - - WARN_ON(new_block != new_sample_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); - WARN_ON(dst_block != dst_buf + (dump_bytes / KBASE_HWCNT_VALUE_HW_BYTES)); -} - -/** - * kbasep_hwcnt_backend_jm_on_freq_change() - On freq change callback - * - * @rate_listener: Callback state - * @clk_index: Clock index - * @clk_rate_hz: Clock frequency(hz) - */ -static void kbasep_hwcnt_backend_jm_on_freq_change(struct kbase_clk_rate_listener *rate_listener, - u32 clk_index, u32 clk_rate_hz) -{ - struct kbase_hwcnt_backend_jm *backend_jm = - container_of(rate_listener, struct kbase_hwcnt_backend_jm, rate_listener); - u64 timestamp_ns; - - if (clk_index != KBASE_CLOCK_DOMAIN_SHADER_CORES) - return; - - timestamp_ns = ktime_get_raw_ns(); - kbase_ccswe_freq_change(&backend_jm->ccswe_shader_cores, timestamp_ns, clk_rate_hz); -} - -/** - * kbasep_hwcnt_backend_jm_cc_enable() - Enable cycle count tracking - * - * @backend_jm: Non-NULL pointer to backend. - * @enable_map: Non-NULL pointer to enable map specifying enabled counters. - * @timestamp_ns: Timestamp(ns) when HWCNT were enabled. - */ -static void kbasep_hwcnt_backend_jm_cc_enable(struct kbase_hwcnt_backend_jm *backend_jm, - const struct kbase_hwcnt_enable_map *enable_map, - u64 timestamp_ns) -{ - struct kbase_device *kbdev = backend_jm->kctx->kbdev; - u64 clk_enable_map = enable_map->clk_enable_map; - u64 cycle_count; - - if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { - /* turn on the cycle counter */ - kbase_pm_request_gpu_cycle_counter_l2_is_on(kbdev); - /* Read cycle count for top clock domain. */ - kbase_backend_get_gpu_time_norequest(kbdev, &cycle_count, NULL, NULL); - - backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_TOP] = cycle_count; - } - - if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { - /* software estimation for non-top clock domains */ - struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; - const struct kbase_clk_data *clk_data = rtm->clks[KBASE_CLOCK_DOMAIN_SHADER_CORES]; - u32 cur_freq; - unsigned long flags; - - spin_lock_irqsave(&rtm->lock, flags); - - cur_freq = (u32)clk_data->clock_val; - kbase_ccswe_reset(&backend_jm->ccswe_shader_cores); - kbase_ccswe_freq_change(&backend_jm->ccswe_shader_cores, timestamp_ns, cur_freq); - - kbase_clk_rate_trace_manager_subscribe_no_lock(rtm, &backend_jm->rate_listener); - - spin_unlock_irqrestore(&rtm->lock, flags); - - /* ccswe was reset. The estimated cycle is zero. */ - backend_jm->prev_cycle_count[KBASE_CLOCK_DOMAIN_SHADER_CORES] = 0; - } - - /* Keep clk_enable_map for dump_request. */ - backend_jm->clk_enable_map = clk_enable_map; -} - -/** - * kbasep_hwcnt_backend_jm_cc_disable() - Disable cycle count tracking - * - * @backend_jm: Non-NULL pointer to backend. - */ -static void kbasep_hwcnt_backend_jm_cc_disable(struct kbase_hwcnt_backend_jm *backend_jm) -{ - struct kbase_device *kbdev = backend_jm->kctx->kbdev; - struct kbase_clk_rate_trace_manager *rtm = &kbdev->pm.clk_rtm; - u64 clk_enable_map = backend_jm->clk_enable_map; - - if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_TOP)) { - /* turn off the cycle counter */ - kbase_pm_release_gpu_cycle_counter(kbdev); - } - - if (kbase_hwcnt_clk_enable_map_enabled(clk_enable_map, KBASE_CLOCK_DOMAIN_SHADER_CORES)) { - kbase_clk_rate_trace_manager_unsubscribe(rtm, &backend_jm->rate_listener); - } -} - -/** - * kbasep_hwcnt_gpu_update_curr_config() - Update the destination buffer with - * current config information. - * @kbdev: Non-NULL pointer to kbase device. - * @curr_config: Non-NULL pointer to return the current configuration of - * hardware allocated to the GPU. - * - * The current configuration information is used for architectures where the - * max_config interface is available from the Arbiter. In this case the current - * allocated hardware is not always the same, so the current config information - * is used to correctly map the current allocated resources to the memory layout - * that is copied to the user space. - * - * Return: 0 on success, else error code. - */ -static int kbasep_hwcnt_gpu_update_curr_config(struct kbase_device *kbdev, - struct kbase_hwcnt_curr_config *curr_config) -{ - if (WARN_ON(!kbdev) || WARN_ON(!curr_config)) - return -EINVAL; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - curr_config->num_l2_slices = kbdev->gpu_props.curr_config.l2_slices; - curr_config->shader_present = kbdev->gpu_props.curr_config.shader_present; - return 0; -} - -/* JM backend implementation of kbase_hwcnt_backend_timestamp_ns_fn */ -static u64 kbasep_hwcnt_backend_jm_timestamp_ns(struct kbase_hwcnt_backend *backend) -{ - (void)backend; - return ktime_get_raw_ns(); -} - -static void kbasep_hwcnt_backend_jm_append_block_states(struct kbase_hwcnt_backend_jm *backend_jm, - blk_stt_t block_state) -{ - size_t i; - - for (i = 0; i < backend_jm->phys_layout.block_cnt; i++) - kbase_hwcnt_block_state_append(&backend_jm->to_user_block_states[i], block_state); -} - -static void -kbasep_hwcnt_backend_jm_get_physical_enable(struct kbase_hwcnt_backend_jm *backend_jm, - const struct kbase_hwcnt_enable_map *enable_map, - struct kbase_instr_hwcnt_enable *enable) -{ - enum kbase_hwcnt_physical_set phys_counter_set; - struct kbase_hwcnt_physical_enable_map phys_enable_map = { 0 }; - - kbase_hwcnt_gpu_enable_map_to_physical(&phys_enable_map, enable_map); - - kbase_hwcnt_gpu_set_to_physical(&phys_counter_set, backend_jm->info->counter_set); - - *enable = (struct kbase_instr_hwcnt_enable){ - .fe_bm = phys_enable_map.fe_bm, - .shader_bm = phys_enable_map.shader_bm, - .tiler_bm = phys_enable_map.tiler_bm, - .mmu_l2_bm = phys_enable_map.mmu_l2_bm, - .counter_set = phys_counter_set, - .dump_buffer = backend_jm->gpu_dump_va, - .dump_buffer_bytes = backend_jm->info->dump_bytes, - }; - - /* The dummy model needs the CPU mapping. */ - if (IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI)) - enable->dump_buffer = (uintptr_t)backend_jm->cpu_dump_va; -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_enable_nolock_fn */ -static int -kbasep_hwcnt_backend_jm_dump_enable_nolock(struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) -{ - int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - struct kbase_context *kctx; - struct kbase_device *kbdev; - struct kbase_instr_hwcnt_enable enable = { 0 }; - u64 timestamp_ns; - - if (!backend_jm || !enable_map || backend_jm->enabled || - (enable_map->metadata != backend_jm->info->metadata)) - return -EINVAL; - - kctx = backend_jm->kctx; - kbdev = backend_jm->kctx->kbdev; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - kbasep_hwcnt_backend_jm_get_physical_enable(backend_jm, enable_map, &enable); - - timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend); - - /* Update the current configuration information. */ - errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, &backend_jm->curr_config); - if (errcode) - goto error; - - errcode = kbase_instr_hwcnt_enable_internal(kbdev, kctx, &enable); - if (errcode) - goto error; - - backend_jm->debug_core_mask = kbase_pm_ca_get_debug_core_mask(kbdev); - backend_jm->max_l2_slices = backend_jm->info->hwcnt_gpu_info.l2_count; - backend_jm->max_core_mask = backend_jm->info->hwcnt_gpu_info.sc_core_mask; - - backend_jm->pm_core_mask = kbase_pm_ca_get_instr_core_mask(kbdev); - - backend_jm->enabled = true; - - /* Enabling counters is an indication that the power may have previously been off for all - * blocks. - * - * In any case, the counters would not have been counting recently, so an 'off' block state - * is an approximation for this. - * - * This will be transferred to the dump only after a dump_wait(), or dump_disable() in - * cases where the caller requested such information. This is to handle when a - * dump_enable() happens in between dump_wait() and dump_get(). - */ - kbasep_hwcnt_backend_jm_append_block_states(backend_jm, KBASE_HWCNT_STATE_OFF); - - kbasep_hwcnt_backend_jm_cc_enable(backend_jm, enable_map, timestamp_ns); - - return 0; -error: - return errcode; -} - -static void -kbasep_hwcnt_backend_jm_reset_consumed_buffers(struct kbase_hwcnt_backend_jm *backend_jm) -{ - size_t block_state_bytes = backend_jm->phys_layout.block_cnt * - KBASE_HWCNT_BLOCK_STATE_BYTES * KBASE_HWCNT_BLOCK_STATE_STRIDE; - - memset(backend_jm->to_user_block_states, 0, block_state_bytes); -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_enable_fn */ -static int kbasep_hwcnt_backend_jm_dump_enable(struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) -{ - unsigned long flags; - int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - struct kbase_device *kbdev; - - if (!backend_jm) - return -EINVAL; - - kbdev = backend_jm->kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - errcode = kbasep_hwcnt_backend_jm_dump_enable_nolock(backend, enable_map); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return errcode; -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_disable_fn */ -static void kbasep_hwcnt_backend_jm_dump_disable(struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dump_buffer, - const struct kbase_hwcnt_enable_map *enable_map) -{ - int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - - if (WARN_ON(!backend_jm || - (dump_buffer && (backend_jm->info->metadata != dump_buffer->metadata)) || - (enable_map && (backend_jm->info->metadata != enable_map->metadata)) || - (dump_buffer && !enable_map))) - return; - - /* No WARN needed here, but still return early if backend is already disabled */ - if (!backend_jm->enabled) - return; - - kbasep_hwcnt_backend_jm_cc_disable(backend_jm); - - errcode = kbase_instr_hwcnt_disable_internal(backend_jm->kctx); - WARN_ON(errcode); - - kbasep_hwcnt_backend_jm_append_block_states(backend_jm, KBASE_HWCNT_STATE_OFF); - - if (dump_buffer) { - /* In some use-cases, the caller will need the information whilst the counters are - * disabled, but will not be able to call into the backend to dump them. Instead, - * they have an opportunity here to request them to be accumulated into their - * buffer immediately. - * - * This consists of taking a sample of the accumulated block state (as though a - * real dump_get() had happened), then transfer ownership of that to the caller - * (i.e. erasing our copy of it). - */ - kbase_hwcnt_dump_buffer_append_block_states(dump_buffer, enable_map, - backend_jm->to_user_block_states); - - /* Now the block state has been passed out into the caller's own accumulation - * buffer, clear our own accumulated and sampled block state - ownership has been - * transferred. - */ - kbasep_hwcnt_backend_jm_reset_consumed_buffers(backend_jm); - } - - backend_jm->enabled = false; -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_clear_fn */ -static int kbasep_hwcnt_backend_jm_dump_clear(struct kbase_hwcnt_backend *backend) -{ - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - - if (!backend_jm || !backend_jm->enabled) - return -EINVAL; - - return kbase_instr_hwcnt_clear(backend_jm->kctx); -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_request_fn */ -static int kbasep_hwcnt_backend_jm_dump_request(struct kbase_hwcnt_backend *backend) -{ - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - struct kbase_device *kbdev; - const struct kbase_hwcnt_metadata *metadata; - u64 current_cycle_count; - size_t clk; - int ret; - - if (!backend_jm || !backend_jm->enabled) - return -EINVAL; - - kbdev = backend_jm->kctx->kbdev; - metadata = backend_jm->info->metadata; - - /* Disable pre-emption, to make the timestamp as accurate as possible */ - preempt_disable(); - { - backend_jm->dump_time_ns = kbasep_hwcnt_backend_jm_timestamp_ns(backend); - ret = kbase_instr_hwcnt_request_dump(backend_jm->kctx); - - kbase_hwcnt_metadata_for_each_clock(metadata, clk) { - if (!kbase_hwcnt_clk_enable_map_enabled(backend_jm->clk_enable_map, clk)) - continue; - - if (clk == KBASE_CLOCK_DOMAIN_TOP) { - /* Read cycle count for top clock domain. */ - kbase_backend_get_gpu_time_norequest(kbdev, ¤t_cycle_count, - NULL, NULL); - } else { - /* - * Estimate cycle count for non-top clock - * domain. - */ - current_cycle_count = kbase_ccswe_cycle_at( - &backend_jm->ccswe_shader_cores, backend_jm->dump_time_ns); - } - backend_jm->cycle_count_elapsed[clk] = - current_cycle_count - backend_jm->prev_cycle_count[clk]; - - /* - * Keep the current cycle count for later calculation. - */ - backend_jm->prev_cycle_count[clk] = current_cycle_count; - } - } - preempt_enable(); - - return ret; -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_wait_fn */ -static int kbasep_hwcnt_backend_jm_dump_wait(struct kbase_hwcnt_backend *backend) -{ - int errcode; - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - - if (!backend_jm || !backend_jm->enabled) - return -EINVAL; - - errcode = kbase_instr_hwcnt_wait_for_dump(backend_jm->kctx); - if (errcode) - return errcode; - - return errcode; -} - -/* JM backend implementation of kbase_hwcnt_backend_dump_get_fn */ -static int kbasep_hwcnt_backend_jm_dump_get(struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dst, - const struct kbase_hwcnt_enable_map *dst_enable_map, - bool accumulate, u64 *dump_time_ns) -{ - struct kbase_hwcnt_backend_jm *backend_jm = (struct kbase_hwcnt_backend_jm *)backend; - size_t clk; -#if IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) - struct kbase_device *kbdev; - unsigned long flags; -#endif /* CONFIG_MALI_VALHALL_NO_MALI */ - int errcode; - - if (!backend_jm || !dst || !dst_enable_map || !dump_time_ns || - (backend_jm->info->metadata != dst->metadata) || - (dst_enable_map->metadata != dst->metadata)) - return -EINVAL; - - /* Invalidate the kernel buffer before reading from it. */ - kbase_sync_mem_regions(backend_jm->kctx, backend_jm->vmap, KBASE_SYNC_TO_CPU); - - /* Dump sample to the internal 64-bit user buffer. */ - kbasep_hwcnt_backend_jm_dump_sample(backend_jm); - - /* Extract elapsed cycle count for each clock domain if enabled. */ - kbase_hwcnt_metadata_for_each_clock(dst_enable_map->metadata, clk) { - if (!kbase_hwcnt_clk_enable_map_enabled(dst_enable_map->clk_enable_map, clk)) - continue; - - /* Reset the counter to zero if accumulation is off. */ - if (!accumulate) - dst->clk_cnt_buf[clk] = 0; - dst->clk_cnt_buf[clk] += backend_jm->cycle_count_elapsed[clk]; - } - -#if IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) - kbdev = backend_jm->kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* Update the current configuration information. */ - errcode = kbasep_hwcnt_gpu_update_curr_config(kbdev, &backend_jm->curr_config); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (errcode) - return errcode; -#endif /* CONFIG_MALI_VALHALL_NO_MALI */ - errcode = kbase_hwcnt_jm_dump_get(dst, backend_jm->to_user_buf, dst_enable_map, - backend_jm->pm_core_mask, backend_jm->debug_core_mask, - backend_jm->max_l2_slices, &backend_jm->curr_config, - accumulate); - - if (errcode) - return errcode; - - *dump_time_ns = backend_jm->dump_time_ns; - kbase_hwcnt_dump_buffer_append_block_states(dst, dst_enable_map, - backend_jm->to_user_block_states); - kbasep_hwcnt_backend_jm_reset_consumed_buffers(backend_jm); - - return errcode; -} - -/** - * kbasep_hwcnt_backend_jm_dump_alloc() - Allocate a GPU dump buffer. - * @info: Non-NULL pointer to JM backend info. - * @kctx: Non-NULL pointer to kbase context. - * @gpu_dump_va: Non-NULL pointer to where GPU dump buffer virtual address - * is stored on success. - * - * Return: 0 on success, else error code. - */ -static int kbasep_hwcnt_backend_jm_dump_alloc(const struct kbase_hwcnt_backend_jm_info *info, - struct kbase_context *kctx, u64 *gpu_dump_va) -{ - struct kbase_va_region *reg; - base_mem_alloc_flags flags; - u64 nr_pages; - - /* Calls to this function are inherently asynchronous, with respect to - * MMU operations. - */ - const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; - - WARN_ON(!info); - WARN_ON(!kctx); - WARN_ON(!gpu_dump_va); - - flags = BASE_MEM_PROT_CPU_RD | BASE_MEM_PROT_GPU_WR | BASEP_MEM_PERMANENT_KERNEL_MAPPING | - BASE_MEM_CACHED_CPU | BASE_MEM_UNCACHED_GPU; - - nr_pages = PFN_UP(info->dump_bytes); - - reg = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, gpu_dump_va, mmu_sync_info); - - if (!reg) - return -ENOMEM; - - return 0; -} - -/** - * kbasep_hwcnt_backend_jm_dump_free() - Free an allocated GPU dump buffer. - * @kctx: Non-NULL pointer to kbase context. - * @gpu_dump_va: GPU dump buffer virtual address. - */ -static void kbasep_hwcnt_backend_jm_dump_free(struct kbase_context *kctx, u64 gpu_dump_va) -{ - WARN_ON(!kctx); - if (gpu_dump_va) - kbase_mem_free(kctx, gpu_dump_va); -} - -/** - * kbasep_hwcnt_backend_jm_destroy() - Destroy a JM backend. - * @backend: Pointer to JM backend to destroy. - * - * Can be safely called on a backend in any state of partial construction. - */ -static void kbasep_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_jm *backend) -{ - if (!backend) - return; - - if (backend->kctx) { - struct kbase_context *kctx = backend->kctx; - struct kbase_device *kbdev = kctx->kbdev; - - if (backend->cpu_dump_va) - kbase_phy_alloc_mapping_put(kctx, backend->vmap); - - if (backend->gpu_dump_va) - kbasep_hwcnt_backend_jm_dump_free(kctx, backend->gpu_dump_va); - - kbasep_js_release_privileged_ctx(kbdev, kctx); - kbase_destroy_context(kctx); - } - - kfree(backend->to_user_buf); - - kfree(backend->to_user_block_states); - - kfree(backend); -} - -/** - * kbasep_hwcnt_backend_jm_create() - Create a JM backend. - * @info: Non-NULL pointer to backend info. - * @out_backend: Non-NULL pointer to where backend is stored on success. - * - * Return: 0 on success, else error code. - */ -static int kbasep_hwcnt_backend_jm_create(const struct kbase_hwcnt_backend_jm_info *info, - struct kbase_hwcnt_backend_jm **out_backend) -{ - int errcode; - struct kbase_device *kbdev; - struct kbase_hwcnt_backend_jm *backend = NULL; - size_t block_state_bytes; - - WARN_ON(!info); - WARN_ON(!out_backend); - - kbdev = info->kbdev; - - backend = kzalloc(sizeof(*backend), GFP_KERNEL); - if (!backend) - goto alloc_error; - - backend->info = info; - kbasep_hwcnt_backend_jm_init_layout(&info->hwcnt_gpu_info, &backend->phys_layout); - - backend->kctx = kbase_create_context(kbdev, true, - BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED, 0, NULL); - if (!backend->kctx) - goto alloc_error; - - kbasep_js_schedule_privileged_ctx(kbdev, backend->kctx); - - errcode = kbasep_hwcnt_backend_jm_dump_alloc(info, backend->kctx, &backend->gpu_dump_va); - if (errcode) - goto error; - - backend->cpu_dump_va = - kbase_phy_alloc_mapping_get(backend->kctx, backend->gpu_dump_va, &backend->vmap); - if (!backend->cpu_dump_va || !backend->vmap) - goto alloc_error; - - backend->to_user_buf = kzalloc(info->metadata->dump_buf_bytes, GFP_KERNEL); - if (!backend->to_user_buf) - goto alloc_error; - - block_state_bytes = backend->phys_layout.block_cnt * KBASE_HWCNT_BLOCK_STATE_BYTES * - KBASE_HWCNT_BLOCK_STATE_STRIDE; - - backend->to_user_block_states = kzalloc(block_state_bytes, GFP_KERNEL); - if (!backend->to_user_block_states) - goto alloc_error; - - memset(backend->to_user_block_states, 0, block_state_bytes); - - kbase_ccswe_init(&backend->ccswe_shader_cores); - backend->rate_listener.notify = kbasep_hwcnt_backend_jm_on_freq_change; - - *out_backend = backend; - return 0; - -alloc_error: - errcode = -ENOMEM; -error: - kbasep_hwcnt_backend_jm_destroy(backend); - return errcode; -} - -/* JM backend implementation of kbase_hwcnt_backend_metadata_fn */ -static const struct kbase_hwcnt_metadata * -kbasep_hwcnt_backend_jm_metadata(const struct kbase_hwcnt_backend_info *info) -{ - if (!info) - return NULL; - - return ((const struct kbase_hwcnt_backend_jm_info *)info)->metadata; -} - -/* JM backend implementation of kbase_hwcnt_backend_init_fn */ -static int kbasep_hwcnt_backend_jm_init(const struct kbase_hwcnt_backend_info *info, - struct kbase_hwcnt_backend **out_backend) -{ - int errcode; - struct kbase_hwcnt_backend_jm *backend = NULL; - - if (!info || !out_backend) - return -EINVAL; - - errcode = kbasep_hwcnt_backend_jm_create((const struct kbase_hwcnt_backend_jm_info *)info, - &backend); - if (errcode) - return errcode; - - *out_backend = (struct kbase_hwcnt_backend *)backend; - - return 0; -} - -/* JM backend implementation of kbase_hwcnt_backend_term_fn */ -static void kbasep_hwcnt_backend_jm_term(struct kbase_hwcnt_backend *backend) -{ - if (!backend) - return; - - kbasep_hwcnt_backend_jm_dump_disable(backend, NULL, NULL); - kbasep_hwcnt_backend_jm_destroy((struct kbase_hwcnt_backend_jm *)backend); -} - -static void kbasep_hwcnt_backend_jm_acquire(const struct kbase_hwcnt_backend *backend) -{ -} - -static void kbasep_hwcnt_backend_jm_release(const struct kbase_hwcnt_backend *backend) -{ -} - -/** - * kbasep_hwcnt_backend_jm_info_destroy() - Destroy a JM backend info. - * @info: Pointer to info to destroy. - * - * Can be safely called on a backend info in any state of partial construction. - */ -static void kbasep_hwcnt_backend_jm_info_destroy(const struct kbase_hwcnt_backend_jm_info *info) -{ - if (!info) - return; - - kbase_hwcnt_metadata_destroy(info->metadata); - kfree(info); -} - -/** - * kbasep_hwcnt_backend_jm_info_create() - Create a JM backend info. - * @kbdev: Non_NULL pointer to kbase device. - * @out_info: Non-NULL pointer to where info is stored on success. - * - * Return: 0 on success, else error code. - */ -static int kbasep_hwcnt_backend_jm_info_create(struct kbase_device *kbdev, - const struct kbase_hwcnt_backend_jm_info **out_info) -{ - int errcode = -ENOMEM; - struct kbase_hwcnt_backend_jm_info *info = NULL; - - WARN_ON(!kbdev); - WARN_ON(!out_info); - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return errcode; - - info->kbdev = kbdev; - -#ifdef CONFIG_MALI_VALHALL_PRFCNT_SET_SECONDARY - info->counter_set = KBASE_HWCNT_SET_SECONDARY; -#elif defined(CONFIG_MALI_VALHALL_PRFCNT_SET_TERTIARY) - info->counter_set = KBASE_HWCNT_SET_TERTIARY; -#else - /* Default to primary */ - info->counter_set = KBASE_HWCNT_SET_PRIMARY; -#endif - - errcode = kbasep_hwcnt_backend_jm_gpu_info_init(kbdev, &info->hwcnt_gpu_info); - if (errcode) - goto error; - - errcode = kbase_hwcnt_jm_metadata_create(&info->hwcnt_gpu_info, info->counter_set, - &info->metadata, &info->dump_bytes); - if (errcode) - goto error; - - *out_info = info; - - return 0; -error: - kbasep_hwcnt_backend_jm_info_destroy(info); - return errcode; -} - -int kbase_hwcnt_backend_jm_create(struct kbase_device *kbdev, - struct kbase_hwcnt_backend_interface *iface) -{ - int errcode; - const struct kbase_hwcnt_backend_jm_info *info = NULL; - - if (!kbdev || !iface) - return -EINVAL; - - errcode = kbasep_hwcnt_backend_jm_info_create(kbdev, &info); - - if (errcode) - return errcode; - - iface->info = (struct kbase_hwcnt_backend_info *)info; - iface->metadata = kbasep_hwcnt_backend_jm_metadata; - iface->init = kbasep_hwcnt_backend_jm_init; - iface->term = kbasep_hwcnt_backend_jm_term; - iface->acquire = kbasep_hwcnt_backend_jm_acquire; - iface->release = kbasep_hwcnt_backend_jm_release; - iface->timestamp_ns = kbasep_hwcnt_backend_jm_timestamp_ns; - iface->dump_enable = kbasep_hwcnt_backend_jm_dump_enable; - iface->dump_enable_nolock = kbasep_hwcnt_backend_jm_dump_enable_nolock; - iface->dump_disable = kbasep_hwcnt_backend_jm_dump_disable; - iface->dump_clear = kbasep_hwcnt_backend_jm_dump_clear; - iface->dump_request = kbasep_hwcnt_backend_jm_dump_request; - iface->dump_wait = kbasep_hwcnt_backend_jm_dump_wait; - iface->dump_get = kbasep_hwcnt_backend_jm_dump_get; - - return 0; -} - -void kbase_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_interface *iface) -{ - if (!iface) - return; - - kbasep_hwcnt_backend_jm_info_destroy( - (const struct kbase_hwcnt_backend_jm_info *)iface->info); - memset(iface, 0, sizeof(*iface)); -} diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h deleted file mode 100644 index 4a6293c25473..000000000000 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2018, 2020-2022 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Concrete implementation of mali_kbase_hwcnt_backend interface for JM - * backend. - */ - -#ifndef _KBASE_HWCNT_BACKEND_JM_H_ -#define _KBASE_HWCNT_BACKEND_JM_H_ - -#include "hwcnt/backend/mali_kbase_hwcnt_backend.h" - -struct kbase_device; - -/** - * kbase_hwcnt_backend_jm_create() - Create a JM hardware counter backend - * interface. - * @kbdev: Non-NULL pointer to kbase device. - * @iface: Non-NULL pointer to backend interface structure that is filled in - * on creation success. - * - * Calls to iface->dump_enable_nolock() require kbdev->hwaccess_lock held. - * - * Return: 0 on success, else error code. - */ -int kbase_hwcnt_backend_jm_create(struct kbase_device *kbdev, - struct kbase_hwcnt_backend_interface *iface); - -/** - * kbase_hwcnt_backend_jm_destroy() - Destroy a JM hardware counter backend - * interface. - * @iface: Pointer to interface to destroy. - * - * Can be safely called on an all-zeroed interface, or on an already destroyed - * interface. - */ -void kbase_hwcnt_backend_jm_destroy(struct kbase_hwcnt_backend_interface *iface); - -#endif /* _KBASE_HWCNT_BACKEND_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c deleted file mode 100644 index a68be8c64fd9..000000000000 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.c +++ /dev/null @@ -1,841 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include - -#include -#include - -#include -#include -#include - -/* - * IDLE_BUFFER_EMPTY -> USER_DUMPING_BUFFER_EMPTY on dump_request. - * IDLE_BUFFER_EMPTY -> TIMER_DUMPING after - * hwcnt_backend_watchdog_timer_interval_ms - * milliseconds, if no dump_request has been - * called in the meantime. - * IDLE_BUFFER_FULL -> USER_DUMPING_BUFFER_FULL on dump_request. - * IDLE_BUFFER_FULL -> TIMER_DUMPING after - * hwcnt_backend_watchdog_timer_interval_ms - * milliseconds, if no dump_request has been - * called in the meantime. - * IDLE_BUFFER_FULL -> IDLE_BUFFER_EMPTY on dump_disable, upon discarding undumped - * counter values since the last dump_get. - * IDLE_BUFFER_EMPTY -> BUFFER_CLEARING on dump_clear, before calling job manager - * backend dump_clear. - * IDLE_BUFFER_FULL -> BUFFER_CLEARING on dump_clear, before calling job manager - * backend dump_clear. - * USER_DUMPING_BUFFER_EMPTY -> BUFFER_CLEARING on dump_clear, before calling job manager - * backend dump_clear. - * USER_DUMPING_BUFFER_FULL -> BUFFER_CLEARING on dump_clear, before calling job manager - * backend dump_clear. - * BUFFER_CLEARING -> IDLE_BUFFER_EMPTY on dump_clear, upon job manager backend - * dump_clear completion. - * TIMER_DUMPING -> IDLE_BUFFER_FULL on timer's callback completion. - * TIMER_DUMPING -> TIMER_DUMPING_USER_CLEAR on dump_clear, notifies the callback thread - * that there is no need for dumping the buffer - * anymore, and that the client will proceed - * clearing the buffer. - * TIMER_DUMPING_USER_CLEAR -> IDLE_BUFFER_EMPTY on timer's callback completion, when a user - * requested a dump_clear. - * TIMER_DUMPING -> TIMER_DUMPING_USER_REQUESTED on dump_request, when a client performs a - * dump request while the timer is dumping (the - * timer will perform the dump and (once - * completed) the client will retrieve the value - * from the buffer). - * TIMER_DUMPING_USER_REQUESTED -> IDLE_BUFFER_EMPTY on dump_get, when a timer completed and the - * user reads the periodic dump buffer. - * Any -> ERROR if the job manager backend returns an error - * (of any kind). - * USER_DUMPING_BUFFER_EMPTY -> IDLE_BUFFER_EMPTY on dump_get (performs get, ignores the - * periodic dump buffer and returns). - * USER_DUMPING_BUFFER_FULL -> IDLE_BUFFER_EMPTY on dump_get (performs get, accumulates with - * periodic dump buffer and returns). - */ - -/** enum backend_watchdog_state State used to synchronize timer callbacks with the main thread. - * @HWCNT_JM_WD_ERROR: Received an error from the job manager backend calls. - * @HWCNT_JM_WD_IDLE_BUFFER_EMPTY: Initial state. Watchdog timer enabled, periodic dump buffer is - * empty. - * @HWCNT_JM_WD_IDLE_BUFFER_FULL: Watchdog timer enabled, periodic dump buffer is full. - * @HWCNT_JM_WD_BUFFER_CLEARING: The client is performing a dump clear. A concurrent timer callback - * thread should just ignore and reschedule another callback in - * hwcnt_backend_watchdog_timer_interval_ms milliseconds. - * @HWCNT_JM_WD_TIMER_DUMPING: The timer ran out. The callback is performing a periodic dump. - * @HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED: While the timer is performing a periodic dump, user - * requested a dump. - * @HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR: While the timer is performing a dump, user requested a - * dump_clear. The timer has to complete the periodic dump - * and clear buffer (internal and job manager backend). - * @HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY: From IDLE state, user requested a dump. The periodic - * dump buffer is empty. - * @HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL: From IDLE state, user requested a dump. The periodic dump - * buffer is full. - * - * While the state machine is in HWCNT_JM_WD_TIMER_DUMPING*, only the timer callback thread is - * allowed to call the job manager backend layer. - */ -enum backend_watchdog_state { - HWCNT_JM_WD_ERROR, - HWCNT_JM_WD_IDLE_BUFFER_EMPTY, - HWCNT_JM_WD_IDLE_BUFFER_FULL, - HWCNT_JM_WD_BUFFER_CLEARING, - HWCNT_JM_WD_TIMER_DUMPING, - HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED, - HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR, - HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY, - HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL, -}; - -/** enum wd_init_state - State machine for initialization / termination of the backend resources - */ -enum wd_init_state { - HWCNT_JM_WD_INIT_START, - HWCNT_JM_WD_INIT_BACKEND = HWCNT_JM_WD_INIT_START, - HWCNT_JM_WD_INIT_ENABLE_MAP, - HWCNT_JM_WD_INIT_DUMP_BUFFER, - HWCNT_JM_WD_INIT_END -}; - -/** - * struct kbase_hwcnt_backend_jm_watchdog_info - Immutable information used to initialize an - * instance of the job manager watchdog backend. - * @jm_backend_iface: Hardware counter backend interface. This module extends - * this interface with a watchdog that performs regular - * dumps. The new interface this module provides complies - * with the old backend interface. - * @dump_watchdog_iface: Dump watchdog interface, used to periodically dump the - * hardware counter in case no reads are requested within - * a certain time, used to avoid hardware counter's buffer - * saturation. - * @watchdog_timer_interval_ms: Interval in milliseconds between hwcnt samples. - */ -struct kbase_hwcnt_backend_jm_watchdog_info { - struct kbase_hwcnt_backend_interface *jm_backend_iface; - struct kbase_hwcnt_watchdog_interface *dump_watchdog_iface; - u32 watchdog_timer_interval_ms; -}; - -/** - * struct kbase_hwcnt_backend_jm_watchdog - An instance of the job manager watchdog backend. - * @info: Immutable information used to create the job manager watchdog backend. - * @jm_backend: Job manager's backend internal state. To be passed as argument during parent calls. - * @timeout_ms: Time period in milliseconds for hardware counters dumping. - * @wd_dump_buffer: Used to store periodic dumps done by a timer callback function. Contents are - * valid in state %HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED, - * %HWCNT_JM_WD_IDLE_BUFFER_FULL or %HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL. - * @wd_enable_map: Watchdog backend internal buffer mask, initialized during dump_enable copying - * the enable_map passed as argument. - * @wd_dump_timestamp: Holds the dumping timestamp for potential future client dump_request, filled - * during watchdog timer dumps. - * @watchdog_complete: Used for synchronization between watchdog dumper thread and client calls. - * @locked: Members protected from concurrent access by different threads. - * @locked.watchdog_lock: Lock used to access fields within this struct (that require mutual - * exclusion). - * @locked.is_enabled: If true then the wrapped job manager hardware counter backend and the - * watchdog timer are both enabled. If false then both are disabled (or soon - * will be). Races between enable and disable have undefined behavior. - * @locked.state: State used to synchronize timer callbacks with the main thread. - */ -struct kbase_hwcnt_backend_jm_watchdog { - const struct kbase_hwcnt_backend_jm_watchdog_info *info; - struct kbase_hwcnt_backend *jm_backend; - u32 timeout_ms; - struct kbase_hwcnt_dump_buffer wd_dump_buffer; - struct kbase_hwcnt_enable_map wd_enable_map; - u64 wd_dump_timestamp; - struct completion watchdog_complete; - struct { - spinlock_t watchdog_lock; - bool is_enabled; - enum backend_watchdog_state state; - } locked; -}; - -/* timer's callback function */ -static void kbasep_hwcnt_backend_jm_watchdog_timer_callback(void *backend) -{ - struct kbase_hwcnt_backend_jm_watchdog *wd_backend = backend; - unsigned long flags; - bool wd_accumulate; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - if (!wd_backend->locked.is_enabled || wd_backend->locked.state == HWCNT_JM_WD_ERROR) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return; - } - - if (!(wd_backend->locked.state == HWCNT_JM_WD_IDLE_BUFFER_EMPTY || - wd_backend->locked.state == HWCNT_JM_WD_IDLE_BUFFER_FULL)) { - /*resetting the timer. Calling modify on a disabled timer enables it.*/ - wd_backend->info->dump_watchdog_iface->modify( - wd_backend->info->dump_watchdog_iface->timer, wd_backend->timeout_ms); - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return; - } - /*start performing the dump*/ - - /* if there has been a previous timeout use accumulating dump_get() - * otherwise use non-accumulating to overwrite buffer - */ - wd_accumulate = (wd_backend->locked.state == HWCNT_JM_WD_IDLE_BUFFER_FULL); - - wd_backend->locked.state = HWCNT_JM_WD_TIMER_DUMPING; - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - if (wd_backend->info->jm_backend_iface->dump_request(wd_backend->jm_backend) || - wd_backend->info->jm_backend_iface->dump_wait(wd_backend->jm_backend) || - wd_backend->info->jm_backend_iface->dump_get( - wd_backend->jm_backend, &wd_backend->wd_dump_buffer, &wd_backend->wd_enable_map, - wd_accumulate, &wd_backend->wd_dump_timestamp)) { - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - WARN_ON(wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING && - wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR && - wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED); - wd_backend->locked.state = HWCNT_JM_WD_ERROR; - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - /* Unblock user if it's waiting. */ - complete_all(&wd_backend->watchdog_complete); - return; - } - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - WARN_ON(wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING && - wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR && - wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED); - - if (wd_backend->locked.state == HWCNT_JM_WD_TIMER_DUMPING) { - /* If there is no user request/clear, transit to HWCNT_JM_WD_IDLE_BUFFER_FULL - * to indicate timer dump is done and the buffer is full. If state changed to - * HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED or - * HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR then user will transit the state - * machine to next state. - */ - wd_backend->locked.state = HWCNT_JM_WD_IDLE_BUFFER_FULL; - } - if (wd_backend->locked.state != HWCNT_JM_WD_ERROR && wd_backend->locked.is_enabled) { - /* reset the timer to schedule another callback. Calling modify on a - * disabled timer enables it. - */ - /*The spin lock needs to be held in case the client calls dump_enable*/ - wd_backend->info->dump_watchdog_iface->modify( - wd_backend->info->dump_watchdog_iface->timer, wd_backend->timeout_ms); - } - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - /* Unblock user if it's waiting. */ - complete_all(&wd_backend->watchdog_complete); -} - -/* helper methods, info structure creation and destruction*/ - -static struct kbase_hwcnt_backend_jm_watchdog_info * -kbasep_hwcnt_backend_jm_watchdog_info_create(struct kbase_hwcnt_backend_interface *backend_iface, - struct kbase_hwcnt_watchdog_interface *watchdog_iface, - u32 watchdog_timer_interval_ms) -{ - struct kbase_hwcnt_backend_jm_watchdog_info *const info = - kmalloc(sizeof(*info), GFP_KERNEL); - - if (!info) - return NULL; - - *info = (struct kbase_hwcnt_backend_jm_watchdog_info){ - .jm_backend_iface = backend_iface, - .dump_watchdog_iface = watchdog_iface, - .watchdog_timer_interval_ms = watchdog_timer_interval_ms - }; - - return info; -} - -/****** kbase_hwcnt_backend_interface implementation *******/ - -/* Job manager watchdog backend, implementation of kbase_hwcnt_backend_metadata_fn */ -static const struct kbase_hwcnt_metadata * -kbasep_hwcnt_backend_jm_watchdog_metadata(const struct kbase_hwcnt_backend_info *info) -{ - const struct kbase_hwcnt_backend_jm_watchdog_info *wd_info = (void *)info; - - if (WARN_ON(!info)) - return NULL; - - return wd_info->jm_backend_iface->metadata(wd_info->jm_backend_iface->info); -} - -static void -kbasep_hwcnt_backend_jm_watchdog_term_partial(struct kbase_hwcnt_backend_jm_watchdog *wd_backend, - enum wd_init_state state) -{ - if (!wd_backend) - return; - - WARN_ON(state > HWCNT_JM_WD_INIT_END); - - while (state-- > HWCNT_JM_WD_INIT_START) { - switch (state) { - case HWCNT_JM_WD_INIT_BACKEND: - wd_backend->info->jm_backend_iface->term(wd_backend->jm_backend); - break; - case HWCNT_JM_WD_INIT_ENABLE_MAP: - kbase_hwcnt_enable_map_free(&wd_backend->wd_enable_map); - break; - case HWCNT_JM_WD_INIT_DUMP_BUFFER: - kbase_hwcnt_dump_buffer_free(&wd_backend->wd_dump_buffer); - break; - case HWCNT_JM_WD_INIT_END: - break; - } - } - - kfree(wd_backend); -} - -static void kbasep_hwcnt_backend_jm_watchdog_acquire(const struct kbase_hwcnt_backend *backend) -{ -} - -static void kbasep_hwcnt_backend_jm_watchdog_release(const struct kbase_hwcnt_backend *backend) -{ -} - -/* Job manager watchdog backend, implementation of kbase_hwcnt_backend_term_fn - * Calling term does *not* destroy the interface - */ -static void kbasep_hwcnt_backend_jm_watchdog_term(struct kbase_hwcnt_backend *backend) -{ - struct kbase_hwcnt_backend_jm_watchdog *wd_backend = - (struct kbase_hwcnt_backend_jm_watchdog *)backend; - - if (!backend) - return; - - /* disable timer thread to avoid concurrent access to shared resources */ - wd_backend->info->dump_watchdog_iface->disable( - wd_backend->info->dump_watchdog_iface->timer); - - kbasep_hwcnt_backend_jm_watchdog_term_partial(wd_backend, HWCNT_JM_WD_INIT_END); -} - -/* Job manager watchdog backend, implementation of kbase_hwcnt_backend_init_fn */ -static int kbasep_hwcnt_backend_jm_watchdog_init(const struct kbase_hwcnt_backend_info *info, - struct kbase_hwcnt_backend **out_backend) -{ - int errcode = 0; - struct kbase_hwcnt_backend_jm_watchdog *wd_backend = NULL; - struct kbase_hwcnt_backend_jm_watchdog_info *const wd_info = (void *)info; - const struct kbase_hwcnt_backend_info *jm_info; - const struct kbase_hwcnt_metadata *metadata; - enum wd_init_state state = HWCNT_JM_WD_INIT_START; - - if (WARN_ON(!info) || WARN_ON(!out_backend)) - return -EINVAL; - - jm_info = wd_info->jm_backend_iface->info; - metadata = wd_info->jm_backend_iface->metadata(wd_info->jm_backend_iface->info); - - wd_backend = kmalloc(sizeof(*wd_backend), GFP_KERNEL); - if (!wd_backend) { - *out_backend = NULL; - return -ENOMEM; - } - - *wd_backend = (struct kbase_hwcnt_backend_jm_watchdog){ - .info = wd_info, - .timeout_ms = wd_info->watchdog_timer_interval_ms, - .locked = { .state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY, .is_enabled = false } - }; - - while (state < HWCNT_JM_WD_INIT_END && !errcode) { - switch (state) { - case HWCNT_JM_WD_INIT_BACKEND: - errcode = wd_info->jm_backend_iface->init(jm_info, &wd_backend->jm_backend); - break; - case HWCNT_JM_WD_INIT_ENABLE_MAP: - errcode = - kbase_hwcnt_enable_map_alloc(metadata, &wd_backend->wd_enable_map); - break; - case HWCNT_JM_WD_INIT_DUMP_BUFFER: - errcode = kbase_hwcnt_dump_buffer_alloc(metadata, - &wd_backend->wd_dump_buffer); - break; - case HWCNT_JM_WD_INIT_END: - break; - } - if (!errcode) - state++; - } - - if (errcode) { - kbasep_hwcnt_backend_jm_watchdog_term_partial(wd_backend, state); - *out_backend = NULL; - return errcode; - } - - WARN_ON(state != HWCNT_JM_WD_INIT_END); - - spin_lock_init(&wd_backend->locked.watchdog_lock); - init_completion(&wd_backend->watchdog_complete); - - *out_backend = (struct kbase_hwcnt_backend *)wd_backend; - return 0; -} - -/* Job manager watchdog backend, implementation of timestamp_ns */ -static u64 kbasep_hwcnt_backend_jm_watchdog_timestamp_ns(struct kbase_hwcnt_backend *backend) -{ - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - - return wd_backend->info->jm_backend_iface->timestamp_ns(wd_backend->jm_backend); -} - -static int kbasep_hwcnt_backend_jm_watchdog_dump_enable_common( - struct kbase_hwcnt_backend_jm_watchdog *wd_backend, - const struct kbase_hwcnt_enable_map *enable_map, kbase_hwcnt_backend_dump_enable_fn enabler) -{ - int errcode = -EPERM; - unsigned long flags; - - if (WARN_ON(!wd_backend) || WARN_ON(!enable_map)) - return -EINVAL; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - /* If the backend is already enabled return an error */ - if (wd_backend->locked.is_enabled) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return -EPERM; - } - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - /*We copy the enable map into our watchdog backend copy, for future usage*/ - kbase_hwcnt_enable_map_copy(&wd_backend->wd_enable_map, enable_map); - - errcode = enabler(wd_backend->jm_backend, enable_map); - if (!errcode) { - /*Enable dump watchdog*/ - errcode = wd_backend->info->dump_watchdog_iface->enable( - wd_backend->info->dump_watchdog_iface->timer, wd_backend->timeout_ms, - kbasep_hwcnt_backend_jm_watchdog_timer_callback, wd_backend); - if (!errcode) { - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - WARN_ON(wd_backend->locked.is_enabled); - wd_backend->locked.is_enabled = true; - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - } else - /*Reverting the job manager backend back to disabled*/ - wd_backend->info->jm_backend_iface->dump_disable(wd_backend->jm_backend, - NULL, NULL); - } - - return errcode; -} - -/* Job manager watchdog backend, implementation of dump_enable */ -static int -kbasep_hwcnt_backend_jm_watchdog_dump_enable(struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) -{ - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - - return kbasep_hwcnt_backend_jm_watchdog_dump_enable_common( - wd_backend, enable_map, wd_backend->info->jm_backend_iface->dump_enable); -} - -/* Job manager watchdog backend, implementation of dump_enable_nolock */ -static int -kbasep_hwcnt_backend_jm_watchdog_dump_enable_nolock(struct kbase_hwcnt_backend *backend, - const struct kbase_hwcnt_enable_map *enable_map) -{ - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - - return kbasep_hwcnt_backend_jm_watchdog_dump_enable_common( - wd_backend, enable_map, wd_backend->info->jm_backend_iface->dump_enable_nolock); -} - -/* Job manager watchdog backend, implementation of dump_disable */ -static void -kbasep_hwcnt_backend_jm_watchdog_dump_disable(struct kbase_hwcnt_backend *backend, - struct kbase_hwcnt_dump_buffer *dump_buffer, - const struct kbase_hwcnt_enable_map *buf_enable_map) -{ - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - unsigned long flags; - - if (WARN_ON(!backend)) - return; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - if (!wd_backend->locked.is_enabled) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return; - } - - wd_backend->locked.is_enabled = false; - - /* Discard undumped counter values since the last dump_get. */ - if (wd_backend->locked.state == HWCNT_JM_WD_IDLE_BUFFER_FULL) - wd_backend->locked.state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY; - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - wd_backend->info->dump_watchdog_iface->disable( - wd_backend->info->dump_watchdog_iface->timer); - - wd_backend->info->jm_backend_iface->dump_disable(wd_backend->jm_backend, dump_buffer, - buf_enable_map); -} - -/* Job manager watchdog backend, implementation of dump_clear */ -static int kbasep_hwcnt_backend_jm_watchdog_dump_clear(struct kbase_hwcnt_backend *backend) -{ - int errcode = -EPERM; - bool clear_wd_wait_completion = false; - unsigned long flags; - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - - if (WARN_ON(!backend)) - return -EINVAL; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - if (!wd_backend->locked.is_enabled) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return -EPERM; - } - - switch (wd_backend->locked.state) { - case HWCNT_JM_WD_IDLE_BUFFER_FULL: - case HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL: - case HWCNT_JM_WD_IDLE_BUFFER_EMPTY: - case HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY: - wd_backend->locked.state = HWCNT_JM_WD_BUFFER_CLEARING; - errcode = 0; - break; - case HWCNT_JM_WD_TIMER_DUMPING: - /* The timer asked for a dump request, when complete, the job manager backend - * buffer will be zero - */ - clear_wd_wait_completion = true; - /* This thread will have to wait for the callback to terminate and then call a - * dump_clear on the job manager backend. We change the state to - * HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR to notify the callback thread there is - * no more need to dump the buffer (since we will clear it right after anyway). - * We set up a wait queue to synchronize with the callback. - */ - reinit_completion(&wd_backend->watchdog_complete); - wd_backend->locked.state = HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR; - errcode = 0; - break; - default: - errcode = -EPERM; - break; - } - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - if (!errcode) { - if (clear_wd_wait_completion) { - /* Waiting for the callback to finish */ - wait_for_completion(&wd_backend->watchdog_complete); - } - - /* Clearing job manager backend buffer */ - errcode = wd_backend->info->jm_backend_iface->dump_clear(wd_backend->jm_backend); - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - WARN_ON(wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_CLEAR && - wd_backend->locked.state != HWCNT_JM_WD_BUFFER_CLEARING && - wd_backend->locked.state != HWCNT_JM_WD_ERROR); - - WARN_ON(!wd_backend->locked.is_enabled); - - if (!errcode && wd_backend->locked.state != HWCNT_JM_WD_ERROR) { - /* Setting the internal buffer state to EMPTY */ - wd_backend->locked.state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY; - /* Resetting the timer. Calling modify on a disabled timer - * enables it. - */ - wd_backend->info->dump_watchdog_iface->modify( - wd_backend->info->dump_watchdog_iface->timer, - wd_backend->timeout_ms); - } else { - wd_backend->locked.state = HWCNT_JM_WD_ERROR; - errcode = -EPERM; - } - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - } - - return errcode; -} - -/* Job manager watchdog backend, implementation of dump_request */ -static int kbasep_hwcnt_backend_jm_watchdog_dump_request(struct kbase_hwcnt_backend *backend) -{ - bool call_dump_request = false; - int errcode = 0; - unsigned long flags; - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - - if (WARN_ON(!backend)) - return -EINVAL; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - if (!wd_backend->locked.is_enabled) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return -EPERM; - } - - switch (wd_backend->locked.state) { - case HWCNT_JM_WD_IDLE_BUFFER_EMPTY: - /* progressing the state to avoid callbacks running while calling the job manager - * backend - */ - wd_backend->locked.state = HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY; - call_dump_request = true; - break; - case HWCNT_JM_WD_IDLE_BUFFER_FULL: - wd_backend->locked.state = HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL; - call_dump_request = true; - break; - case HWCNT_JM_WD_TIMER_DUMPING: - /* On the next client call (dump_wait) the thread will have to wait for the - * callback to finish the dumping. - * We set up a wait queue to synchronize with the callback. - */ - reinit_completion(&wd_backend->watchdog_complete); - wd_backend->locked.state = HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED; - break; - default: - errcode = -EPERM; - break; - } - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - if (call_dump_request) { - errcode = wd_backend->info->jm_backend_iface->dump_request(wd_backend->jm_backend); - if (!errcode) { - /*resetting the timer. Calling modify on a disabled timer enables it*/ - wd_backend->info->dump_watchdog_iface->modify( - wd_backend->info->dump_watchdog_iface->timer, - wd_backend->timeout_ms); - } else { - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - WARN_ON(!wd_backend->locked.is_enabled); - wd_backend->locked.state = HWCNT_JM_WD_ERROR; - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - } - } - - return errcode; -} - -/* Job manager watchdog backend, implementation of dump_wait */ -static int kbasep_hwcnt_backend_jm_watchdog_dump_wait(struct kbase_hwcnt_backend *backend) -{ - int errcode = -EPERM; - bool wait_for_auto_dump = false, wait_for_user_dump = false; - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - unsigned long flags; - - if (WARN_ON(!backend)) - return -EINVAL; - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - if (!wd_backend->locked.is_enabled) { - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - return -EPERM; - } - - switch (wd_backend->locked.state) { - case HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED: - wait_for_auto_dump = true; - errcode = 0; - break; - case HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY: - case HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL: - wait_for_user_dump = true; - errcode = 0; - break; - default: - errcode = -EPERM; - break; - } - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - if (wait_for_auto_dump) - wait_for_completion(&wd_backend->watchdog_complete); - else if (wait_for_user_dump) { - errcode = wd_backend->info->jm_backend_iface->dump_wait(wd_backend->jm_backend); - if (errcode) { - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - WARN_ON(!wd_backend->locked.is_enabled); - wd_backend->locked.state = HWCNT_JM_WD_ERROR; - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - } - } - - return errcode; -} - -/* Job manager watchdog backend, implementation of dump_get */ -static int kbasep_hwcnt_backend_jm_watchdog_dump_get( - struct kbase_hwcnt_backend *backend, struct kbase_hwcnt_dump_buffer *dump_buffer, - const struct kbase_hwcnt_enable_map *enable_map, bool accumulate, u64 *dump_time_ns) -{ - bool call_dump_get = false; - struct kbase_hwcnt_backend_jm_watchdog *const wd_backend = (void *)backend; - unsigned long flags; - int errcode = 0; - - if (WARN_ON(!backend) || WARN_ON(!dump_buffer) || WARN_ON(!enable_map) || - WARN_ON(!dump_time_ns)) - return -EINVAL; - - /* The resultant contents of the dump buffer are only well defined if a prior - * call to dump_wait returned successfully, and a new dump has not yet been - * requested by a call to dump_request. - */ - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - switch (wd_backend->locked.state) { - case HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED: - /*we assume dump_wait has been called and completed successfully*/ - if (accumulate) - kbase_hwcnt_dump_buffer_accumulate(dump_buffer, &wd_backend->wd_dump_buffer, - enable_map); - else - kbase_hwcnt_dump_buffer_copy(dump_buffer, &wd_backend->wd_dump_buffer, - enable_map); - - /*use state to indicate the the buffer is now empty*/ - wd_backend->locked.state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY; - /* Retrieve timing information from previous dump_request */ - *dump_time_ns = wd_backend->wd_dump_timestamp; - break; - case HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL: - /*accumulate or copy watchdog data to user buffer first so that dump_get can set - * the header correctly - */ - if (accumulate) - kbase_hwcnt_dump_buffer_accumulate(dump_buffer, &wd_backend->wd_dump_buffer, - enable_map); - else - kbase_hwcnt_dump_buffer_copy(dump_buffer, &wd_backend->wd_dump_buffer, - enable_map); - - /*accumulate backend data into user buffer on top of watchdog data*/ - accumulate = true; - call_dump_get = true; - break; - case HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY: - call_dump_get = true; - break; - default: - errcode = -EPERM; - break; - } - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - - if (call_dump_get && !errcode) { - /*we just dump the job manager backend into the user buffer, following - *accumulate flag - */ - errcode = wd_backend->info->jm_backend_iface->dump_get( - wd_backend->jm_backend, dump_buffer, enable_map, accumulate, dump_time_ns); - - spin_lock_irqsave(&wd_backend->locked.watchdog_lock, flags); - - WARN_ON(wd_backend->locked.state != HWCNT_JM_WD_USER_DUMPING_BUFFER_EMPTY && - wd_backend->locked.state != HWCNT_JM_WD_USER_DUMPING_BUFFER_FULL && - wd_backend->locked.state != HWCNT_JM_WD_TIMER_DUMPING_USER_REQUESTED); - - if (!errcode) - wd_backend->locked.state = HWCNT_JM_WD_IDLE_BUFFER_EMPTY; - else - wd_backend->locked.state = HWCNT_JM_WD_ERROR; - - spin_unlock_irqrestore(&wd_backend->locked.watchdog_lock, flags); - } - - return errcode; -} - -/* exposed methods */ - -int kbase_hwcnt_backend_jm_watchdog_create(struct kbase_hwcnt_backend_interface *backend_iface, - struct kbase_hwcnt_watchdog_interface *watchdog_iface, - struct kbase_hwcnt_backend_interface *out_iface, - u32 watchdog_timer_interval_ms) -{ - struct kbase_hwcnt_backend_jm_watchdog_info *info = NULL; - - if (WARN_ON(!backend_iface) || WARN_ON(!watchdog_iface) || WARN_ON(!out_iface)) - return -EINVAL; - - info = kbasep_hwcnt_backend_jm_watchdog_info_create(backend_iface, watchdog_iface, - watchdog_timer_interval_ms); - if (!info) - return -ENOMEM; - - /*linking the info table with the output iface, to allow the callbacks below to access the - *info object later on - */ - *out_iface = (struct kbase_hwcnt_backend_interface){ - .info = (void *)info, - .metadata = kbasep_hwcnt_backend_jm_watchdog_metadata, - .init = kbasep_hwcnt_backend_jm_watchdog_init, - .term = kbasep_hwcnt_backend_jm_watchdog_term, - .acquire = kbasep_hwcnt_backend_jm_watchdog_acquire, - .release = kbasep_hwcnt_backend_jm_watchdog_release, - .timestamp_ns = kbasep_hwcnt_backend_jm_watchdog_timestamp_ns, - .dump_enable = kbasep_hwcnt_backend_jm_watchdog_dump_enable, - .dump_enable_nolock = kbasep_hwcnt_backend_jm_watchdog_dump_enable_nolock, - .dump_disable = kbasep_hwcnt_backend_jm_watchdog_dump_disable, - .dump_clear = kbasep_hwcnt_backend_jm_watchdog_dump_clear, - .dump_request = kbasep_hwcnt_backend_jm_watchdog_dump_request, - .dump_wait = kbasep_hwcnt_backend_jm_watchdog_dump_wait, - .dump_get = kbasep_hwcnt_backend_jm_watchdog_dump_get - }; - - /*registering watchdog backend module methods on the output interface*/ - - return 0; -} - -void kbase_hwcnt_backend_jm_watchdog_destroy(struct kbase_hwcnt_backend_interface *iface) -{ - if (!iface || !iface->info) - return; - - kfree((struct kbase_hwcnt_backend_jm_watchdog_info *)iface->info); - - /*blanking the watchdog backend interface*/ - memset(iface, 0, sizeof(*iface)); -} diff --git a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h b/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h deleted file mode 100644 index d5ce27685186..000000000000 --- a/drivers/gpu/arm/valhall/hwcnt/backend/mali_kbase_hwcnt_backend_jm_watchdog.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Concrete implementation of mali_kbase_hwcnt_backend interface for job manager - * backend. This module functionally interleaves between the hardware counter - * (hwcnt_accumulator) module (the interface consumer) and the job manager - * backend module (hwcnt_backend_jm). This module provides buffering - * functionality for the dumping requests requested by the hwcnt_accumulator - * consumer. This module is NOT multi-thread safe. The programmer must - * ensure the exposed methods are called by at most one thread at any time. - */ - -#ifndef _KBASE_HWCNT_BACKEND_JM_WATCHDOG_H_ -#define _KBASE_HWCNT_BACKEND_JM_WATCHDOG_H_ - -#include -#include - -/** - * kbase_hwcnt_backend_jm_watchdog_create() - Create a job manager hardware counter watchdog - * backend interface. - * @backend_iface: Non-NULL pointer to the backend interface structure that this module will - * extend. - * @watchdog_iface: Non-NULL pointer to an hardware counter watchdog interface. - * @out_iface: Non-NULL pointer to backend interface structure that is filled in - * on creation success. - * @watchdog_timer_interval_ms: Interval in milliseconds between hwcnt samples. - * - * Calls to out_iface->dump_enable_nolock() require kbdev->hwaccess_lock held. - * - * Return: 0 on success, error otherwise. - */ -int kbase_hwcnt_backend_jm_watchdog_create(struct kbase_hwcnt_backend_interface *backend_iface, - struct kbase_hwcnt_watchdog_interface *watchdog_iface, - struct kbase_hwcnt_backend_interface *out_iface, - u32 watchdog_timer_interval_ms); - -/** - * kbase_hwcnt_backend_jm_watchdog_destroy() - Destroy a job manager hardware counter watchdog - * backend interface. - * @iface: Pointer to interface to destroy. - * - * Can be safely called on an all-zeroed interface, or on an already destroyed - * interface. - */ -void kbase_hwcnt_backend_jm_watchdog_destroy(struct kbase_hwcnt_backend_interface *iface); - -#endif /* _KBASE_HWCNT_BACKEND_JM_WATCHDOG_H_ */ diff --git a/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if.h b/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if.h index 501c0087b7e6..f8b12c12a4ef 100644 --- a/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if.h +++ b/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -33,6 +33,15 @@ */ struct kbase_hwcnt_watchdog_info; +/* + * Enum describing different types of watchdog disable calls. + */ +enum kbase_hwcnt_watchdog_disable_type { + KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_BLOCK, + KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_NOT_BLOCK, + KBASE_HWCNT_WATCHDOG_DISABLE_TYPE_CNT +}; + /** * typedef kbase_hwcnt_watchdog_callback_fn - Callback function when watchdog timer is done * @@ -59,8 +68,10 @@ typedef int kbase_hwcnt_watchdog_enable_fn(const struct kbase_hwcnt_watchdog_inf * typedef kbase_hwcnt_watchdog_disable_fn - Disable watchdog timer * * @timer: Non-NULL pointer to a watchdog timer interface context + * @type: Disable type to use */ -typedef void kbase_hwcnt_watchdog_disable_fn(const struct kbase_hwcnt_watchdog_info *timer); +typedef void kbase_hwcnt_watchdog_disable_fn(const struct kbase_hwcnt_watchdog_info *timer, + enum kbase_hwcnt_watchdog_disable_type type); /** * typedef kbase_hwcnt_watchdog_modify_fn - Modify watchdog timer's timeout diff --git a/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c b/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c index 4caa832cd587..eae1cf6c0aae 100644 --- a/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c +++ b/drivers/gpu/arm/valhall/hwcnt/mali_kbase_hwcnt_watchdog_if_timer.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2021-2022 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2021-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -57,7 +57,8 @@ static void kbasep_hwcnt_watchdog_callback(struct work_struct *const work) struct kbase_hwcnt_watchdog_if_timer_info *const info = container_of(work, struct kbase_hwcnt_watchdog_if_timer_info, dwork.work); - if (info->callback) + /* Issue the callback only if timer is enabled. */ + if (info->callback && info->timer_enabled) info->callback(info->user_data); } @@ -80,7 +81,8 @@ static int kbasep_hwcnt_watchdog_if_timer_enable( } static void -kbasep_hwcnt_watchdog_if_timer_disable(const struct kbase_hwcnt_watchdog_info *const timer) +kbasep_hwcnt_watchdog_if_timer_disable(const struct kbase_hwcnt_watchdog_info *const timer, + enum kbase_hwcnt_watchdog_disable_type type) { struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = (void *)timer; @@ -90,7 +92,16 @@ kbasep_hwcnt_watchdog_if_timer_disable(const struct kbase_hwcnt_watchdog_info *c if (!timer_info->timer_enabled) return; - cancel_delayed_work_sync(&timer_info->dwork); + /* Cancel any pending work. + * Use a blocking call if the caller can afford to wait. + * In an opposite case (KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_NOT_BLOCK), + * timer callback will be effectively canceled by setting timer_enabled to false. + * This will prevent the timer callback from being issued and from rescheduling + * itself. + */ + if (type == KBASE_HWCNT_WATCHDOG_DISABLE_SHOULD_BLOCK) + cancel_delayed_work_sync(&timer_info->dwork); + timer_info->timer_enabled = false; } @@ -100,7 +111,7 @@ kbasep_hwcnt_watchdog_if_timer_modify(const struct kbase_hwcnt_watchdog_info *co { struct kbase_hwcnt_watchdog_if_timer_info *const timer_info = (void *)timer; - if (WARN_ON(!timer) || WARN_ON(!timer_info->timer_enabled)) + if (WARN_ON(!timer) || !timer_info->timer_enabled) return; mod_delayed_work(timer_info->workq, &timer_info->dwork, msecs_to_jiffies(delay_ms)); @@ -118,6 +129,7 @@ void kbase_hwcnt_watchdog_if_timer_destroy(struct kbase_hwcnt_watchdog_interface if (WARN_ON(!timer_info)) return; + cancel_delayed_work_sync(&timer_info->dwork); destroy_workqueue(timer_info->workq); kfree(timer_info); diff --git a/drivers/gpu/arm/valhall/ipa/Kbuild b/drivers/gpu/arm/valhall/ipa/Kbuild index 9d8a79d8dc29..968157446956 100644 --- a/drivers/gpu/arm/valhall/ipa/Kbuild +++ b/drivers/gpu/arm/valhall/ipa/Kbuild @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note # -# (C) COPYRIGHT 2016-2018, 2020-2021 ARM Limited. All rights reserved. +# (C) COPYRIGHT 2016-2018, 2020-2021, 2024 ARM Limited. All rights reserved. # # This program is free software and is provided to you under the terms of the # GNU General Public License version 2 as published by the Free Software @@ -20,16 +20,8 @@ valhall_kbase-y += \ ipa/mali_kbase_ipa_simple.o \ - ipa/mali_kbase_ipa.o + ipa/mali_kbase_ipa.o \ + ipa/backend/mali_kbase_ipa_counter_csf.o \ + ipa/backend/mali_kbase_ipa_counter_common_csf.o valhall_kbase-$(CONFIG_DEBUG_FS) += ipa/mali_kbase_ipa_debugfs.o - -ifeq ($(MALI_USE_CSF),1) - valhall_kbase-y += \ - ipa/backend/mali_kbase_ipa_counter_csf.o \ - ipa/backend/mali_kbase_ipa_counter_common_csf.o -else - valhall_kbase-y += \ - ipa/backend/mali_kbase_ipa_counter_jm.o \ - ipa/backend/mali_kbase_ipa_counter_common_jm.o -endif diff --git a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.c b/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.c deleted file mode 100644 index a716e15b3df3..000000000000 --- a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.c +++ /dev/null @@ -1,339 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include "mali_kbase_ipa_counter_common_jm.h" -#include "ipa/mali_kbase_ipa_debugfs.h" - -#define DEFAULT_SCALING_FACTOR 5 - -/* If the value of GPU_ACTIVE is below this, use the simple model - * instead, to avoid extrapolating small amounts of counter data across - * large sample periods. - */ -#define DEFAULT_MIN_SAMPLE_CYCLES 10000 - -/** - * kbase_ipa_read_hwcnt() - read a counter value - * @model_data: pointer to model data - * @offset: offset, in bytes, into vinstr buffer - * - * Return: A 32-bit counter value. Range: 0 < value < 2^27 (worst case would be - * incrementing every cycle over a ~100ms sample period at a high frequency, - * e.g. 1 GHz: 2^30 * 0.1seconds ~= 2^27. - */ -static inline u32 kbase_ipa_read_hwcnt(struct kbase_ipa_model_vinstr_data *model_data, u32 offset) -{ - u8 *p = (u8 *)model_data->dump_buf.dump_buf; - u64 val = *(u64 *)&p[offset]; - - return (val > U32_MAX) ? U32_MAX : (u32)val; -} - -static inline s64 kbase_ipa_add_saturate(s64 a, s64 b) -{ - s64 rtn; - - if (a > 0 && (S64_MAX - a) < b) - rtn = S64_MAX; - else if (a < 0 && (S64_MIN - a) > b) - rtn = S64_MIN; - else - rtn = a + b; - - return rtn; -} - -s64 kbase_ipa_sum_all_shader_cores(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter) -{ - struct kbase_device *kbdev = model_data->kbdev; - u64 core_mask; - u32 base = 0; - s64 ret = 0; - - core_mask = kbdev->gpu_props.coherency_info.group.core_mask; - while (core_mask != 0ull) { - if ((core_mask & 1ull) != 0ull) { - /* 0 < counter_value < 2^27 */ - u32 counter_value = kbase_ipa_read_hwcnt(model_data, base + counter); - - /* 0 < ret < 2^27 * max_num_cores = 2^32 */ - ret = kbase_ipa_add_saturate(ret, counter_value); - } - base += KBASE_IPA_NR_BYTES_PER_BLOCK; - core_mask >>= 1; - } - - /* Range: -2^54 < ret * coeff < 2^54 */ - return ret * coeff; -} - -s64 kbase_ipa_sum_all_memsys_blocks(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter) -{ - struct kbase_device *kbdev = model_data->kbdev; - const u32 num_blocks = kbdev->gpu_props.num_l2_slices; - u32 base = 0; - s64 ret = 0; - u32 i; - - for (i = 0; i < num_blocks; i++) { - /* 0 < counter_value < 2^27 */ - u32 counter_value = kbase_ipa_read_hwcnt(model_data, base + counter); - - /* 0 < ret < 2^27 * max_num_memsys_blocks = 2^29 */ - ret = kbase_ipa_add_saturate(ret, counter_value); - base += KBASE_IPA_NR_BYTES_PER_BLOCK; - } - - /* Range: -2^51 < ret * coeff < 2^51 */ - return ret * coeff; -} - -s64 kbase_ipa_single_counter(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, u32 counter) -{ - /* Range: 0 < counter_value < 2^27 */ - const u32 counter_value = kbase_ipa_read_hwcnt(model_data, counter); - - /* Range: -2^49 < ret < 2^49 */ - return counter_value * (s64)coeff; -} - -int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data) -{ - int errcode; - struct kbase_device *kbdev = model_data->kbdev; - struct kbase_hwcnt_virtualizer *hvirt = kbdev->hwcnt_gpu_virt; - struct kbase_hwcnt_enable_map enable_map; - const struct kbase_hwcnt_metadata *metadata = kbase_hwcnt_virtualizer_metadata(hvirt); - - if (!metadata) - return -1; - - errcode = kbase_hwcnt_enable_map_alloc(metadata, &enable_map); - if (errcode) { - dev_err(kbdev->dev, "Failed to allocate IPA enable map"); - return errcode; - } - - kbase_hwcnt_enable_map_enable_all(&enable_map); - - /* Disable cycle counter only. */ - enable_map.clk_enable_map = 0; - - errcode = kbase_hwcnt_virtualizer_client_create(hvirt, &enable_map, &model_data->hvirt_cli); - kbase_hwcnt_enable_map_free(&enable_map); - if (errcode) { - dev_err(kbdev->dev, "Failed to register IPA with virtualizer"); - model_data->hvirt_cli = NULL; - return errcode; - } - - errcode = kbase_hwcnt_dump_buffer_alloc(metadata, &model_data->dump_buf); - if (errcode) { - dev_err(kbdev->dev, "Failed to allocate IPA dump buffer"); - kbase_hwcnt_virtualizer_client_destroy(model_data->hvirt_cli); - model_data->hvirt_cli = NULL; - return errcode; - } - - return 0; -} - -void kbase_ipa_detach_vinstr(struct kbase_ipa_model_vinstr_data *model_data) -{ - if (model_data->hvirt_cli) { - kbase_hwcnt_virtualizer_client_destroy(model_data->hvirt_cli); - kbase_hwcnt_dump_buffer_free(&model_data->dump_buf); - model_data->hvirt_cli = NULL; - } -} - -int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp) -{ - struct kbase_ipa_model_vinstr_data *model_data = - (struct kbase_ipa_model_vinstr_data *)model->model_data; - s64 energy = 0; - size_t i; - u64 coeff = 0, coeff_mul = 0; - u64 start_ts_ns, end_ts_ns; - u32 active_cycles; - int err = 0; - - err = kbase_hwcnt_virtualizer_client_dump(model_data->hvirt_cli, &start_ts_ns, &end_ts_ns, - &model_data->dump_buf); - if (err) - goto err0; - - /* Range: 0 (GPU not used at all), to the max sampling interval, say - * 1s, * max GPU frequency (GPU 100% utilized). - * 0 <= active_cycles <= 1 * ~2GHz - * 0 <= active_cycles < 2^31 - */ - active_cycles = model_data->get_active_cycles(model_data); - - if (active_cycles < (u32)max(model_data->min_sample_cycles, 0)) { - err = -ENODATA; - goto err0; - } - - /* Range: 1 <= active_cycles < 2^31 */ - active_cycles = max(1u, active_cycles); - - /* Range of 'energy' is +/- 2^54 * number of IPA groups (~8), so around - * -2^57 < energy < 2^57 - */ - for (i = 0; i < model_data->groups_def_num; i++) { - const struct kbase_ipa_group *group = &model_data->groups_def[i]; - s32 coeff = model_data->group_values[i]; - s64 group_energy = group->op(model_data, coeff, group->counter_block_offset); - - energy = kbase_ipa_add_saturate(energy, group_energy); - } - - /* Range: 0 <= coeff < 2^57 */ - if (energy > 0) - coeff = (u64)energy; - - /* Range: 0 <= coeff < 2^57 (because active_cycles >= 1). However, this - * can be constrained further: Counter values can only be increased by - * a theoretical maximum of about 64k per clock cycle. Beyond this, - * we'd have to sample every 1ms to avoid them overflowing at the - * lowest clock frequency (say 100MHz). Therefore, we can write the - * range of 'coeff' in terms of active_cycles: - * - * coeff = SUM(coeffN * counterN * num_cores_for_counterN) - * coeff <= SUM(coeffN * counterN) * max_num_cores - * coeff <= num_IPA_groups * max_coeff * max_counter * max_num_cores - * (substitute max_counter = 2^16 * active_cycles) - * coeff <= num_IPA_groups * max_coeff * 2^16 * active_cycles * max_num_cores - * coeff <= 2^3 * 2^22 * 2^16 * active_cycles * 2^5 - * coeff <= 2^46 * active_cycles - * - * So after the division: 0 <= coeff <= 2^46 - */ - coeff = div_u64(coeff, active_cycles); - - /* Not all models were derived at the same reference voltage. Voltage - * scaling is done by multiplying by V^2, so we need to *divide* by - * Vref^2 here. - * Range: 0 <= coeff <= 2^49 - */ - coeff = div_u64(coeff * 1000, max(model_data->reference_voltage, 1)); - /* Range: 0 <= coeff <= 2^52 */ - coeff = div_u64(coeff * 1000, max(model_data->reference_voltage, 1)); - - /* Scale by user-specified integer factor. - * Range: 0 <= coeff_mul < 2^57 - */ - coeff_mul = coeff * (u64)model_data->scaling_factor; - - /* The power models have results with units - * mW/(MHz V^2), i.e. nW/(Hz V^2). With precision of 1/1000000, this - * becomes fW/(Hz V^2), which are the units of coeff_mul. However, - * kbase_scale_dynamic_power() expects units of pW/(Hz V^2), so divide - * by 1000. - * Range: 0 <= coeff_mul < 2^47 - */ - coeff_mul = div_u64(coeff_mul, 1000u); - -err0: - /* Clamp to a sensible range - 2^16 gives about 14W at 400MHz/750mV */ - *coeffp = clamp(coeff_mul, (u64)0, (u64)1 << 16); - return err; -} - -void kbase_ipa_vinstr_reset_data(struct kbase_ipa_model *model) -{ - CSTD_UNUSED(model); - /* Currently not implemented */ - WARN_ON_ONCE(1); -} - -int kbase_ipa_vinstr_common_model_init(struct kbase_ipa_model *model, - const struct kbase_ipa_group *ipa_groups_def, - size_t ipa_group_size, - kbase_ipa_get_active_cycles_callback get_active_cycles, - s32 reference_voltage) -{ - int err = 0; - size_t i; - struct kbase_ipa_model_vinstr_data *model_data; - - if (!model || !ipa_groups_def || !ipa_group_size || !get_active_cycles) - return -EINVAL; - - model_data = kzalloc(sizeof(*model_data), GFP_KERNEL); - if (!model_data) - return -ENOMEM; - - model_data->kbdev = model->kbdev; - model_data->groups_def = ipa_groups_def; - model_data->groups_def_num = ipa_group_size; - model_data->get_active_cycles = get_active_cycles; - - model->model_data = (void *)model_data; - - for (i = 0; i < model_data->groups_def_num; ++i) { - const struct kbase_ipa_group *group = &model_data->groups_def[i]; - - model_data->group_values[i] = group->default_value; - err = kbase_ipa_model_add_param_s32(model, group->name, - &model_data->group_values[i], 1, false); - if (err) - goto exit; - } - - model_data->scaling_factor = DEFAULT_SCALING_FACTOR; - err = kbase_ipa_model_add_param_s32(model, "scale", &model_data->scaling_factor, 1, false); - if (err) - goto exit; - - model_data->min_sample_cycles = DEFAULT_MIN_SAMPLE_CYCLES; - err = kbase_ipa_model_add_param_s32(model, "min_sample_cycles", - &model_data->min_sample_cycles, 1, false); - if (err) - goto exit; - - model_data->reference_voltage = reference_voltage; - err = kbase_ipa_model_add_param_s32(model, "reference_voltage", - &model_data->reference_voltage, 1, false); - if (err) - goto exit; - - err = kbase_ipa_attach_vinstr(model_data); - -exit: - if (err) { - kbase_ipa_model_param_free_all(model); - kfree(model_data); - } - return err; -} - -void kbase_ipa_vinstr_common_model_term(struct kbase_ipa_model *model) -{ - struct kbase_ipa_model_vinstr_data *model_data = - (struct kbase_ipa_model_vinstr_data *)model->model_data; - - kbase_ipa_detach_vinstr(model_data); - kfree(model_data); -} diff --git a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.h b/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.h deleted file mode 100644 index d1d1f7d3b57f..000000000000 --- a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_common_jm.h +++ /dev/null @@ -1,227 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_IPA_COUNTER_COMMON_JM_H_ -#define _KBASE_IPA_COUNTER_COMMON_JM_H_ - -#include "mali_kbase.h" -#include "hwcnt/mali_kbase_hwcnt_virtualizer.h" -#include "hwcnt/mali_kbase_hwcnt_types.h" - -/* Maximum number of IPA groups for an IPA model. */ -#define KBASE_IPA_MAX_GROUP_DEF_NUM 16 - -/* Number of bytes per hardware counter in a vinstr_buffer. */ -#define KBASE_IPA_NR_BYTES_PER_CNT (sizeof(u64)) - -/* Number of hardware counters per block in a vinstr_buffer. */ -#define KBASE_IPA_NR_CNT_PER_BLOCK 64 - -/* Number of bytes per block in a vinstr_buffer. */ -#define KBASE_IPA_NR_BYTES_PER_BLOCK (KBASE_IPA_NR_CNT_PER_BLOCK * KBASE_IPA_NR_BYTES_PER_CNT) - -struct kbase_ipa_model_vinstr_data; - -typedef u32 kbase_ipa_get_active_cycles_callback(struct kbase_ipa_model_vinstr_data *); - -/** - * struct kbase_ipa_model_vinstr_data - IPA context per device - * @kbdev: pointer to kbase device - * @group_values: values of coefficients for IPA groups - * @groups_def: Array of IPA groups. - * @groups_def_num: Number of elements in the array of IPA groups. - * @get_active_cycles: Callback to return number of active cycles during - * counter sample period - * @hvirt_cli: hardware counter virtualizer client handle - * @dump_buf: buffer to dump hardware counters onto - * @reference_voltage: voltage, in mV, of the operating point used when - * deriving the power model coefficients. Range approx - * 0.1V - 5V (~= 8V): 2^7 <= reference_voltage <= 2^13 - * @scaling_factor: User-specified power scaling factor. This is an - * integer, which is multiplied by the power coefficient - * just before OPP scaling. - * Range approx 0-32: 0 < scaling_factor < 2^5 - * @min_sample_cycles: If the value of the GPU_ACTIVE counter (the number of - * cycles the GPU was working) is less than - * min_sample_cycles, the counter model will return an - * error, causing the IPA framework to approximate using - * the cached simple model results instead. This may be - * more accurate than extrapolating using a very small - * counter dump. - */ -struct kbase_ipa_model_vinstr_data { - struct kbase_device *kbdev; - s32 group_values[KBASE_IPA_MAX_GROUP_DEF_NUM]; - const struct kbase_ipa_group *groups_def; - size_t groups_def_num; - kbase_ipa_get_active_cycles_callback *get_active_cycles; - struct kbase_hwcnt_virtualizer_client *hvirt_cli; - struct kbase_hwcnt_dump_buffer dump_buf; - s32 reference_voltage; - s32 scaling_factor; - s32 min_sample_cycles; -}; - -/** - * struct kbase_ipa_group - represents a single IPA group - * @name: name of the IPA group - * @default_value: default value of coefficient for IPA group. - * Coefficients are interpreted as fractions where the - * denominator is 1000000. - * @op: which operation to be performed on the counter values - * @counter_block_offset: block offset in bytes of the counter used to calculate energy for IPA group - */ -struct kbase_ipa_group { - const char *name; - s32 default_value; - s64 (*op)(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter_block_offset); - u32 counter_block_offset; -}; - -/** - * kbase_ipa_sum_all_shader_cores() - sum a counter over all cores - * @model_data: pointer to model data - * @coeff: model coefficient. Unity is ~2^20, so range approx - * +/- 4.0: -2^22 < coeff < 2^22 - * @counter: offset in bytes of the counter used to calculate energy - * for IPA group - * - * Calculate energy estimation based on hardware counter `counter' - * across all shader cores. - * - * Return: Sum of counter values. Range: -2^54 < ret < 2^54 - */ -s64 kbase_ipa_sum_all_shader_cores(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter); - -/** - * kbase_ipa_sum_all_memsys_blocks() - sum a counter over all mem system blocks - * @model_data: pointer to model data - * @coeff: model coefficient. Unity is ~2^20, so range approx - * +/- 4.0: -2^22 < coeff < 2^22 - * @counter: offset in bytes of the counter used to calculate energy - * for IPA group - * - * Calculate energy estimation based on hardware counter `counter' across all - * memory system blocks. - * - * Return: Sum of counter values. Range: -2^51 < ret < 2^51 - */ -s64 kbase_ipa_sum_all_memsys_blocks(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter); - -/** - * kbase_ipa_single_counter() - sum a single counter - * @model_data: pointer to model data - * @coeff: model coefficient. Unity is ~2^20, so range approx - * +/- 4.0: -2^22 < coeff < 2^22 - * @counter: offset in bytes of the counter used to calculate energy - * for IPA group - * - * Calculate energy estimation based on hardware counter `counter'. - * - * Return: Counter value. Range: -2^49 < ret < 2^49 - */ -s64 kbase_ipa_single_counter(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter); - -/** - * kbase_ipa_attach_vinstr() - attach a vinstr_buffer to an IPA model. - * @model_data: pointer to model data - * - * Attach a vinstr_buffer to an IPA model. The vinstr_buffer - * allows access to the hardware counters used to calculate - * energy consumption. - * - * Return: 0 on success, or an error code. - */ -int kbase_ipa_attach_vinstr(struct kbase_ipa_model_vinstr_data *model_data); - -/** - * kbase_ipa_detach_vinstr() - detach a vinstr_buffer from an IPA model. - * @model_data: pointer to model data - * - * Detach a vinstr_buffer from an IPA model. - */ -void kbase_ipa_detach_vinstr(struct kbase_ipa_model_vinstr_data *model_data); - -/** - * kbase_ipa_vinstr_dynamic_coeff() - calculate dynamic power based on HW counters - * @model: pointer to instantiated model - * @coeffp: pointer to location where calculated power, in - * pW/(Hz V^2), is stored. - * - * This is a GPU-agnostic implementation of the get_dynamic_coeff() - * function of an IPA model. It relies on the model being populated - * with GPU-specific attributes at initialization time. - * - * Return: 0 on success, or an error code. - */ -int kbase_ipa_vinstr_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp); - -/** - * kbase_ipa_vinstr_reset_data() - Reset the counters data used for dynamic - * power estimation - * @model: pointer to instantiated model - * - * Currently it is not implemented for JM GPUs. - * When implemented it is expected to retrieve the accumulated value of HW - * counters from the Vinstr component, without doing any processing, which is - * effectively a reset as the next call to kbase_ipa_counter_dynamic_coeff() - * will see the increment in counter values from this point onwards. - */ -void kbase_ipa_vinstr_reset_data(struct kbase_ipa_model *model); - -/** - * kbase_ipa_vinstr_common_model_init() - initialize ipa power model - * @model: ipa power model to initialize - * @ipa_groups_def: array of ipa groups which sets coefficients for - * the corresponding counters used in the ipa model - * @ipa_group_size: number of elements in the array @ipa_groups_def - * @get_active_cycles: callback to return the number of cycles the GPU was - * active during the counter sample period. - * @reference_voltage: voltage, in mV, of the operating point used when - * deriving the power model coefficients. - * - * This initialization function performs initialization steps common - * for ipa models based on counter values. In each call, the model - * passes its specific coefficient values per ipa counter group via - * @ipa_groups_def array. - * - * Return: 0 on success, error code otherwise - */ -int kbase_ipa_vinstr_common_model_init(struct kbase_ipa_model *model, - const struct kbase_ipa_group *ipa_groups_def, - size_t ipa_group_size, - kbase_ipa_get_active_cycles_callback *get_active_cycles, - s32 reference_voltage); - -/** - * kbase_ipa_vinstr_common_model_term() - terminate ipa power model - * @model: ipa power model to terminate - * - * This function performs all necessary steps to terminate ipa power model - * including clean up of resources allocated to hold model data. - */ -void kbase_ipa_vinstr_common_model_term(struct kbase_ipa_model *model); - -#endif /* _KBASE_IPA_COUNTER_COMMON_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_jm.c b/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_jm.c deleted file mode 100644 index b19608a71b54..000000000000 --- a/drivers/gpu/arm/valhall/ipa/backend/mali_kbase_ipa_counter_jm.c +++ /dev/null @@ -1,536 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2016-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include - -#include "mali_kbase_ipa_counter_common_jm.h" -#include "mali_kbase.h" -#include - -/* Performance counter blocks base offsets */ -#define JM_BASE (0 * KBASE_IPA_NR_BYTES_PER_BLOCK) -#define MEMSYS_BASE (2 * KBASE_IPA_NR_BYTES_PER_BLOCK) - -/* JM counter block offsets */ -#define JM_GPU_ACTIVE (KBASE_IPA_NR_BYTES_PER_CNT * 6) - -/* MEMSYS counter block offsets */ -#define MEMSYS_L2_ANY_LOOKUP (KBASE_IPA_NR_BYTES_PER_CNT * 25) - -/* SC counter block offsets */ -#define SC_EXEC_INSTR_FMA (KBASE_IPA_NR_BYTES_PER_CNT * 27) -#define SC_EXEC_INSTR_COUNT (KBASE_IPA_NR_BYTES_PER_CNT * 28) -#define SC_EXEC_INSTR_MSG (KBASE_IPA_NR_BYTES_PER_CNT * 30) -#define SC_TEX_FILT_NUM_OPERATIONS (KBASE_IPA_NR_BYTES_PER_CNT * 39) -#define SC_TEX_COORD_ISSUE (KBASE_IPA_NR_BYTES_PER_CNT * 40) -#define SC_TEX_TFCH_NUM_OPERATIONS (KBASE_IPA_NR_BYTES_PER_CNT * 42) -#define SC_VARY_INSTR (KBASE_IPA_NR_BYTES_PER_CNT * 49) -#define SC_BEATS_WR_TIB (KBASE_IPA_NR_BYTES_PER_CNT * 62) - -/** - * kbase_g7x_power_model_get_jm_counter() - get performance counter offset - * inside the Job Manager block - * @model_data: pointer to GPU model data. - * @counter_block_offset: offset in bytes of the performance counter inside - * the Job Manager block. - * - * Return: Block offset in bytes of the required performance counter. - */ -static u32 kbase_g7x_power_model_get_jm_counter(struct kbase_ipa_model_vinstr_data *model_data, - u32 counter_block_offset) -{ - CSTD_UNUSED(model_data); - return JM_BASE + counter_block_offset; -} - -/** - * kbase_g7x_power_model_get_memsys_counter() - get performance counter offset - * inside the Memory System block - * @model_data: pointer to GPU model data. - * @counter_block_offset: offset in bytes of the performance counter inside - * the (first) Memory System block. - * - * Return: Block offset in bytes of the required performance counter. - */ -static u32 kbase_g7x_power_model_get_memsys_counter(struct kbase_ipa_model_vinstr_data *model_data, - u32 counter_block_offset) -{ - CSTD_UNUSED(model_data); - /* The base address of Memory System performance counters is always the same, although their number - * may vary based on the number of cores. For the moment it's ok to return a constant. - */ - return MEMSYS_BASE + counter_block_offset; -} - -/** - * kbase_g7x_power_model_get_sc_counter() - get performance counter offset - * inside the Shader Cores block - * @model_data: pointer to GPU model data. - * @counter_block_offset: offset in bytes of the performance counter inside - * the (first) Shader Cores block. - * - * Return: Block offset in bytes of the required performance counter. - */ -static u32 kbase_g7x_power_model_get_sc_counter(struct kbase_ipa_model_vinstr_data *model_data, - u32 counter_block_offset) -{ -#if IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) - const u32 sc_base = - MEMSYS_BASE + (KBASE_DUMMY_MODEL_MAX_MEMSYS_BLOCKS * KBASE_IPA_NR_BYTES_PER_BLOCK); -#else - const u32 sc_base = MEMSYS_BASE + (model_data->kbdev->gpu_props.num_l2_slices * - KBASE_IPA_NR_BYTES_PER_BLOCK); -#endif - return sc_base + counter_block_offset; -} - -/** - * kbase_g7x_sum_all_memsys_blocks() - calculate energy for a single Memory - * System performance counter. - * @model_data: pointer to GPU model data. - * @coeff: default value of coefficient for IPA group. - * @counter_block_offset: offset in bytes of the counter inside the block it - * belongs to. - * - * Return: Energy estimation for a single Memory System performance counter. - */ -static s64 kbase_g7x_sum_all_memsys_blocks(struct kbase_ipa_model_vinstr_data *model_data, - s32 coeff, u32 counter_block_offset) -{ - u32 counter; - - counter = kbase_g7x_power_model_get_memsys_counter(model_data, counter_block_offset); - return kbase_ipa_sum_all_memsys_blocks(model_data, coeff, counter); -} - -/** - * kbase_g7x_sum_all_shader_cores() - calculate energy for a Shader Cores - * performance counter for all cores. - * @model_data: pointer to GPU model data. - * @coeff: default value of coefficient for IPA group. - * @counter_block_offset: offset in bytes of the counter inside the block it - * belongs to. - * - * Return: Energy estimation for a Shader Cores performance counter for all - * cores. - */ -static s64 kbase_g7x_sum_all_shader_cores(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter_block_offset) -{ - u32 counter; - - counter = kbase_g7x_power_model_get_sc_counter(model_data, counter_block_offset); - return kbase_ipa_sum_all_shader_cores(model_data, coeff, counter); -} - -/** - * kbase_g7x_jm_single_counter() - calculate energy for a single Job Manager performance counter. - * @model_data: pointer to GPU model data. - * @coeff: default value of coefficient for IPA group. - * @counter_block_offset: offset in bytes of the counter inside the block it belongs to. - * - * Return: Energy estimation for a single Job Manager performance counter. - */ -static s64 kbase_g7x_jm_single_counter(struct kbase_ipa_model_vinstr_data *model_data, s32 coeff, - u32 counter_block_offset) -{ - u32 counter; - - counter = kbase_g7x_power_model_get_jm_counter(model_data, counter_block_offset); - return kbase_ipa_single_counter(model_data, coeff, counter); -} - -/** - * kbase_g7x_get_active_cycles() - return the GPU_ACTIVE counter - * @model_data: pointer to GPU model data. - * - * Return: the number of cycles the GPU was active during the counter sampling - * period. - */ -static u32 kbase_g7x_get_active_cycles(struct kbase_ipa_model_vinstr_data *model_data) -{ - u32 counter = kbase_g7x_power_model_get_jm_counter(model_data, JM_GPU_ACTIVE); - - /* Counters are only 32-bit, so we can safely multiply by 1 then cast - * the 64-bit result back to a u32. - */ - return kbase_ipa_single_counter(model_data, 1, counter); -} - -/* Table of IPA group definitions. - * - * For each IPA group, this table defines a function to access the given performance block counter (or counters, - * if the operation needs to be iterated on multiple blocks) and calculate energy estimation. - */ - -static const struct kbase_ipa_group ipa_groups_def_g71[] = { - { - .name = "l2_access", - .default_value = 526300, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, - { - .name = "exec_instr_count", - .default_value = 301100, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_COUNT, - }, - { - .name = "tex_issue", - .default_value = 197400, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_COORD_ISSUE, - }, - { - .name = "tile_wb", - .default_value = -156400, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_BEATS_WR_TIB, - }, - { - .name = "gpu_active", - .default_value = 115800, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_g72[] = { - { - .name = "l2_access", - .default_value = 393000, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, - { - .name = "exec_instr_count", - .default_value = 227000, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_COUNT, - }, - { - .name = "tex_issue", - .default_value = 181900, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_COORD_ISSUE, - }, - { - .name = "tile_wb", - .default_value = -120200, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_BEATS_WR_TIB, - }, - { - .name = "gpu_active", - .default_value = 133100, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_g76[] = { - { - .name = "gpu_active", - .default_value = 122000, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, - { - .name = "exec_instr_count", - .default_value = 488900, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_COUNT, - }, - { - .name = "vary_instr", - .default_value = 212100, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_VARY_INSTR, - }, - { - .name = "tex_tfch_num_operations", - .default_value = 288000, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_TFCH_NUM_OPERATIONS, - }, - { - .name = "l2_access", - .default_value = 378100, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_g52_r1[] = { - { - .name = "gpu_active", - .default_value = 224200, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, - { - .name = "exec_instr_count", - .default_value = 384700, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_COUNT, - }, - { - .name = "vary_instr", - .default_value = 271900, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_VARY_INSTR, - }, - { - .name = "tex_tfch_num_operations", - .default_value = 477700, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_TFCH_NUM_OPERATIONS, - }, - { - .name = "l2_access", - .default_value = 551400, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_g51[] = { - { - .name = "gpu_active", - .default_value = 201400, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, - { - .name = "exec_instr_count", - .default_value = 392700, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_COUNT, - }, - { - .name = "vary_instr", - .default_value = 274000, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_VARY_INSTR, - }, - { - .name = "tex_tfch_num_operations", - .default_value = 528000, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_TFCH_NUM_OPERATIONS, - }, - { - .name = "l2_access", - .default_value = 506400, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_g77[] = { - { - .name = "l2_access", - .default_value = 710800, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, - { - .name = "exec_instr_msg", - .default_value = 2375300, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_MSG, - }, - { - .name = "exec_instr_fma", - .default_value = 656100, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_FMA, - }, - { - .name = "tex_filt_num_operations", - .default_value = 318800, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_FILT_NUM_OPERATIONS, - }, - { - .name = "gpu_active", - .default_value = 172800, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_tbex[] = { - { - .name = "l2_access", - .default_value = 599800, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, - { - .name = "exec_instr_msg", - .default_value = 1830200, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_MSG, - }, - { - .name = "exec_instr_fma", - .default_value = 407300, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_FMA, - }, - { - .name = "tex_filt_num_operations", - .default_value = 224500, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_FILT_NUM_OPERATIONS, - }, - { - .name = "gpu_active", - .default_value = 153800, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, -}; - -static const struct kbase_ipa_group ipa_groups_def_tbax[] = { - { - .name = "l2_access", - .default_value = 599800, - .op = kbase_g7x_sum_all_memsys_blocks, - .counter_block_offset = MEMSYS_L2_ANY_LOOKUP, - }, - { - .name = "exec_instr_msg", - .default_value = 1830200, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_MSG, - }, - { - .name = "exec_instr_fma", - .default_value = 407300, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_EXEC_INSTR_FMA, - }, - { - .name = "tex_filt_num_operations", - .default_value = 224500, - .op = kbase_g7x_sum_all_shader_cores, - .counter_block_offset = SC_TEX_FILT_NUM_OPERATIONS, - }, - { - .name = "gpu_active", - .default_value = 153800, - .op = kbase_g7x_jm_single_counter, - .counter_block_offset = JM_GPU_ACTIVE, - }, -}; - -#define IPA_POWER_MODEL_OPS(gpu, init_token) \ - static const struct kbase_ipa_model_ops kbase_##gpu##_ipa_model_ops = { \ - .name = "mali-" #gpu "-power-model", \ - .init = kbase_##init_token##_power_model_init, \ - .term = kbase_ipa_vinstr_common_model_term, \ - .get_dynamic_coeff = kbase_ipa_vinstr_dynamic_coeff, \ - .reset_counter_data = kbase_ipa_vinstr_reset_data, \ - } - -#define STANDARD_POWER_MODEL(gpu, reference_voltage) \ - static int kbase_##gpu##_power_model_init(struct kbase_ipa_model *model) \ - { \ - BUILD_BUG_ON(ARRAY_SIZE(ipa_groups_def_##gpu) > KBASE_IPA_MAX_GROUP_DEF_NUM); \ - return kbase_ipa_vinstr_common_model_init(model, ipa_groups_def_##gpu, \ - ARRAY_SIZE(ipa_groups_def_##gpu), \ - kbase_g7x_get_active_cycles, \ - (reference_voltage)); \ - } \ - IPA_POWER_MODEL_OPS(gpu, gpu) - -#define ALIAS_POWER_MODEL(gpu, as_gpu) IPA_POWER_MODEL_OPS(gpu, as_gpu) - -STANDARD_POWER_MODEL(g71, 800); -STANDARD_POWER_MODEL(g72, 800); -STANDARD_POWER_MODEL(g76, 800); -STANDARD_POWER_MODEL(g52_r1, 1000); -STANDARD_POWER_MODEL(g51, 1000); -STANDARD_POWER_MODEL(g77, 1000); -STANDARD_POWER_MODEL(tbex, 1000); -STANDARD_POWER_MODEL(tbax, 1000); - -/* g52 is an alias of g76 (TNOX) for IPA */ -ALIAS_POWER_MODEL(g52, g76); -/* tnax is an alias of g77 (TTRX) for IPA */ -ALIAS_POWER_MODEL(tnax, g77); - -static const struct kbase_ipa_model_ops *ipa_counter_model_ops[] = { - &kbase_g71_ipa_model_ops, &kbase_g72_ipa_model_ops, &kbase_g76_ipa_model_ops, - &kbase_g52_ipa_model_ops, &kbase_g52_r1_ipa_model_ops, &kbase_g51_ipa_model_ops, - &kbase_g77_ipa_model_ops, &kbase_tnax_ipa_model_ops, &kbase_tbex_ipa_model_ops, - &kbase_tbax_ipa_model_ops -}; - -const struct kbase_ipa_model_ops *kbase_ipa_counter_model_ops_find(struct kbase_device *kbdev, - const char *name) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(ipa_counter_model_ops); ++i) { - const struct kbase_ipa_model_ops *ops = ipa_counter_model_ops[i]; - - if (!strcmp(ops->name, name)) - return ops; - } - - dev_err(kbdev->dev, "power model \'%s\' not found\n", name); - - return NULL; -} - -const char *kbase_ipa_counter_model_name_from_id(struct kbase_gpu_id_props *gpu_id) -{ - switch (gpu_id->product_model) { - case GPU_ID_PRODUCT_TMIX: - return "mali-g71-power-model"; - case GPU_ID_PRODUCT_THEX: - return "mali-g72-power-model"; - case GPU_ID_PRODUCT_TNOX: - return "mali-g76-power-model"; - case GPU_ID_PRODUCT_TSIX: - return "mali-g51-power-model"; - case GPU_ID_PRODUCT_TGOX: - if (gpu_id->version_major == 0) - /* g52 aliased to g76 power-model's ops */ - return "mali-g52-power-model"; - else - return "mali-g52_r1-power-model"; - case GPU_ID_PRODUCT_TNAX: - return "mali-tnax-power-model"; - case GPU_ID_PRODUCT_TTRX: - return "mali-g77-power-model"; - case GPU_ID_PRODUCT_TBEX: - return "mali-tbex-power-model"; - case GPU_ID_PRODUCT_TBAX: - return "mali-tbax-power-model"; - default: - return NULL; - } -} diff --git a/drivers/gpu/arm/valhall/ipa/mali_kbase_ipa_simple.c b/drivers/gpu/arm/valhall/ipa/mali_kbase_ipa_simple.c index d8a356c3e8c2..b2dce96f4922 100644 --- a/drivers/gpu/arm/valhall/ipa/mali_kbase_ipa_simple.c +++ b/drivers/gpu/arm/valhall/ipa/mali_kbase_ipa_simple.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2016-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2016-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -34,8 +34,6 @@ #include "mali_kbase_ipa_simple.h" #include "mali_kbase_ipa_debugfs.h" -#if MALI_USE_CSF - /* This is used if the dynamic power for top-level is estimated separately * through the counter model. To roughly match the contribution of top-level * power in the total dynamic power, when calculated through counter model, @@ -46,8 +44,6 @@ */ #define TOP_LEVEL_DYN_COEFF_SCALER (3) -#endif /* MALI_USE_CSF */ - #if MALI_UNIT_TEST static int dummy_temp; @@ -208,7 +204,6 @@ static int model_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp) struct kbase_ipa_model_simple_data *model_data = (struct kbase_ipa_model_simple_data *)model->model_data; -#if MALI_USE_CSF /* On CSF GPUs, the dynamic power for top-level and shader cores is * estimated separately. Currently there is a single dynamic * coefficient value provided in the device tree for simple model. @@ -219,9 +214,6 @@ static int model_dynamic_coeff(struct kbase_ipa_model *model, u32 *coeffp) coeffp[KBASE_IPA_BLOCK_TYPE_TOP_LEVEL] = model_data->dynamic_coefficient / TOP_LEVEL_DYN_COEFF_SCALER; coeffp[KBASE_IPA_BLOCK_TYPE_SHADER_CORES] = model_data->dynamic_coefficient; -#else - *coeffp = model_data->dynamic_coefficient; -#endif return 0; } diff --git a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_defs.h b/drivers/gpu/arm/valhall/jm/mali_kbase_jm_defs.h deleted file mode 100644 index e9b388fabbda..000000000000 --- a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_defs.h +++ /dev/null @@ -1,770 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Definitions (types, defines, etcs) specific to Job Manager Kbase. - * They are placed here to allow the hierarchy of header files to work. - */ - -#ifndef _KBASE_JM_DEFS_H_ -#define _KBASE_JM_DEFS_H_ - -#include "mali_kbase_js_defs.h" - -#include - -/* Dump Job slot trace on error (only active if KBASE_KTRACE_ENABLE != 0) */ -#define KBASE_KTRACE_DUMP_ON_JOB_SLOT_ERROR 1 - -/* - * Number of milliseconds before resetting the GPU when a job cannot be "zapped" - * from the hardware. Note that the time is actually - * ZAP_TIMEOUT+SOFT_STOP_RESET_TIMEOUT between the context zap starting and - * the GPU actually being reset to give other contexts time for their jobs - * to be soft-stopped and removed from the hardware before resetting. - */ -#define ZAP_TIMEOUT 1000 - -/* - * Prevent soft-stops from occurring in scheduling situations - * - * This is not due to HW issues, but when scheduling is desired to be more - * predictable. - * - * Therefore, soft stop may still be disabled due to HW issues. - * - * Soft stop will still be used for non-scheduling purposes e.g. when - * terminating a context. - * - * if not in use, define this value to 0 instead of being undefined. - */ -#define KBASE_DISABLE_SCHEDULING_SOFT_STOPS 0 - -/* - * Prevent hard-stops from occurring in scheduling situations - * - * This is not due to HW issues, but when scheduling is desired to be more - * predictable. - * - * Hard stop will still be used for non-scheduling purposes e.g. when - * terminating a context. - * - * if not in use, define this value to 0 instead of being undefined. - */ -#define KBASE_DISABLE_SCHEDULING_HARD_STOPS 0 - -/* Atom has been previously soft-stopped */ -#define KBASE_KATOM_FLAG_BEEN_SOFT_STOPPED (1U << 1) -/* Atom has been previously retried to execute */ -#define KBASE_KATOM_FLAGS_RERUN (1U << 2) -/* Atom submitted with JOB_CHAIN_FLAG bit set in JS_CONFIG_NEXT register, helps - * to disambiguate short-running job chains during soft/hard stopping of jobs - */ -#define KBASE_KATOM_FLAGS_JOBCHAIN (1U << 3) -/* Atom has been previously hard-stopped. */ -#define KBASE_KATOM_FLAG_BEEN_HARD_STOPPED (1U << 4) -/* Atom has caused us to enter disjoint state */ -#define KBASE_KATOM_FLAG_IN_DISJOINT (1U << 5) -/* Atom blocked on cross-slot dependency */ -#define KBASE_KATOM_FLAG_X_DEP_BLOCKED (1U << 7) -/* Atom has fail dependency on cross-slot dependency */ -#define KBASE_KATOM_FLAG_FAIL_BLOCKER (1U << 8) -/* Atom is currently in the list of atoms blocked on cross-slot dependencies */ -#define KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST (1U << 9) -/* Atom requires GPU to be in protected mode */ -#define KBASE_KATOM_FLAG_PROTECTED (1U << 11) -/* Atom has been stored in runnable_tree */ -#define KBASE_KATOM_FLAG_JSCTX_IN_TREE (1U << 12) -/* Atom is waiting for L2 caches to power up in order to enter protected mode */ -#define KBASE_KATOM_FLAG_HOLDING_L2_REF_PROT (1U << 13) - -/* SW related flags about types of JS_COMMAND action - * NOTE: These must be masked off by JS_COMMAND_MASK - */ - -/* This command causes a disjoint event */ -#define JS_COMMAND_SW_CAUSES_DISJOINT 0x100 - -/* Bitmask of all SW related flags */ -#define JS_COMMAND_SW_BITS (JS_COMMAND_SW_CAUSES_DISJOINT) - -#if (JS_COMMAND_SW_BITS & JS_COMMAND_MASK) -#error "JS_COMMAND_SW_BITS not masked off by JS_COMMAND_MASK." \ - "Must update JS_COMMAND_SW_<..> bitmasks" -#endif - -/* Soft-stop command that causes a Disjoint event. This of course isn't - * entirely masked off by JS_COMMAND_MASK - */ -#define JS_COMMAND_SOFT_STOP_WITH_SW_DISJOINT (JS_COMMAND_SW_CAUSES_DISJOINT | JS_COMMAND_SOFT_STOP) - -#define KBASEP_ATOM_ID_INVALID BASE_JD_ATOM_COUNT - -/* Serialize atoms within a slot (ie only one atom per job slot) */ -#define KBASE_SERIALIZE_INTRA_SLOT (1 << 0) -/* Serialize atoms between slots (ie only one job slot running at any time) */ -#define KBASE_SERIALIZE_INTER_SLOT (1 << 1) -/* Reset the GPU after each atom completion */ -#define KBASE_SERIALIZE_RESET (1 << 2) - -/** - * enum kbase_timeout_selector - The choice of which timeout to get scaled - * using the lowest GPU frequency. - * @MMU_AS_INACTIVE_WAIT_TIMEOUT: Maximum waiting time in ms for the completion - * of a MMU operation - * @JM_DEFAULT_JS_FREE_TIMEOUT: Maximum timeout to wait for JS_COMMAND_NEXT - * to be updated on HW side so a Job Slot is - * considered free. - * @KBASE_PRFCNT_ACTIVE_TIMEOUT: Waiting time for prfcnt to be ready. - * @KBASE_CLEAN_CACHE_TIMEOUT: Waiting time for cache flush to complete. - * @KBASE_AS_INACTIVE_TIMEOUT: Waiting time for MCU address space to become inactive. - * @KBASE_TIMEOUT_SELECTOR_COUNT: Number of timeout selectors. - * @KBASE_DEFAULT_TIMEOUT: Fallthrough in case an invalid timeout is - * passed. - */ -enum kbase_timeout_selector { - MMU_AS_INACTIVE_WAIT_TIMEOUT, - JM_DEFAULT_JS_FREE_TIMEOUT, - KBASE_PRFCNT_ACTIVE_TIMEOUT, - KBASE_CLEAN_CACHE_TIMEOUT, - KBASE_AS_INACTIVE_TIMEOUT, - /* Must be the last in the enum */ - KBASE_TIMEOUT_SELECTOR_COUNT, - KBASE_DEFAULT_TIMEOUT = JM_DEFAULT_JS_FREE_TIMEOUT -}; - -#if IS_ENABLED(CONFIG_DEBUG_FS) -/** - * struct base_job_fault_event - keeps track of the atom which faulted or which - * completed after the faulty atom but before the - * debug data for faulty atom was dumped. - * - * @event_code: event code for the atom, should != BASE_JD_EVENT_DONE for - * the atom which faulted. - * @katom: pointer to the atom for which job fault occurred or which - * completed after the faulty atom. - * @job_fault_work: work item, queued only for the faulty atom, which waits for - * the dumping to get completed and then does the bottom half - * of job done for the atoms which followed the faulty atom. - * @head: List head used to store the atom in the global list of - * faulty atoms or context specific list of atoms which got - * completed during the dump. - * @reg_offset: offset of the register to be dumped next, only applicable - * for the faulty atom. - */ -struct base_job_fault_event { - u32 event_code; - struct kbase_jd_atom *katom; - struct work_struct job_fault_work; - struct list_head head; - int reg_offset; -}; -#endif - -/** - * struct kbase_jd_atom_dependency - Contains the dependency info for an atom. - * @atom: pointer to the dependee atom. - * @dep_type: type of dependency on the dependee @atom, i.e. order or data - * dependency. BASE_JD_DEP_TYPE_INVALID indicates no dependency. - */ -struct kbase_jd_atom_dependency { - struct kbase_jd_atom *atom; - u8 dep_type; -}; - -/** - * kbase_jd_katom_dep_atom - Retrieves a read-only reference to the - * dependee atom. - * @dep: pointer to the dependency info structure. - * - * Return: readonly reference to dependee atom. - */ -static inline const struct kbase_jd_atom * -kbase_jd_katom_dep_atom(const struct kbase_jd_atom_dependency *dep) -{ - return (const struct kbase_jd_atom *)(dep->atom); -} - -/** - * kbase_jd_katom_dep_type - Retrieves the dependency type info - * - * @dep: pointer to the dependency info structure. - * - * Return: the type of dependency there is on the dependee atom. - */ -static inline u8 kbase_jd_katom_dep_type(const struct kbase_jd_atom_dependency *dep) -{ - return dep->dep_type; -} - -/** - * kbase_jd_katom_dep_set - sets up the dependency info structure - * as per the values passed. - * @const_dep: pointer to the dependency info structure to be setup. - * @a: pointer to the dependee atom. - * @type: type of dependency there is on the dependee atom. - */ -static inline void kbase_jd_katom_dep_set(const struct kbase_jd_atom_dependency *const_dep, - struct kbase_jd_atom *a, u8 type) -{ - struct kbase_jd_atom_dependency *dep; - - dep = (struct kbase_jd_atom_dependency *)const_dep; - - dep->atom = a; - dep->dep_type = type; -} - -/** - * kbase_jd_katom_dep_clear - resets the dependency info structure - * - * @const_dep: pointer to the dependency info structure to be setup. - */ -static inline void kbase_jd_katom_dep_clear(const struct kbase_jd_atom_dependency *const_dep) -{ - struct kbase_jd_atom_dependency *dep; - - dep = (struct kbase_jd_atom_dependency *)const_dep; - - dep->atom = NULL; - dep->dep_type = BASE_JD_DEP_TYPE_INVALID; -} - -/** - * enum kbase_atom_gpu_rb_state - The state of an atom, pertinent after it - * becomes runnable, with respect to job slot - * ringbuffer/fifo. - * @KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB: Atom not currently present in slot fifo, - * which implies that either atom has not become - * runnable due to dependency or has completed - * the execution on GPU. - * @KBASE_ATOM_GPU_RB_WAITING_BLOCKED: Atom has been added to slot fifo but is - * blocked due to cross slot dependency, - * can't be submitted to GPU. - * @KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV: Atom has been added to slot - * fifo but is waiting for the completion of - * previously added atoms in current & other - * slots, as their protected mode requirements - * do not match with the current atom. - * @KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION: Atom is in slot fifo - * and is waiting for completion of protected - * mode transition, needed before the atom is - * submitted to GPU. - * @KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE: Atom is in slot fifo but is - * waiting for the cores, which are needed to - * execute the job chain represented by the atom, - * to become available - * @KBASE_ATOM_GPU_RB_READY: Atom is in slot fifo and can be submitted to - * GPU. - * @KBASE_ATOM_GPU_RB_SUBMITTED: Atom is in slot fifo and has been submitted - * to GPU. - * @KBASE_ATOM_GPU_RB_RETURN_TO_JS: Atom must be returned to JS due to some - * failure, but only after the previously added - * atoms in fifo have completed or have also - * been returned to JS. - */ -enum kbase_atom_gpu_rb_state { - KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB, - KBASE_ATOM_GPU_RB_WAITING_BLOCKED, - KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_PREV, - KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION, - KBASE_ATOM_GPU_RB_WAITING_FOR_CORE_AVAILABLE, - KBASE_ATOM_GPU_RB_READY, - KBASE_ATOM_GPU_RB_SUBMITTED, - KBASE_ATOM_GPU_RB_RETURN_TO_JS = -1 -}; - -/** - * enum kbase_atom_enter_protected_state - The state of an atom with respect to - * the preparation for GPU's entry into protected mode, - * becomes pertinent only after atom's state with respect - * to slot ringbuffer is - * KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION - * @KBASE_ATOM_ENTER_PROTECTED_CHECK: Starting state. Check if there are any - * atoms currently submitted to GPU and protected mode - * transition is not already in progress. - * @KBASE_ATOM_ENTER_PROTECTED_HWCNT: Wait for hardware counter context to - * become disabled before entry into protected mode. - * @KBASE_ATOM_ENTER_PROTECTED_IDLE_L2: Wait for the L2 to become idle in - * preparation for the coherency change. L2 shall be - * powered down and GPU shall come out of fully - * coherent mode before entering protected mode. - * @KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY: Prepare coherency change; - * for KBASE_HW_ISSUE_TGOX_R1_1234 also request L2 power on - * so that coherency register contains correct value when - * GPU enters protected mode. - * @KBASE_ATOM_ENTER_PROTECTED_FINISHED: End state; for - * KBASE_HW_ISSUE_TGOX_R1_1234 check - * that L2 is powered up and switch GPU to protected mode. - */ -enum kbase_atom_enter_protected_state { - /* - * NOTE: The integer value of this must match - * KBASE_ATOM_EXIT_PROTECTED_CHECK. - */ - KBASE_ATOM_ENTER_PROTECTED_CHECK = 0, - KBASE_ATOM_ENTER_PROTECTED_HWCNT, - KBASE_ATOM_ENTER_PROTECTED_IDLE_L2, - KBASE_ATOM_ENTER_PROTECTED_SET_COHERENCY, - KBASE_ATOM_ENTER_PROTECTED_FINISHED, -}; - -/** - * enum kbase_atom_exit_protected_state - The state of an atom with respect to - * the preparation for GPU's exit from protected mode, - * becomes pertinent only after atom's state with respect - * to slot ngbuffer is - * KBASE_ATOM_GPU_RB_WAITING_PROTECTED_MODE_TRANSITION - * @KBASE_ATOM_EXIT_PROTECTED_CHECK: Starting state. Check if there are any - * atoms currently submitted to GPU and protected mode - * transition is not already in progress. - * @KBASE_ATOM_EXIT_PROTECTED_IDLE_L2: Wait for the L2 to become idle in - * preparation for the reset, as exiting protected mode - * requires a reset. - * @KBASE_ATOM_EXIT_PROTECTED_RESET: Issue the reset to trigger exit from - * protected mode - * @KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT: End state, Wait for the reset to - * complete - */ -enum kbase_atom_exit_protected_state { - /* - * NOTE: The integer value of this must match - * KBASE_ATOM_ENTER_PROTECTED_CHECK. - */ - KBASE_ATOM_EXIT_PROTECTED_CHECK = 0, - KBASE_ATOM_EXIT_PROTECTED_IDLE_L2, - KBASE_ATOM_EXIT_PROTECTED_RESET, - KBASE_ATOM_EXIT_PROTECTED_RESET_WAIT, -}; - -/** - * struct kbase_jd_atom - object representing the atom, containing the complete - * state and attributes of an atom. - * @work: work item for the bottom half processing of the atom, - * by JD or JS, after it got executed on GPU or the - * input fence got signaled - * @start_timestamp: time at which the atom was submitted to the GPU, by - * updating the JS_HEAD_NEXTn register. - * @udata: copy of the user data sent for the atom in - * base_jd_submit. - * @kctx: Pointer to the base context with which the atom is - * associated. - * @dep_head: Array of 2 list heads, pointing to the two list of - * atoms - * which are blocked due to dependency on this atom. - * @dep_item: Array of 2 list heads, used to store the atom in the - * list of other atoms depending on the same dependee - * atom. - * @dep: Array containing the dependency info for the 2 atoms - * on which the atom depends upon. - * @jd_item: List head used during job dispatch job_done - * processing - as dependencies may not be entirely - * resolved at this point, - * we need to use a separate list head. - * @in_jd_list: flag set to true if atom's @jd_item is currently on - * a list, prevents atom being processed twice. - * @jit_ids: Zero-terminated array of IDs of just-in-time memory - * allocations written to by the atom. When the atom - * completes, the value stored at the - * &struct_base_jit_alloc_info.heap_info_gpu_addr of - * each allocation is read in order to enforce an - * overall physical memory usage limit. - * @nr_extres: number of external resources referenced by the atom. - * @extres: Pointer to @nr_extres VA regions containing the external - * resource allocation and other information. - * @nr_extres external resources referenced by the atom. - * @device_nr: indicates the coregroup with which the atom is - * associated, when - * BASE_JD_REQ_SPECIFIC_COHERENT_GROUP specified. - * @jc: GPU address of the job-chain. - * @softjob_data: Copy of data read from the user space buffer that @jc - * points to. - * @dma_fence: object containing pointers to both input & output - * fences and other related members used for explicit - * sync through soft jobs and for the implicit - * synchronization required on access to external - * resources. - * @dma_fence.fence_in: Points to the dma-buf input fence for this atom. - * The atom would complete only after the fence is - * signaled. - * @dma_fence.fence: Points to the dma-buf output fence for this atom. - * @dma_fence.fence_cb: The object that is passed at the time of adding the - * callback that gets invoked when @dma_fence.fence_in - * is signaled. - * @dma_fence.fence_cb_added: Flag to keep a track if the callback was successfully - * added for @dma_fence.fence_in, which is supposed to be - * invoked on the signaling of fence. - * @dma_fence.context: The dma-buf fence context number for this atom. A - * unique context number is allocated to each katom in - * the context on context creation. - * @dma_fence.seqno: The dma-buf fence sequence number for this atom. This - * is increased every time this katom uses dma-buf fence - * @event_code: Event code for the job chain represented by the atom, - * both HW and low-level SW events are represented by - * event codes. - * @core_req: bitmask of BASE_JD_REQ_* flags specifying either - * Hw or Sw requirements for the job chain represented - * by the atom. - * @ticks: Number of scheduling ticks for which atom has been - * running on the GPU. - * @sched_priority: Priority of the atom for Job scheduling, as per the - * KBASE_JS_ATOM_SCHED_PRIO_*. - * @completed: Wait queue to wait upon for the completion of atom. - * @status: Indicates at high level at what stage the atom is in, - * as per KBASE_JD_ATOM_STATE_*, that whether it is not - * in use or its queued in JD or given to JS or - * submitted to Hw or it completed the execution on Hw. - * @slot_nr: Job slot chosen for the atom. - * @atom_flags: bitmask of KBASE_KATOM_FLAG* flags capturing the - * excat low level state of the atom. - * @gpu_rb_state: bitmnask of KBASE_ATOM_GPU_RB_* flags, precisely - * tracking atom's state after it has entered - * Job scheduler on becoming runnable. Atom - * could be blocked due to cross slot dependency - * or waiting for the shader cores to become available - * or waiting for protected mode transitions to - * complete. - * @need_cache_flush_cores_retained: flag indicating that manual flush of GPU - * cache is needed for the atom and the shader cores - * used for atom have been kept on. - * @blocked: flag indicating that atom's resubmission to GPU is - * blocked till the work item is scheduled to return the - * atom to JS. - * @seq_nr: user-space sequence number, to order atoms in some - * temporal order - * @pre_dep: Pointer to atom that this atom has same-slot - * dependency on - * @post_dep: Pointer to atom that has same-slot dependency on - * this atom - * @x_pre_dep: Pointer to atom that this atom has cross-slot - * dependency on - * @x_post_dep: Pointer to atom that has cross-slot dependency on - * this atom - * @flush_id: The GPU's flush count recorded at the time of - * submission, - * used for the cache flush optimization - * @fault_event: Info for dumping the debug data on Job fault. - * @queue: List head used for 4 different purposes : - * Adds atom to the list of dma-buf fence waiting atoms. - * Adds atom to the list of atoms blocked due to cross - * slot dependency. - * Adds atom to the list of softjob atoms for which JIT - * allocation has been deferred - * Adds atom to the list of softjob atoms waiting for - * the signaling of fence. - * @jit_node: Used to keep track of all JIT free/alloc jobs in - * submission order - * @jit_blocked: Flag indicating that JIT allocation requested through - * softjob atom will be reattempted after the impending - * free of other active JIT allocations. - * @will_fail_event_code: If non-zero, this indicates that the atom will fail - * with the set event_code when the atom is processed. - * Used for special handling of atoms, which have a data - * dependency on the failed atoms. - * @protected_state: State of the atom, as per - * KBASE_ATOM_(ENTER|EXIT)_PROTECTED_*, - * when transitioning into or out of protected mode. - * Atom will be either entering or exiting the - * protected mode. - * @protected_state.enter: entering the protected mode. - * @protected_state.exit: exiting the protected mode. - * @runnable_tree_node: The node added to context's job slot specific rb tree - * when the atom becomes runnable. - * @age: Age of atom relative to other atoms in the context, - * is snapshot of the age_count counter in kbase - * context. - * @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified. - */ -struct kbase_jd_atom { - struct work_struct work; - ktime_t start_timestamp; - - struct base_jd_udata udata; - struct kbase_context *kctx; - - struct list_head dep_head[2]; - struct list_head dep_item[2]; - const struct kbase_jd_atom_dependency dep[2]; - struct list_head jd_item; - bool in_jd_list; - -#if MALI_JIT_PRESSURE_LIMIT_BASE - u8 jit_ids[2]; -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - - u16 nr_extres; - struct kbase_va_region **extres; - - u32 device_nr; - u64 jc; - void *softjob_data; -#if IS_ENABLED(CONFIG_SYNC_FILE) - struct { - /* Use the functions/API defined in mali_kbase_fence.h to - * when working with this sub struct - */ - struct dma_fence *fence_in; - /* This points to the dma-buf output fence for this atom. If - * this is NULL then there is no fence for this atom and the - * following fields related to dma_fence may have invalid data. - * - * The context and seqno fields contain the details for this - * fence. - * - * This fence is signaled when the katom is completed, - * regardless of the event_code of the katom (signal also on - * failure). - */ - struct dma_fence *fence; - - /* This is the callback object that is registered for the fence_in. - * The callback is invoked when the fence_in is signaled. - */ - struct dma_fence_cb fence_cb; - bool fence_cb_added; - - unsigned int context; - atomic_t seqno; - } dma_fence; -#endif /* CONFIG_SYNC_FILE */ - - /* Note: refer to kbasep_js_atom_retained_state, which will take a copy - * of some of the following members - */ - enum base_jd_event_code event_code; - base_jd_core_req core_req; - u8 jobslot; - - u32 ticks; - int sched_priority; - - wait_queue_head_t completed; - enum kbase_jd_atom_state status; - unsigned int slot_nr; - - u32 atom_flags; - - enum kbase_atom_gpu_rb_state gpu_rb_state; - - bool need_cache_flush_cores_retained; - - atomic_t blocked; - - u64 seq_nr; - - struct kbase_jd_atom *pre_dep; - struct kbase_jd_atom *post_dep; - - struct kbase_jd_atom *x_pre_dep; - struct kbase_jd_atom *x_post_dep; - - u32 flush_id; - -#if IS_ENABLED(CONFIG_DEBUG_FS) - struct base_job_fault_event fault_event; -#endif - struct list_head queue; - - struct list_head jit_node; - bool jit_blocked; - - enum base_jd_event_code will_fail_event_code; - - union { - enum kbase_atom_enter_protected_state enter; - enum kbase_atom_exit_protected_state exit; - } protected_state; - - struct rb_node runnable_tree_node; - - u32 age; -}; - -static inline bool kbase_jd_katom_is_protected(const struct kbase_jd_atom *katom) -{ - return (bool)(katom->atom_flags & KBASE_KATOM_FLAG_PROTECTED); -} - -/** - * kbase_jd_atom_is_younger - query if one atom is younger by age than another - * - * @katom_a: the first atom - * @katom_b: the second atom - * - * Return: true if the first atom is strictly younger than the second, - * false otherwise. - */ -static inline bool kbase_jd_atom_is_younger(const struct kbase_jd_atom *katom_a, - const struct kbase_jd_atom *katom_b) -{ - return ((s32)(katom_a->age - katom_b->age) < 0); -} - -/** - * kbase_jd_atom_is_earlier - Check whether the first atom has been submitted - * earlier than the second one - * - * @katom_a: the first atom - * @katom_b: the second atom - * - * Return: true if the first atom has been submitted earlier than the - * second atom. It is used to understand if an atom that is ready has been - * submitted earlier than the currently running atom, so that the currently - * running atom should be preempted to allow the ready atom to run. - */ -static inline bool kbase_jd_atom_is_earlier(const struct kbase_jd_atom *katom_a, - const struct kbase_jd_atom *katom_b) -{ - /* No seq_nr set? */ - if (!katom_a->seq_nr || !katom_b->seq_nr) - return false; - - /* Efficiently handle the unlikely case of wrapping. - * The following code assumes that the delta between the sequence number - * of the two atoms is less than INT64_MAX. - * In the extremely unlikely case where the delta is higher, the comparison - * defaults for no preemption. - * The code also assumes that the conversion from unsigned to signed types - * works because the signed integers are 2's complement. - */ - return (s64)(katom_a->seq_nr - katom_b->seq_nr) < 0; -} - -/* - * Theory of operations: - * - * Atom objects are statically allocated within the context structure. - * - * Each atom is the head of two lists, one for the "left" set of dependencies, - * one for the "right" set. - */ - -#define KBASE_JD_DEP_QUEUE_SIZE 256 - -/** - * struct kbase_jd_context - per context object encapsulating all the - * Job dispatcher related state. - * @lock: lock to serialize the updates made to the - * Job dispatcher state and kbase_jd_atom objects. - * @sched_info: Structure encapsulating all the Job scheduling - * info. - * @atoms: Array of the objects representing atoms, - * containing the complete state and attributes - * of an atom. - * @job_nr: Tracks the number of atoms being processed by the - * kbase. This includes atoms that are not tracked by - * scheduler: 'not ready to run' & 'dependency-only' - * jobs. - * @zero_jobs_wait: Waitq that reflects whether there are no jobs - * (including SW-only dependency jobs). This is set - * when no jobs are present on the ctx, and clear - * when there are jobs. - * This must be updated atomically with @job_nr. - * note: Job Dispatcher knows about more jobs than - * the Job Scheduler as it is unaware of jobs that - * are blocked on dependencies and SW-only dependency - * jobs. This waitq can be waited upon to find out - * when the context jobs are all done/cancelled - * (including those that might've been blocked - * on dependencies) - and so, whether it can be - * terminated. However, it should only be terminated - * once it is not present in the run-pool. - * Since the waitq is only set under @lock, - * the waiter should also briefly obtain and drop - * @lock to guarantee that the setter has completed - * its work on the kbase_context - * @job_done_wq: Workqueue to which the per atom work item is - * queued for bottom half processing when the - * atom completes - * execution on GPU or the input fence get signaled. - * @tb_lock: Lock to serialize the write access made to @tb to - * store the register access trace messages. - * @tb: Pointer to the Userspace accessible buffer storing - * the trace messages for register read/write - * accesses made by the Kbase. The buffer is filled - * in circular fashion. - * @tb_wrap_offset: Offset to the end location in the trace buffer, - * the write pointer is moved to the beginning on - * reaching this offset. - * @jit_atoms_head: A list of the just-in-time memory soft-jobs, both - * allocate & free, in submission order, protected - * by kbase_jd_context.lock. - * @jit_pending_alloc: A list of just-in-time memory allocation - * soft-jobs which will be reattempted after the - * impending free of other active allocations. - * @max_priority: Max priority level allowed for this context. - */ -struct kbase_jd_context { - struct mutex lock; - struct kbasep_js_kctx_info sched_info; - struct kbase_jd_atom atoms[BASE_JD_ATOM_COUNT]; - struct workqueue_struct *job_done_wq; - - wait_queue_head_t zero_jobs_wait; - spinlock_t tb_lock; - u32 *tb; - u32 job_nr; - size_t tb_wrap_offset; - - struct list_head jit_atoms_head; - struct list_head jit_pending_alloc; - int max_priority; -}; - -/** - * struct jsctx_queue - JS context atom queue - * @runnable_tree: Root of RB-tree containing currently runnable atoms on this - * job slot. - * @x_dep_head: Head item of the linked list of atoms blocked on cross-slot - * dependencies. Atoms on this list will be moved to the - * runnable_tree when the blocking atom completes. - * - * hwaccess_lock must be held when accessing this structure. - */ -struct jsctx_queue { - struct rb_root runnable_tree; - struct list_head x_dep_head; -}; - -/** - * struct kbase_as - Object representing an address space of GPU. - * @number: Index at which this address space structure is present - * in an array of address space structures embedded inside - * the &struct kbase_device. - * @pf_wq: Workqueue for processing work items related to - * Page fault and Bus fault handling. - * @work_pagefault: Work item for the Page fault handling. - * @work_busfault: Work item for the Bus fault handling. - * @pf_data: Data relating to Page fault. - * @bf_data: Data relating to Bus fault. - * @current_setup: Stores the MMU configuration for this address space. - */ -struct kbase_as { - unsigned int number; - struct workqueue_struct *pf_wq; - struct work_struct work_pagefault; - struct work_struct work_busfault; - struct kbase_fault pf_data; - struct kbase_fault bf_data; - struct kbase_mmu_setup current_setup; -}; - -#endif /* _KBASE_JM_DEFS_H_ */ diff --git a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_js.h b/drivers/gpu/arm/valhall/jm/mali_kbase_jm_js.h deleted file mode 100644 index 65b54c68d8c7..000000000000 --- a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_js.h +++ /dev/null @@ -1,1002 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Job Scheduler Interface. - * These interfaces are Internal to KBase. - */ - -#ifndef _KBASE_JM_JS_H_ -#define _KBASE_JM_JS_H_ - -#include "mali_kbase_js_ctx_attr.h" - -#define JS_MAX_RUNNING_JOBS 8 - -/** - * kbasep_js_devdata_init - Initialize the Job Scheduler - * @kbdev: The kbase_device to operate on - * - * The struct kbasep_js_device_data sub-structure of kbdev must be zero - * initialized before passing to the kbasep_js_devdata_init() function. This is - * to give efficient error path code. - * - * Return: 0 on success, error code otherwise. - */ -int kbasep_js_devdata_init(struct kbase_device *const kbdev); - -/** - * kbasep_js_devdata_halt - Halt the Job Scheduler. - * @kbdev: The kbase_device to operate on - * - * It is safe to call this on kbdev even if it the kbasep_js_device_data - * sub-structure was never initialized/failed initialization, to give efficient - * error-path code. - * - * For this to work, the struct kbasep_js_device_data sub-structure of kbdev - * must be zero initialized before passing to the kbasep_js_devdata_init() - * function. This is to give efficient error path code. - * - * It is a programming error to call this whilst there are still kbase_context - * structures registered with this scheduler. - * - */ -void kbasep_js_devdata_halt(struct kbase_device *kbdev); - -/** - * kbasep_js_devdata_term - Terminate the Job Scheduler - * @kbdev: The kbase_device to operate on - * - * It is safe to call this on kbdev even if it the kbasep_js_device_data - * sub-structure was never initialized/failed initialization, to give efficient - * error-path code. - * - * For this to work, the struct kbasep_js_device_data sub-structure of kbdev - * must be zero initialized before passing to the kbasep_js_devdata_init() - * function. This is to give efficient error path code. - * - * It is a programming error to call this whilst there are still kbase_context - * structures registered with this scheduler. - */ -void kbasep_js_devdata_term(struct kbase_device *kbdev); - -/** - * kbasep_js_kctx_init - Initialize the Scheduling Component of a - * struct kbase_context on the Job Scheduler. - * @kctx: The kbase_context to operate on - * - * This effectively registers a struct kbase_context with a Job Scheduler. - * - * It does not register any jobs owned by the struct kbase_context with - * the scheduler. Those must be separately registered by kbasep_js_add_job(). - * - * The struct kbase_context must be zero initialized before passing to the - * kbase_js_init() function. This is to give efficient error path code. - * - * Return: 0 on success, error code otherwise. - */ -int kbasep_js_kctx_init(struct kbase_context *const kctx); - -/** - * kbasep_js_kctx_term - Terminate the Scheduling Component of a - * struct kbase_context on the Job Scheduler - * @kctx: The kbase_context to operate on - * - * This effectively de-registers a struct kbase_context from its Job Scheduler - * - * It is safe to call this on a struct kbase_context that has never had or - * failed initialization of its jctx.sched_info member, to give efficient - * error-path code. - * - * For this to work, the struct kbase_context must be zero intitialized before - * passing to the kbase_js_init() function. - * - * It is a Programming Error to call this whilst there are still jobs - * registered with this context. - */ -void kbasep_js_kctx_term(struct kbase_context *kctx); - -/* kbase_jsctx_slot_prio_blocked_set - Set a context as being blocked for a job - * slot at and below a given priority level - * @kctx: The kbase_context - * @js: The job slot - * @sched_prio: The priority levels that the context is blocked at for @js (all - * priority levels at this level and below will be blocked) - * - * To preserve ordering and dependencies of atoms on soft-stopping (both within - * an between priority levels), a context must be marked as blocked for that - * atom's job slot, for all priority levels at or below the atom's priority. - * - * This must only be called due to an atom that was pulled from the context, - * otherwise there will be no way of unblocking the context when the atom is - * completed/unpulled. - * - * Atoms of higher priority might still be able to be pulled from the context - * on @js. This helps with starting a high priority atom as soon as possible. - */ -static inline void kbase_jsctx_slot_prio_blocked_set(struct kbase_context *kctx, unsigned int js, - int sched_prio) -{ - struct kbase_jsctx_slot_tracking *slot_tracking = &kctx->slot_tracking[js]; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - WARN(!slot_tracking->atoms_pulled_pri[sched_prio], - "When marking slot %u as blocked for priority %d on a kctx, no atoms were pulled - the slot cannot become unblocked", - js, sched_prio); - - slot_tracking->blocked |= ((kbase_js_prio_bitmap_t)1) << sched_prio; - KBASE_KTRACE_ADD_JM_SLOT_INFO(kctx->kbdev, JS_SLOT_PRIO_BLOCKED, kctx, NULL, 0, js, - (unsigned int)sched_prio); -} - -/* kbase_jsctx_atoms_pulled - Return number of atoms pulled on a context - * @kctx: The kbase_context - * - * Having atoms pulled indicates the context is not idle. - * - * Return: the number of atoms pulled on @kctx - */ -static inline int kbase_jsctx_atoms_pulled(struct kbase_context *kctx) -{ - return atomic_read(&kctx->atoms_pulled_all_slots); -} - -/** - * kbasep_js_add_job - Add a job chain to the Job Scheduler, - * and take necessary actions to - * schedule the context/run the job. - * @kctx: The kbase_context to operate on - * @atom: Atom to add - * - * This atomically does the following: - * * Update the numbers of jobs information - * * Add the job to the run pool if necessary (part of init_job) - * - * Once this is done, then an appropriate action is taken: - * * If the ctx is scheduled, it attempts to start the next job (which might be - * this added job) - * * Otherwise, and if this is the first job on the context, it enqueues it on - * the Policy Queue - * - * The Policy's Queue can be updated by this in the following ways: - * * In the above case that this is the first job on the context - * * If the context is high priority and the context is not scheduled, then it - * could cause the Policy to schedule out a low-priority context, allowing - * this context to be scheduled in. - * - * If the context is already scheduled on the RunPool, then adding a job to it - * is guaranteed not to update the Policy Queue. And so, the caller is - * guaranteed to not need to try scheduling a context from the Run Pool - it - * can safely assert that the result is false. - * - * It is a programming error to have more than U32_MAX jobs in flight at a time. - * - * The following locking conditions are made on the caller: - * * it must not hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * * it must not hold hwaccess_lock (as this will be obtained internally) - * * it must not hold kbasep_js_device_data::runpool_mutex (as this will be - * obtained internally) - * * it must not hold kbasep_jd_device_data::queue_mutex (again, it's used - * internally). - * - * Return: true indicates that the Policy Queue was updated, and so the - * caller will need to try scheduling a context onto the Run Pool, - * false indicates that no updates were made to the Policy Queue, - * so no further action is required from the caller. This is always returned - * when the context is currently scheduled. - */ -bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom); - -/** - * kbasep_js_remove_job - Remove a job chain from the Job Scheduler, - * except for its 'retained state'. - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * @atom: Atom to remove - * - * Completely removing a job requires several calls: - * * kbasep_js_copy_atom_retained_state(), to capture the 'retained state' of - * the atom - * * kbasep_js_remove_job(), to partially remove the atom from the Job Scheduler - * * kbasep_js_runpool_release_ctx_and_katom_retained_state(), to release the - * remaining state held as part of the job having been run. - * - * In the common case of atoms completing normally, this set of actions is more - * optimal for spinlock purposes than having kbasep_js_remove_job() handle all - * of the actions. - * - * In the case of canceling atoms, it is easier to call - * kbasep_js_remove_cancelled_job(), which handles all the necessary actions. - * - * It is a programming error to call this when: - * * a atom is not a job belonging to kctx. - * * a atom has already been removed from the Job Scheduler. - * * a atom is still in the runpool - * - * Do not use this for removing jobs being killed by kbase_jd_cancel() - use - * kbasep_js_remove_cancelled_job() instead. - * - * The following locking conditions are made on the caller: - * * it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * - */ -void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *atom); - -/** - * kbasep_js_remove_cancelled_job - Completely remove a job chain from the - * Job Scheduler, in the case - * where the job chain was cancelled. - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * @katom: Atom to remove - * - * This is a variant of kbasep_js_remove_job() that takes care of removing all - * of the retained state too. This is generally useful for cancelled atoms, - * which need not be handled in an optimal way. - * - * It is a programming error to call this when: - * * a atom is not a job belonging to kctx. - * * a atom has already been removed from the Job Scheduler. - * * a atom is still in the runpool: - * * it is not being killed with kbasep_jd_cancel() - * - * The following locking conditions are made on the caller: - * * it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * * it must not hold the hwaccess_lock, (as this will be obtained - * internally) - * * it must not hold kbasep_js_device_data::runpool_mutex (as this could be - * obtained internally) - * - * Return: true indicates that ctx attributes have changed and the caller - * should call kbase_js_sched_all() to try to run more jobs and - * false otherwise. - */ -bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *katom); - -/** - * kbasep_js_runpool_requeue_or_kill_ctx - Handling the requeuing/killing of a - * context that was evicted from the - * policy queue or runpool. - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * @has_pm_ref: tells whether to release Power Manager active reference - * - * This should be used whenever handing off a context that has been evicted - * from the policy queue or the runpool: - * * If the context is not dying and has jobs, it gets re-added to the policy - * queue - * * Otherwise, it is not added - * - * In addition, if the context is dying the jobs are killed asynchronously. - * - * In all cases, the Power Manager active reference is released - * (kbase_pm_context_idle()) whenever the has_pm_ref parameter is true. - * has_pm_ref must be set to false whenever the context was not previously in - * the runpool and does not hold a Power Manager active refcount. Note that - * contexts in a rollback of kbasep_js_try_schedule_head_ctx() might have an - * active refcount even though they weren't in the runpool. - * - * The following locking conditions are made on the caller: - * * it must hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * * it must not hold kbasep_jd_device_data::queue_mutex (as this will be - * obtained internally) - */ -void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, - bool has_pm_ref); - -/** - * kbasep_js_runpool_release_ctx - Release a refcount of a context being busy, - * allowing it to be scheduled out. - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * - * When the refcount reaches zero and the context might be scheduled out - * (depending on whether the Scheduling Policy has deemed it so, or if it has - * run out of jobs). - * - * If the context does get scheduled out, then The following actions will be - * taken as part of deschduling a context: - * For the context being descheduled: - * * If the context is in the processing of dying (all the jobs are being - * removed from it), then descheduling also kills off any jobs remaining in the - * context. - * * If the context is not dying, and any jobs remain after descheduling the - * context then it is re-enqueued to the Policy's Queue. - * * Otherwise, the context is still known to the scheduler, but remains absent - * from the Policy Queue until a job is next added to it. - * * In all descheduling cases, the Power Manager active reference (obtained - * during kbasep_js_try_schedule_head_ctx()) is released - * (kbase_pm_context_idle()). - * - * Whilst the context is being descheduled, this also handles actions that - * cause more atoms to be run: - * * Attempt submitting atoms when the Context Attributes on the Runpool have - * changed. This is because the context being scheduled out could mean that - * there are more opportunities to run atoms. - * * Attempt submitting to a slot that was previously blocked due to affinity - * restrictions. This is usually only necessary when releasing a context - * happens as part of completing a previous job, but is harmless nonetheless. - * * Attempt scheduling in a new context (if one is available), and if - * necessary, running a job from that new context. - * - * Unlike retaining a context in the runpool, this function cannot be called - * from IRQ context. - * - * It is a programming error to call this on a kctx that is not currently - * scheduled, or that already has a zero refcount. - * - * The following locking conditions are made on the caller: - * * it must not hold the hwaccess_lock, because it will be used internally. - * * it must not hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * * it must not hold kbasep_js_device_data::runpool_mutex (as this will be - * obtained internally) - * * it must not hold the kbase_device::mmu_hw_mutex (as this will be - * obtained internally) - * * it must not hold kbasep_jd_device_data::queue_mutex (as this will be - * obtained internally) - * - */ -void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbasep_js_runpool_release_ctx_and_katom_retained_state - Variant of - * kbasep_js_runpool_release_ctx() that handles additional - * actions from completing an atom. - * - * @kbdev: KBase device - * @kctx: KBase context - * @katom_retained_state: Retained state from the atom - * - * This is usually called as part of completing an atom and releasing the - * refcount on the context held by the atom. - * - * Therefore, the extra actions carried out are part of handling actions queued - * on a completed atom, namely: - * * Releasing the atom's context attributes - * * Retrying the submission on a particular slot, because we couldn't submit - * on that slot from an IRQ handler. - * - * The locking conditions of this function are the same as those for - * kbasep_js_runpool_release_ctx() - */ -void kbasep_js_runpool_release_ctx_and_katom_retained_state( - struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state); - -/** - * kbasep_js_runpool_release_ctx_nolock - Variant of kbase_js_runpool_release_ctx() - * without locks - * @kbdev: KBase device - * @kctx: KBase context - * - * Variant of kbase_js_runpool_release_ctx() that assumes that - * kbasep_js_device_data::runpool_mutex and - * kbasep_js_kctx_info::ctx::jsctx_mutex are held by the caller, and does not - * attempt to schedule new contexts. - */ -void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbasep_js_schedule_privileged_ctx - Schedule in a privileged context - * - * @kbdev: KBase device - * @kctx: KBase context - * - * This schedules a context in regardless of the context priority. - * If the runpool is full, a context will be forced out of the runpool and the - * function will wait for the new context to be scheduled in. - * The context will be kept scheduled in (and the corresponding address space - * reserved) until kbasep_js_release_privileged_ctx is called). - * - * The following locking conditions are made on the caller: - * * it must not hold the hwaccess_lock, because it will be used internally. - * * it must not hold kbasep_js_device_data::runpool_mutex (as this will be - * obtained internally) - * * it must not hold the kbase_device::mmu_hw_mutex (as this will be - * obtained internally) - * * it must not hold kbasep_jd_device_data::queue_mutex (again, it's used - * internally). - * * it must not hold kbasep_js_kctx_info::ctx::jsctx_mutex, because it will - * be used internally. - * - */ -void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbasep_js_release_privileged_ctx - Release a privileged context, - * allowing it to be scheduled out. - * @kbdev: KBase device - * @kctx: KBase context - * - * See kbasep_js_runpool_release_ctx for potential side effects. - * - * The following locking conditions are made on the caller: - * * it must not hold the hwaccess_lock, because it will be used internally. - * * it must not hold kbasep_js_kctx_info::ctx::jsctx_mutex. - * * it must not hold kbasep_js_device_data::runpool_mutex (as this will be - * obtained internally) - * * it must not hold the kbase_device::mmu_hw_mutex (as this will be - * obtained internally) - * - */ -void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbase_js_try_run_jobs - Try to submit the next job on each slot - * @kbdev: KBase device - * - * The following locks may be used: - * * kbasep_js_device_data::runpool_mutex - * * hwaccess_lock - */ -void kbase_js_try_run_jobs(struct kbase_device *kbdev); - -/** - * kbasep_js_suspend - Suspend the job scheduler during a Power Management - * Suspend event. - * @kbdev: KBase device - * - * Causes all contexts to be removed from the runpool, and prevents any - * contexts from (re)entering the runpool. - * - * This does not handle suspending the one privileged context: the caller must - * instead do this by suspending the GPU HW Counter Instrumentation. - * - * This will eventually cause all Power Management active references held by - * contexts on the runpool to be released, without running any more atoms. - * - * The caller must then wait for all Power Management active refcount to become - * zero before completing the suspend. - * - * The emptying mechanism may take some time to complete, since it can wait for - * jobs to complete naturally instead of forcing them to end quickly. However, - * this is bounded by the Job Scheduler's Job Timeouts. Hence, this - * function is guaranteed to complete in a finite time. - */ -void kbasep_js_suspend(struct kbase_device *kbdev); - -/** - * kbasep_js_resume - Resume the Job Scheduler after a Power Management - * Resume event. - * @kbdev: KBase device - * - * This restores the actions from kbasep_js_suspend(): - * * Schedules contexts back into the runpool - * * Resumes running atoms on the GPU - */ -void kbasep_js_resume(struct kbase_device *kbdev); - -/** - * kbase_js_dep_resolved_submit - Submit an atom to the job scheduler. - * - * @kctx: Context pointer - * @katom: Pointer to the atom to submit - * - * The atom is enqueued on the context's ringbuffer. The caller must have - * ensured that all dependencies can be represented in the ringbuffer. - * - * Caller must hold jctx->lock - * - * Return: true if the context requires to be enqueued, otherwise false. - */ -bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_atom *katom); - -/** - * kbase_js_pull - Pull an atom from a context in the job scheduler for - * execution. - * - * @kctx: Context to pull from - * @js: Job slot to pull from - * - * The atom will not be removed from the ringbuffer at this stage. - * - * The HW access lock must be held when calling this function. - * - * Return: a pointer to an atom, or NULL if there are no atoms for this - * slot that can be currently run. - */ -struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, unsigned int js); - -/** - * kbase_js_unpull - Return an atom to the job scheduler ringbuffer. - * - * @kctx: Context pointer - * @katom: Pointer to the atom to unpull - * - * An atom is 'unpulled' if execution is stopped but intended to be returned to - * later. The most common reason for this is that the atom has been - * soft-stopped. Another reason is if an end-of-renderpass atom completed - * but will need to be run again as part of the same renderpass. - * - * Note that if multiple atoms are to be 'unpulled', they must be returned in - * the reverse order to which they were originally pulled. It is a programming - * error to return atoms in any other order. - * - * The HW access lock must be held when calling this function. - * - */ -void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom); - -/** - * kbase_js_complete_atom_wq - Complete an atom from jd_done_worker(), - * removing it from the job - * scheduler ringbuffer. - * @kctx: Context pointer - * @katom: Pointer to the atom to complete - * - * If the atom failed then all dependee atoms marked for failure propagation - * will also fail. - * - * Return: true if the context is now idle (no jobs pulled) false otherwise. - */ -bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom *katom); - -/** - * kbase_js_complete_atom - Complete an atom. - * - * @katom: Pointer to the atom to complete - * @end_timestamp: The time that the atom completed (may be NULL) - * - * Most of the work required to complete an atom will be performed by - * jd_done_worker(). - * - * The HW access lock must be held when calling this function. - * - * Return: a atom that has now been unblocked and can now be run, or NULL - * if none - */ -struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_t *end_timestamp); - -/** - * kbase_js_sched - Submit atoms from all available contexts. - * - * @kbdev: Device pointer - * @js_mask: Mask of job slots to submit to - * - * This will attempt to submit as many jobs as possible to the provided job - * slots. It will exit when either all job slots are full, or all contexts have - * been used. - * - */ -void kbase_js_sched(struct kbase_device *kbdev, unsigned int js_mask); - -/** - * kbase_js_zap_context - Attempt to deschedule a context that is being - * destroyed - * @kctx: Context pointer - * - * This will attempt to remove a context from any internal job scheduler queues - * and perform any other actions to ensure a context will not be submitted - * from. - * - * If the context is currently scheduled, then the caller must wait for all - * pending jobs to complete before taking any further action. - */ -void kbase_js_zap_context(struct kbase_context *kctx); - -/** - * kbase_js_is_atom_valid - Validate an atom - * - * @kbdev: Device pointer - * @katom: Atom to validate - * - * This will determine whether the atom can be scheduled onto the GPU. Atoms - * with invalid combinations of core requirements will be rejected. - * - * Return: true if atom is valid false otherwise. - */ -bool kbase_js_is_atom_valid(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -/** - * kbase_js_set_timeouts - update all JS timeouts with user specified data - * - * @kbdev: Device pointer - * - * Timeouts are specified through the 'js_timeouts' sysfs file. If a timeout is - * set to a positive number then that becomes the new value used, if a timeout - * is negative then the default is set. - */ -void kbase_js_set_timeouts(struct kbase_device *kbdev); - -/** - * kbase_js_set_ctx_priority - set the context priority - * - * @kctx: Context pointer - * @new_priority: New priority value for the Context - * - * The context priority is set to a new value and it is moved to the - * pullable/unpullable list as per the new priority. - */ -void kbase_js_set_ctx_priority(struct kbase_context *kctx, int new_priority); - -/** - * kbase_js_update_ctx_priority - update the context priority - * - * @kctx: Context pointer - * - * The context priority gets updated as per the priority of atoms currently in - * use for that context, but only if system priority mode for context scheduling - * is being used. - */ -void kbase_js_update_ctx_priority(struct kbase_context *kctx); - -/* - * Helpers follow - */ - -/** - * kbasep_js_is_submit_allowed - Check that a context is allowed to submit - * jobs on this policy - * @js_devdata: KBase Job Scheduler Device Data - * @kctx: KBase context - * - * The purpose of this abstraction is to hide the underlying data size, - * and wrap up the long repeated line of code. - * - * As with any bool, never test the return value with true. - * - * The caller must hold hwaccess_lock. - * - * Return: true if the context is allowed to submit jobs, false otherwise. - */ -static inline bool kbasep_js_is_submit_allowed(struct kbasep_js_device_data *js_devdata, - struct kbase_context *kctx) -{ - u16 test_bit; - bool is_allowed; - - /* Ensure context really is scheduled in */ - if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), - "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, - kctx->as_nr, atomic_read(&kctx->flags))) - return false; - - test_bit = (u16)(1u << kctx->as_nr); - - is_allowed = (bool)(js_devdata->runpool_irq.submit_allowed & test_bit); - dev_dbg(kctx->kbdev->dev, "JS: submit %s allowed on %pK (as=%d)", - is_allowed ? "is" : "isn't", (void *)kctx, kctx->as_nr); - return is_allowed; -} - -/** - * kbasep_js_set_submit_allowed - Allow a context to submit jobs on this policy - * @js_devdata: KBase Job Scheduler Device Data - * @kctx: KBase context - * - * The purpose of this abstraction is to hide the underlying data size, - * and wrap up the long repeated line of code. - * - * The caller must hold hwaccess_lock. - */ -static inline void kbasep_js_set_submit_allowed(struct kbasep_js_device_data *js_devdata, - struct kbase_context *kctx) -{ - u16 set_bit; - - /* Ensure context really is scheduled in */ - if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), - "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, - kctx->as_nr, atomic_read(&kctx->flags))) - return; - - set_bit = (u16)(1u << kctx->as_nr); - - dev_dbg(kctx->kbdev->dev, "JS: Setting Submit Allowed on %pK (as=%d)", kctx, kctx->as_nr); - - js_devdata->runpool_irq.submit_allowed |= set_bit; -} - -/** - * kbasep_js_clear_submit_allowed - Prevent a context from submitting more - * jobs on this policy - * @js_devdata: KBase Job Scheduler Device Data - * @kctx: KBase context - * - * The purpose of this abstraction is to hide the underlying data size, - * and wrap up the long repeated line of code. - * - * The caller must hold hwaccess_lock. - */ -static inline void kbasep_js_clear_submit_allowed(struct kbasep_js_device_data *js_devdata, - struct kbase_context *kctx) -{ - u16 clear_bit; - u16 clear_mask; - - /* Ensure context really is scheduled in */ - if (WARN((kctx->as_nr == KBASEP_AS_NR_INVALID) || !kbase_ctx_flag(kctx, KCTX_SCHEDULED), - "%s: kctx %pK has assigned AS %d and context flag %d\n", __func__, (void *)kctx, - kctx->as_nr, atomic_read(&kctx->flags))) - return; - - clear_bit = (u16)(1u << kctx->as_nr); - clear_mask = ~clear_bit; - - dev_dbg(kctx->kbdev->dev, "JS: Clearing Submit Allowed on %pK (as=%d)", kctx, kctx->as_nr); - - js_devdata->runpool_irq.submit_allowed &= clear_mask; -} - -/** - * kbasep_js_atom_retained_state_init_invalid - Create an initial 'invalid' - * atom retained state - * - * @retained_state: pointer where to create and initialize the state - * - * Create an initial 'invalid' atom retained state, that requires no - * atom-related work to be done on releasing with - * kbasep_js_runpool_release_ctx_and_katom_retained_state() - */ -static inline void -kbasep_js_atom_retained_state_init_invalid(struct kbasep_js_atom_retained_state *retained_state) -{ - retained_state->event_code = BASE_JD_EVENT_NOT_STARTED; - retained_state->core_req = KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID; -} - -/** - * kbasep_js_atom_retained_state_copy() - Copy atom state - * @retained_state: where to copy - * @katom: where to copy from - * - * Copy atom state that can be made available after kbase_jd_done_nolock() is called - * on that atom. - */ -static inline void -kbasep_js_atom_retained_state_copy(struct kbasep_js_atom_retained_state *retained_state, - const struct kbase_jd_atom *katom) -{ - retained_state->event_code = katom->event_code; - retained_state->core_req = katom->core_req; - retained_state->sched_priority = katom->sched_priority; - retained_state->device_nr = katom->device_nr; -} - -/** - * kbasep_js_has_atom_finished - Determine whether an atom has finished - * (given its retained state), - * and so should be given back to - * userspace/removed from the system. - * - * @katom_retained_state: the retained state of the atom to check - * - * Reasons for an atom not finishing include: - * * Being soft-stopped (and so, the atom should be resubmitted sometime later) - * * It is an end of renderpass atom that was run to consume the output of a - * start-of-renderpass atom that was soft-stopped because it used too much - * memory. In this case, it will have to be run again later. - * - * Return: false if the atom has not finished, true otherwise. - */ -static inline bool -kbasep_js_has_atom_finished(const struct kbasep_js_atom_retained_state *katom_retained_state) -{ - return (bool)(katom_retained_state->event_code != BASE_JD_EVENT_STOPPED && - katom_retained_state->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT); -} - -/** - * kbasep_js_atom_retained_state_is_valid - Determine whether a struct - * kbasep_js_atom_retained_state - * is valid - * @katom_retained_state: the atom's retained state to check - * - * An invalid struct kbasep_js_atom_retained_state is allowed, and indicates - * that the code should just ignore it. - * - * Return: false if the retained state is invalid, true otherwise. - */ -static inline bool kbasep_js_atom_retained_state_is_valid( - const struct kbasep_js_atom_retained_state *katom_retained_state) -{ - return (bool)(katom_retained_state->core_req != - KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID); -} - -/** - * kbase_js_runpool_inc_context_count - Increment number of running contexts. - * @kbdev: KBase device - * @kctx: KBase context - * - * The following locking conditions are made on the caller: - * * The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. - * * The caller must hold the kbasep_js_device_data::runpool_mutex - */ -static inline void kbase_js_runpool_inc_context_count(struct kbase_device *kbdev, - struct kbase_context *kctx) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - lockdep_assert_held(&js_devdata->runpool_mutex); - - /* Track total contexts */ - WARN_ON_ONCE(js_devdata->nr_all_contexts_running >= JS_MAX_RUNNING_JOBS); - ++(js_devdata->nr_all_contexts_running); - - if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { - /* Track contexts that can submit jobs */ - WARN_ON_ONCE(js_devdata->nr_user_contexts_running >= JS_MAX_RUNNING_JOBS); - ++(js_devdata->nr_user_contexts_running); - } -} - -/** - * kbase_js_runpool_dec_context_count - decrement number of running contexts. - * - * @kbdev: KBase device - * @kctx: KBase context - * The following locking conditions are made on the caller: - * * The caller must hold the kbasep_js_kctx_info::ctx::jsctx_mutex. - * * The caller must hold the kbasep_js_device_data::runpool_mutex - */ -static inline void kbase_js_runpool_dec_context_count(struct kbase_device *kbdev, - struct kbase_context *kctx) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - lockdep_assert_held(&js_devdata->runpool_mutex); - - /* Track total contexts */ - --(js_devdata->nr_all_contexts_running); - WARN_ON_ONCE(js_devdata->nr_all_contexts_running < 0); - - if (!kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { - /* Track contexts that can submit jobs */ - --(js_devdata->nr_user_contexts_running); - WARN_ON_ONCE(js_devdata->nr_user_contexts_running < 0); - } -} - -/** - * kbase_js_sched_all - Submit atoms from all available contexts to all - * job slots. - * - * @kbdev: Device pointer - * - * This will attempt to submit as many jobs as possible. It will exit when - * either all job slots are full, or all contexts have been used. - */ -static inline void kbase_js_sched_all(struct kbase_device *kbdev) -{ - kbase_js_sched(kbdev, (1U << kbdev->gpu_props.num_job_slots) - 1U); -} - -extern const int kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS]; - -extern const base_jd_prio kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; - -/** - * kbasep_js_atom_prio_to_sched_prio - Convert atom priority (base_jd_prio) - * to relative ordering. - * @atom_prio: Priority ID to translate. - * - * Atom priority values for @ref base_jd_prio cannot be compared directly to - * find out which are higher or lower. - * - * This function will convert base_jd_prio values for successively lower - * priorities into a monotonically increasing sequence. That is, the lower the - * base_jd_prio priority, the higher the value produced by this function. This - * is in accordance with how the rest of the kernel treats priority. - * - * The mapping is 1:1 and the size of the valid input range is the same as the - * size of the valid output range, i.e. - * KBASE_JS_ATOM_SCHED_PRIO_COUNT == BASE_JD_NR_PRIO_LEVELS - * - * Note This must be kept in sync with BASE_JD_PRIO_<...> definitions - * - * Return: On success: a value in the inclusive range - * 0..KBASE_JS_ATOM_SCHED_PRIO_COUNT-1. On failure: - * KBASE_JS_ATOM_SCHED_PRIO_INVALID - */ -static inline int kbasep_js_atom_prio_to_sched_prio(base_jd_prio atom_prio) -{ - if (atom_prio >= BASE_JD_NR_PRIO_LEVELS) - return KBASE_JS_ATOM_SCHED_PRIO_INVALID; - - return kbasep_js_atom_priority_to_relative[atom_prio]; -} - -/** - * kbasep_js_sched_prio_to_atom_prio - Convert relative scheduler priority - * to atom priority (base_jd_prio). - * - * @kbdev: Device pointer - * @sched_prio: Relative scheduler priority to translate. - * - * This function will convert relative scheduler priority back into base_jd_prio - * values. It takes values which priorities are monotonically increasing - * and converts them to the corresponding base_jd_prio values. If an invalid number is - * passed in (i.e. not within the expected range) an error code is returned instead. - * - * The mapping is 1:1 and the size of the valid input range is the same as the - * size of the valid output range, i.e. - * KBASE_JS_ATOM_SCHED_PRIO_COUNT == BASE_JD_NR_PRIO_LEVELS - * - * Return: On success: a value in the inclusive range - * 0..BASE_JD_NR_PRIO_LEVELS-1. On failure: BASE_JD_PRIO_INVALID. - */ -static inline base_jd_prio kbasep_js_sched_prio_to_atom_prio(struct kbase_device *kbdev, - int sched_prio) -{ - if (likely(sched_prio >= 0 && sched_prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT)) - return kbasep_js_relative_priority_to_atom[sched_prio]; - /* Invalid priority value if reached here */ - dev_warn(kbdev->dev, "Unknown JS scheduling priority %d", sched_prio); - return BASE_JD_PRIO_INVALID; -} - -/** - * kbase_js_priority_check - Check the priority requested - * - * @kbdev: Device pointer - * @priority: Requested priority - * - * This will determine whether the requested priority can be satisfied. - * - * Return: The same or lower priority than requested. - */ -base_jd_prio kbase_js_priority_check(struct kbase_device *kbdev, base_jd_prio priority); - -/** - * kbase_js_atom_runs_before - determine if atoms for the same slot have an - * ordering relation - * @kbdev: kbase device - * @katom_a: the first atom - * @katom_b: the second atom. - * @order_flags: combination of KBASE_ATOM_ORDERING_FLAG_<...> for the ordering - * relation - * - * This is for making consistent decisions about the ordering of atoms when we - * need to do pre-emption on a slot, which includes stopping existing atoms - * when a new atom is ready to run, and also which other atoms to remove from - * the slot when the atom in JS_HEAD is being pre-empted. - * - * This only handles @katom_a and @katom_b being for the same job slot, as - * pre-emption only operates within a slot. - * - * Note: there is currently no use-case for this as a sorting comparison - * functions, hence only a boolean returned instead of int -1, 0, +1 return. If - * required in future, a modification to do so would be better than calling - * twice with katom_a and katom_b swapped. - * - * Return: - * true if @katom_a should run before @katom_b, false otherwise. - * A false return value does not distinguish between "no ordering relation" and - * "@katom_a should run after @katom_b". - */ -bool kbase_js_atom_runs_before(struct kbase_device *kbdev, const struct kbase_jd_atom *katom_a, - const struct kbase_jd_atom *katom_b, - const kbase_atom_ordering_flag_t order_flags); - -#endif /* _KBASE_JM_JS_H_ */ diff --git a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h b/drivers/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h deleted file mode 100644 index 98767fc06527..000000000000 --- a/drivers/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_JM_MEM_FLAGS_H_ -#define _KBASE_JM_MEM_FLAGS_H_ - -#include - -/* Kernel-side only flags allocated from 63 bit downwards */ - -/* Use the GPU VA chosen by the kernel client */ -#define BASEP_MEM_FLAG_MAP_FIXED ((base_mem_alloc_flags)1 << 61) - -/* Force trimming of JIT allocations when creating a new allocation */ -#define BASEP_MEM_PERFORM_JIT_TRIM ((base_mem_alloc_flags)1 << 60) - -/* Region belongs to a shrinker. - * - * This can either mean that it is part of the JIT/Ephemeral or tiler heap - * shrinker paths. Should be removed only after making sure that there are - * no references remaining to it in these paths, as it may cause the physical - * backing of the region to disappear during use. - */ -#define BASEP_MEM_DONT_NEED ((base_mem_alloc_flags)1 << 59) - -/* Allocation is actively used for JIT memory */ -#define BASEP_MEM_ACTIVE_JIT_ALLOC ((base_mem_alloc_flags)1 << 58) - -/* The first available bit which can be used to define new memory flag - * if needed. It should be decremented by one once new flag is added - * and BASEP_MEM_FLAGS_NR_BITS should be incremented accordingly - */ -#define BASEP_MEM_FIRST_FREE_FLAG ((base_mem_alloc_flags)1 << 57) - -#endif /* _KBASE_JM_MEM_FLAGS_H_ */ diff --git a/drivers/gpu/arm/valhall/jm/mali_kbase_js_defs.h b/drivers/gpu/arm/valhall/jm/mali_kbase_js_defs.h deleted file mode 100644 index c81af50918fd..000000000000 --- a/drivers/gpu/arm/valhall/jm/mali_kbase_js_defs.h +++ /dev/null @@ -1,466 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Job Scheduler Type Definitions - */ - -#ifndef _KBASE_JS_DEFS_H_ -#define _KBASE_JS_DEFS_H_ - -/* Forward decls */ -struct kbase_device; -struct kbase_jd_atom; - -typedef u32 kbase_context_flags; - -/* - * typedef kbasep_js_ctx_job_cb - Callback function run on all of a context's - * jobs registered with the Job Scheduler - */ -typedef void kbasep_js_ctx_job_cb(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -/* - * @brief Maximum number of jobs that can be submitted to a job slot whilst - * inside the IRQ handler. - * - * This is important because GPU NULL jobs can complete whilst the IRQ handler - * is running. Otherwise, it potentially allows an unlimited number of GPU NULL - * jobs to be submitted inside the IRQ handler, which increases IRQ latency. - */ -#define KBASE_JS_MAX_JOB_SUBMIT_PER_SLOT_PER_IRQ 2 - -/** - * enum kbasep_js_ctx_attr - Context attributes - * @KBASEP_JS_CTX_ATTR_COMPUTE: Attribute indicating a context that contains - * Compute jobs. - * @KBASEP_JS_CTX_ATTR_NON_COMPUTE: Attribute indicating a context that contains - * Non-Compute jobs. - * @KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES: Attribute indicating that a context - * contains compute-job atoms that aren't - * restricted to a coherent group, - * and can run on all cores. - * @KBASEP_JS_CTX_ATTR_COUNT: Must be the last in the enum - * - * Each context attribute can be thought of as a boolean value that caches some - * state information about either the runpool, or the context: - * - In the case of the runpool, it is a cache of "Do any contexts owned by - * the runpool have attribute X?" - * - In the case of a context, it is a cache of "Do any atoms owned by the - * context have attribute X?" - * - * The boolean value of the context attributes often affect scheduling - * decisions, such as affinities to use and job slots to use. - * - * To accomodate changes of state in the context, each attribute is refcounted - * in the context, and in the runpool for all running contexts. Specifically: - * - The runpool holds a refcount of how many contexts in the runpool have this - * attribute. - * - The context holds a refcount of how many atoms have this attribute. - * - * KBASEP_JS_CTX_ATTR_COMPUTE: - * Attribute indicating a context that contains Compute jobs. That is, - * the context has jobs of type @ref BASE_JD_REQ_ONLY_COMPUTE - * - * @note A context can be both 'Compute' and 'Non Compute' if it contains - * both types of jobs. - * - * KBASEP_JS_CTX_ATTR_NON_COMPUTE: - * Attribute indicating a context that contains Non-Compute jobs. That is, - * the context has some jobs that are \b not of type @ref - * BASE_JD_REQ_ONLY_COMPUTE. - * - * @note A context can be both 'Compute' and 'Non Compute' if it contains - * both types of jobs. - * - * KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES: - * Attribute indicating that a context contains compute-job atoms that - * aren't restricted to a coherent group, and can run on all cores. - * - * Specifically, this is when the atom's \a core_req satisfy: - * - (\a core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T) // uses slot 1 or slot 2 - * - && !(\a core_req & BASE_JD_REQ_COHERENT_GROUP) // not restricted to coherent groups - * - * Such atoms could be blocked from running if one of the coherent groups - * is being used by another job slot, so tracking this context attribute - * allows us to prevent such situations. - * - * @note This doesn't take into account the 1-coregroup case, where all - * compute atoms would effectively be able to run on 'all cores', but - * contexts will still not always get marked with this attribute. Instead, - * it is the caller's responsibility to take into account the number of - * coregroups when interpreting this attribute. - * - * @note Whilst Tiler atoms are normally combined with - * BASE_JD_REQ_COHERENT_GROUP, it is possible to send such atoms without - * BASE_JD_REQ_COHERENT_GROUP set. This is an unlikely case, but it's easy - * enough to handle anyway. - * - */ -enum kbasep_js_ctx_attr { - KBASEP_JS_CTX_ATTR_COMPUTE, - KBASEP_JS_CTX_ATTR_NON_COMPUTE, - KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES, - KBASEP_JS_CTX_ATTR_COUNT -}; - -enum { - /* - * Bit indicating that new atom should be started because this atom - * completed - */ - KBASE_JS_ATOM_DONE_START_NEW_ATOMS = (1u << 0), - /* - * Bit indicating that the atom was evicted from the JS_NEXT registers - */ - KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT = (1u << 1) -}; - -/** - * typedef kbasep_js_atom_done_code - Combination of KBASE_JS_ATOM_DONE_<...> - * bits - */ -typedef u32 kbasep_js_atom_done_code; - -/* - * Context scheduling mode defines for kbase_device::js_ctx_scheduling_mode - */ -enum { - /* - * In this mode, higher priority atoms will be scheduled first, - * regardless of the context they belong to. Newly-runnable higher - * priority atoms can preempt lower priority atoms currently running on - * the GPU, even if they belong to a different context. - */ - KBASE_JS_SYSTEM_PRIORITY_MODE = 0, - - /* - * In this mode, the highest-priority atom will be chosen from each - * context in turn using a round-robin algorithm, so priority only has - * an effect within the context an atom belongs to. Newly-runnable - * higher priority atoms can preempt the lower priority atoms currently - * running on the GPU, but only if they belong to the same context. - */ - KBASE_JS_PROCESS_LOCAL_PRIORITY_MODE, - - /* Must be the last in the enum */ - KBASE_JS_PRIORITY_MODE_COUNT, -}; - -/* - * Internal atom priority defines for kbase_jd_atom::sched_prio - */ -enum { - KBASE_JS_ATOM_SCHED_PRIO_FIRST = 0, - KBASE_JS_ATOM_SCHED_PRIO_REALTIME = KBASE_JS_ATOM_SCHED_PRIO_FIRST, - KBASE_JS_ATOM_SCHED_PRIO_HIGH, - KBASE_JS_ATOM_SCHED_PRIO_MED, - KBASE_JS_ATOM_SCHED_PRIO_LOW, - KBASE_JS_ATOM_SCHED_PRIO_COUNT, -}; - -/* Invalid priority for kbase_jd_atom::sched_prio */ -#define KBASE_JS_ATOM_SCHED_PRIO_INVALID -1 - -/* Default priority in the case of contexts with no atoms, or being lenient - * about invalid priorities from userspace. - */ -#define KBASE_JS_ATOM_SCHED_PRIO_DEFAULT KBASE_JS_ATOM_SCHED_PRIO_MED - -/* Atom priority bitmaps, where bit 0 is the highest priority, and higher bits - * indicate successively lower KBASE_JS_ATOM_SCHED_PRIO_<...> levels. - * - * Must be strictly larger than the number of bits to represent a bitmap of - * priorities, so that we can do calculations such as: - * (1 << KBASE_JS_ATOM_SCHED_PRIO_COUNT) - 1 - * ...without causing undefined behavior due to a shift beyond the width of the - * type - * - * If KBASE_JS_ATOM_SCHED_PRIO_COUNT starts requiring 32 bits, then it's worth - * moving to DECLARE_BITMAP() - */ -typedef u8 kbase_js_prio_bitmap_t; - -/* Ordering modification for kbase_js_atom_runs_before() */ -typedef u32 kbase_atom_ordering_flag_t; - -/* Atoms of the same context and priority should have their ordering decided by - * their seq_nr instead of their age. - * - * seq_nr is used as a more slowly changing variant of age - it increases once - * per group of related atoms, as determined by user-space. Hence, it can be - * used to limit re-ordering decisions (such as pre-emption) to only re-order - * between such groups, rather than re-order within those groups of atoms. - */ -#define KBASE_ATOM_ORDERING_FLAG_SEQNR (((kbase_atom_ordering_flag_t)1) << 0) - -/** - * struct kbasep_js_device_data - KBase Device Data Job Scheduler sub-structure - * @runpool_irq: Sub-structure to collect together Job Scheduling data used in - * IRQ context. The hwaccess_lock must be held when accessing. - * @runpool_irq.submit_allowed: Bitvector indicating whether a currently - * scheduled context is allowed to submit jobs. - * When bit 'N' is set in this, it indicates whether - * the context bound to address space 'N' is - * allowed to submit jobs. - * @runpool_irq.ctx_attr_ref_count: Array of Context Attributes Ref_counters: - * Each is large enough to hold a refcount of the number of contexts - * that can fit into the runpool. This is currently BASE_MAX_NR_AS. - * Note that when BASE_MAX_NR_AS==16 we need 5 bits (not 4) to store - * the refcount. Hence, it's not worthwhile reducing this to - * bit-manipulation on u32s to save space (where in contrast, 4 bit - * sub-fields would be easy to do and would save space). - * Whilst this must not become negative, the sign bit is used for: - * - error detection in debug builds - * - Optimization: it is undefined for a signed int to overflow, and so - * the compiler can optimize for that never happening (thus, no masking - * is required on updating the variable) - * @runpool_irq.slot_affinities: Affinity management and tracking. Bitvector - * to aid affinity checking. - * Element 'n' bit 'i' indicates that slot 'n' - * is using core i (i.e. slot_affinity_refcount[n][i] > 0) - * @runpool_irq.slot_affinity_refcount: Array of fefcount for each core owned - * by each slot. Used to generate the slot_affinities array of bitvectors. - * The value of the refcount will not exceed BASE_JM_SUBMIT_SLOTS, - * because it is refcounted only when a job is definitely about to be - * submitted to a slot, and is de-refcounted immediately after a job - * finishes - * @schedule_sem: Scheduling semaphore. This must be held when calling - * kbase_jm_kick() - * @ctx_list_pullable: List of contexts that can currently be pulled from - * @ctx_list_unpullable: List of contexts that can not currently be pulled - * from, but have jobs currently running. - * @nr_user_contexts_running: Number of currently scheduled user contexts - * (excluding ones that are not submitting jobs) - * @nr_all_contexts_running: Number of currently scheduled contexts (including - * ones that are not submitting jobs) - * @js_reqs: Core Requirements to match up with base_js_atom's core_req memeber - * @note This is a write-once member, and so no locking is required to - * read - * @scheduling_period_ns: Value for JS_SCHEDULING_PERIOD_NS - * @soft_stop_ticks: Value for JS_SOFT_STOP_TICKS - * @soft_stop_ticks_cl: Value for JS_SOFT_STOP_TICKS_CL - * @hard_stop_ticks_ss: Value for JS_HARD_STOP_TICKS_SS - * @hard_stop_ticks_cl: Value for JS_HARD_STOP_TICKS_CL - * @hard_stop_ticks_dumping: Value for JS_HARD_STOP_TICKS_DUMPING - * @gpu_reset_ticks_ss: Value for JS_RESET_TICKS_SS - * @gpu_reset_ticks_cl: Value for JS_RESET_TICKS_CL - * @gpu_reset_ticks_dumping: Value for JS_RESET_TICKS_DUMPING - * @ctx_timeslice_ns: Value for JS_CTX_TIMESLICE_NS - * @suspended_soft_jobs_list: List of suspended soft jobs - * @softstop_always: Support soft-stop on a single context - * @init_status:The initialized-flag is placed at the end, to avoid - * cache-pollution (we should only be using this during init/term paths). - * @note This is a write-once member, and so no locking is required to - * read - * @nr_contexts_pullable:Number of contexts that can currently be pulled from - * @nr_contexts_runnable:Number of contexts that can either be pulled from or - * arecurrently running - * @soft_job_timeout_ms:Value for JS_SOFT_JOB_TIMEOUT - * @js_free_wait_time_ms: Maximum waiting time in ms for a Job Slot to be seen free. - * @queue_mutex: Queue Lock, used to access the Policy's queue of contexts - * independently of the Run Pool. - * Of course, you don't need the Run Pool lock to access this. - * @runpool_mutex: Run Pool mutex, for managing contexts within the runpool. - * - * This encapsulates the current context of the Job Scheduler on a particular - * device. This context is global to the device, and is not tied to any - * particular struct kbase_context running on the device. - * - * nr_contexts_running and as_free are optimized for packing together (by making - * them smaller types than u32). The operations on them should rarely involve - * masking. The use of signed types for arithmetic indicates to the compiler - * that the value will not rollover (which would be undefined behavior), and so - * under the Total License model, it is free to make optimizations based on - * that (i.e. to remove masking). - */ -struct kbasep_js_device_data { - struct runpool_irq { - u16 submit_allowed; - s8 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; - u64 slot_affinities[BASE_JM_MAX_NR_SLOTS]; - s8 slot_affinity_refcount[BASE_JM_MAX_NR_SLOTS][64]; - } runpool_irq; - struct semaphore schedule_sem; - struct list_head ctx_list_pullable[BASE_JM_MAX_NR_SLOTS][KBASE_JS_ATOM_SCHED_PRIO_COUNT]; - struct list_head ctx_list_unpullable[BASE_JM_MAX_NR_SLOTS][KBASE_JS_ATOM_SCHED_PRIO_COUNT]; - s8 nr_user_contexts_running; - s8 nr_all_contexts_running; - base_jd_core_req js_reqs[BASE_JM_MAX_NR_SLOTS]; - - u32 scheduling_period_ns; - u32 soft_stop_ticks; - u32 soft_stop_ticks_cl; - u32 hard_stop_ticks_ss; - u32 hard_stop_ticks_cl; - u32 hard_stop_ticks_dumping; - u32 gpu_reset_ticks_ss; - u32 gpu_reset_ticks_cl; - u32 gpu_reset_ticks_dumping; - u32 ctx_timeslice_ns; - - struct list_head suspended_soft_jobs_list; - -#ifdef CONFIG_MALI_VALHALL_DEBUG - bool softstop_always; -#endif /* CONFIG_MALI_VALHALL_DEBUG */ - int init_status; - u32 nr_contexts_pullable; - atomic_t nr_contexts_runnable; - atomic_t soft_job_timeout_ms; - u32 js_free_wait_time_ms; - - struct mutex queue_mutex; - /* - * Run Pool mutex, for managing contexts within the runpool. - * Unless otherwise specified, you must hold this lock whilst accessing - * any members that follow - * - * In addition, this is used to access: - * * the kbasep_js_kctx_info::runpool substructure - */ - struct mutex runpool_mutex; - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - /** - * @gpu_metrics_timer: High-resolution timer used to periodically emit the GPU metrics - * tracepoints for applications that are using the GPU. The timer is - * needed for the long duration handling so that the length of work - * period is within the allowed limit. - */ - struct hrtimer gpu_metrics_timer; - - /** - * @gpu_metrics_timer_needed: Flag to indicate if the @gpu_metrics_timer is needed. - * The timer won't be started after the expiry if the flag - * isn't set. - */ - bool gpu_metrics_timer_needed; - - /** - * @gpu_metrics_timer_running: Flag to indicate if the @gpu_metrics_timer is running. - * The flag is set to false when the timer is cancelled or - * is not restarted after the expiry. - */ - bool gpu_metrics_timer_running; -#endif -}; - -/** - * struct kbasep_js_kctx_info - KBase Context Job Scheduling information - * structure - * @ctx: Job Scheduler Context information sub-structure.Its members are - * accessed regardless of whether the context is: - * - In the Policy's Run Pool - * - In the Policy's Queue - * - Not queued nor in the Run Pool. - * You must obtain the @ctx.jsctx_mutex before accessing any other members - * of this substructure. - * You may not access any of its members from IRQ context. - * @ctx.jsctx_mutex: Job Scheduler Context lock - * @ctx.nr_jobs: Number of jobs ready to run - does \em not include - * the jobs waiting in the dispatcher, and dependency-only - * jobs. See kbase_jd_context::job_nr for such jobs - * @ctx.ctx_attr_ref_count: Context Attributes ref count. Each is large enough - * to hold a refcount of the number of atoms on the context. - * @ctx.is_scheduled_wait: Wait queue to wait for KCTX_SHEDULED flag state - * changes. - * @ctx.ctx_list_entry: Link implementing JS queues. Context can be present on - * one list per job slot. - * @init_status: The initalized-flag is placed at the end, to avoid - * cache-pollution (we should only be using this during init/term paths) - * - * This is a substructure in the struct kbase_context that encapsulates all the - * scheduling information. - */ -struct kbasep_js_kctx_info { - struct kbase_jsctx { - struct mutex jsctx_mutex; - - u32 nr_jobs; - u32 ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT]; - wait_queue_head_t is_scheduled_wait; - struct list_head ctx_list_entry[BASE_JM_MAX_NR_SLOTS]; - } ctx; - int init_status; -}; - -/** - * struct kbasep_js_atom_retained_state - Subset of atom state. - * @event_code: to determine whether the atom has finished - * @core_req: core requirements - * @sched_priority: priority - * @device_nr: Core group atom was executed on - * - * Subset of atom state that can be available after kbase_jd_done_nolock() is called - * on that atom. A copy must be taken via kbasep_js_atom_retained_state_copy(), - * because the original atom could disappear. - */ -struct kbasep_js_atom_retained_state { - /* Event code - to determine whether the atom has finished */ - enum base_jd_event_code event_code; - /* core requirements */ - base_jd_core_req core_req; - /* priority */ - int sched_priority; - /* Core group atom was executed on */ - u32 device_nr; -}; - -/* - * Value signifying 'no retry on a slot required' for: - * - kbase_js_atom_retained_state::retry_submit_on_slot - * - kbase_jd_atom::retry_submit_on_slot - */ -#define KBASEP_JS_RETRY_SUBMIT_SLOT_INVALID (-1) - -/* - * base_jd_core_req value signifying 'invalid' for a - * kbase_jd_atom_retained_state. See kbase_atom_retained_state_is_valid() - */ -#define KBASEP_JS_ATOM_RETAINED_STATE_CORE_REQ_INVALID BASE_JD_REQ_DEP - -/* - * The JS timer resolution, in microseconds - * Any non-zero difference in time will be at least this size. - */ -#define KBASEP_JS_TICK_RESOLUTION_US 1 - -/** - * struct kbase_jsctx_slot_tracking - Job Scheduling tracking of a context's - * use of a job slot - * @blocked: bitmap of priorities that this slot is blocked at - * @atoms_pulled: counts of atoms that have been pulled from this slot, - * across all priority levels - * @atoms_pulled_pri: counts of atoms that have been pulled from this slot, per - * priority level - * - * Controls how a slot from the &struct kbase_context's jsctx_queue is managed, - * for example to ensure correct ordering of atoms when atoms of different - * priorities are unpulled. - */ -struct kbase_jsctx_slot_tracking { - kbase_js_prio_bitmap_t blocked; - atomic_t atoms_pulled; - int atoms_pulled_pri[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; -}; - -#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_csffw.bin b/drivers/gpu/arm/valhall/mali_csffw.bin index d95a7e530576..5d6480e8c70f 100644 Binary files a/drivers/gpu/arm/valhall/mali_csffw.bin and b/drivers/gpu/arm/valhall/mali_csffw.bin differ diff --git a/drivers/gpu/arm/valhall/mali_kbase.h b/drivers/gpu/arm/valhall/mali_kbase.h index b260be8077a8..da34a4225975 100644 --- a/drivers/gpu/arm/valhall/mali_kbase.h +++ b/drivers/gpu/arm/valhall/mali_kbase.h @@ -45,20 +45,11 @@ #include "mali_kbase_mem_profile_debugfs.h" #include "mali_kbase_gpuprops.h" #include -#if !MALI_USE_CSF -#include "mali_kbase_debug_job_fault.h" -#include "mali_kbase_jd_debugfs.h" -#include "mali_kbase_jm.h" -#include "mali_kbase_js.h" -#else /* !MALI_USE_CSF */ #include "csf/mali_kbase_debug_csf_fault.h" -#endif /* MALI_USE_CSF */ #include "ipa/mali_kbase_ipa.h" -#if MALI_USE_CSF #include "csf/mali_kbase_csf.h" -#endif #include "mali_linux_trace.h" @@ -84,7 +75,6 @@ #define KBASE_DRV_NAME "mali" #define KBASE_TIMELINE_NAME KBASE_DRV_NAME ".timeline" -#if MALI_USE_CSF /* Physical memory group ID for CSF user I/O. */ #define KBASE_MEM_GROUP_CSF_IO BASE_MEM_GROUP_DEFAULT @@ -92,7 +82,6 @@ /* Physical memory group ID for CSF firmware. */ #define KBASE_MEM_GROUP_CSF_FW BASE_MEM_GROUP_DEFAULT -#endif /* Physical memory group ID for a special page which can alias several regions. */ @@ -118,13 +107,6 @@ struct kbase_device *kbase_device_alloc(void); */ int kbase_device_misc_init(struct kbase_device *kbdev); void kbase_device_misc_term(struct kbase_device *kbdev); - -#if !MALI_USE_CSF -void kbase_enable_quick_reset(struct kbase_device *kbdev); -void kbase_disable_quick_reset(struct kbase_device *kbdev); -bool kbase_is_quick_reset_enabled(struct kbase_device *kbdev); -#endif - void kbase_device_free(struct kbase_device *kbdev); int kbase_device_has_feature(struct kbase_device *kbdev, u32 feature); @@ -242,162 +224,7 @@ void registers_unmap(struct kbase_device *kbdev); int kbase_device_coherency_init(struct kbase_device *kbdev); -#if !MALI_USE_CSF -/** - * kbase_jd_init() - Initialize kbase context for job dispatcher. - * @kctx: Pointer to the kbase context to be initialized. - * - * This function must be called only when a kbase context is instantiated. - * - * Return: 0 on success. - */ -int kbase_jd_init(struct kbase_context *kctx); -void kbase_jd_exit(struct kbase_context *kctx); - -/** - * kbase_jd_submit - Submit atoms to the job dispatcher - * - * @kctx: The kbase context to submit to - * @user_addr: The address in user space of the struct base_jd_atom array - * @nr_atoms: The number of atoms in the array - * @stride: sizeof(struct base_jd_atom) - * @uk6_atom: true if the atoms are legacy atoms (struct base_jd_atom_v2_uk6) - * - * Return: 0 on success or error code - */ -int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_atoms, u32 stride, - bool uk6_atom); - -/** - * kbase_jd_done_worker - Handle a job completion - * @data: a &struct work_struct - * - * This function requeues the job from the runpool (if it was soft-stopped or - * removed from NEXT registers). - * - * Removes it from the system if it finished/failed/was cancelled. - * - * Resolves dependencies to add dependent jobs to the context, potentially - * starting them if necessary (which may add more references to the context) - * - * Releases the reference to the context from the no-longer-running job. - * - * Handles retrying submission outside of IRQ context if it failed from within - * IRQ context. - */ -void kbase_jd_done_worker(struct work_struct *data); - -void kbase_jd_done(struct kbase_jd_atom *katom, unsigned int slot_nr, ktime_t *end_timestamp, - kbasep_js_atom_done_code done_code); -void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom); -void kbase_jd_zap_context(struct kbase_context *kctx); - -/* - * kbase_jd_done_nolock - Perform the necessary handling of an atom that has completed - * the execution. - * - * @katom: Pointer to the atom that completed the execution - * @post_immediately: Flag indicating that completion event can be posted - * immediately for @katom and the other atoms depdendent - * on @katom which also completed execution. The flag is - * false only for the case where the function is called by - * kbase_jd_done_worker() on the completion of atom running - * on the GPU. - * - * Note that if this is a soft-job that has had kbase_prepare_soft_job called on it then the caller - * is responsible for calling kbase_finish_soft_job *before* calling this function. - * - * The caller must hold the kbase_jd_context.lock. - */ -bool kbase_jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately); - -void kbase_jd_free_external_resources(struct kbase_jd_atom *katom); -void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom); - -/** - * kbase_job_done - Process completed jobs from job interrupt - * @kbdev: Pointer to the kbase device. - * @done: Bitmask of done or failed jobs, from JOB_IRQ_STAT register - * - * This function processes the completed, or failed, jobs from the GPU job - * slots, for the bits set in the @done bitmask. - * - * The hwaccess_lock must be held when calling this function. - */ -void kbase_job_done(struct kbase_device *kbdev, u32 done); - -/** - * kbase_job_slot_ctx_priority_check_locked(): - Check for lower priority atoms - * and soft stop them - * @kctx: Pointer to context to check. - * @katom: Pointer to priority atom. - * - * Atoms from @kctx on the same job slot as @katom, which have lower priority - * than @katom will be soft stopped and put back in the queue, so that atoms - * with higher priority can run. - * - * The hwaccess_lock must be held when calling this function. - */ -void kbase_job_slot_ctx_priority_check_locked(struct kbase_context *kctx, - struct kbase_jd_atom *katom); - -/** - * kbase_job_slot_softstop - Soft-stop the specified job slot - * - * @kbdev: The kbase device - * @js: The job slot to soft-stop - * @target_katom: The job that should be soft-stopped (or NULL for any job) - * Context: - * The job slot lock must be held when calling this function. - * The job slot must not already be in the process of being soft-stopped. - * - * Where possible any job in the next register is evicted before the soft-stop. - */ -void kbase_job_slot_softstop(struct kbase_device *kbdev, unsigned int js, - struct kbase_jd_atom *target_katom); - -void kbase_job_slot_softstop_swflags(struct kbase_device *kbdev, unsigned int js, - struct kbase_jd_atom *target_katom, u32 sw_flags); - -/** - * kbase_job_check_enter_disjoint - potentiall enter disjoint mode - * @kbdev: kbase device - * @action: the event which has occurred - * @core_reqs: core requirements of the atom - * @target_katom: the atom which is being affected - * - * For a certain soft-stop action, work out whether to enter disjoint - * state. - * - * This does not register multiple disjoint events if the atom has already - * started a disjoint period - * - * @core_reqs can be supplied as 0 if the atom had not started on the hardware - * (and so a 'real' soft/hard-stop was not required, but it still interrupted - * flow, perhaps on another context) - * - * kbase_job_check_leave_disjoint() should be used to end the disjoint - * state when the soft/hard-stop action is complete - */ -void kbase_job_check_enter_disjoint(struct kbase_device *kbdev, u32 action, - base_jd_core_req core_reqs, struct kbase_jd_atom *target_katom); - -/** - * kbase_job_check_leave_disjoint - potentially leave disjoint state - * @kbdev: kbase device - * @target_katom: atom which is finishing - * - * Work out whether to leave disjoint state when finishing an atom that was - * originated by kbase_job_check_enter_disjoint(). - */ -void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, struct kbase_jd_atom *target_katom); - -#endif /* !MALI_USE_CSF */ - void kbase_event_post(struct kbase_context *kctx, struct kbase_jd_atom *event); -#if !MALI_USE_CSF -int kbase_event_dequeue(struct kbase_context *kctx, struct base_jd_event_v2 *uevent); -#endif /* !MALI_USE_CSF */ int kbase_event_pending(struct kbase_context *kctx); int kbase_event_init(struct kbase_context *kctx); void kbase_event_close(struct kbase_context *kctx); @@ -449,22 +276,6 @@ static inline void kbase_free_user_buffer(struct kbase_debug_copy_buffer *buffer } } -#if !MALI_USE_CSF -int kbase_process_soft_job(struct kbase_jd_atom *katom); -int kbase_prepare_soft_job(struct kbase_jd_atom *katom); -void kbase_finish_soft_job(struct kbase_jd_atom *katom); -void kbase_cancel_soft_job(struct kbase_jd_atom *katom); -void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev); -void kbasep_remove_waiting_soft_job(struct kbase_jd_atom *katom); -#if IS_ENABLED(CONFIG_SYNC_FILE) -void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom); -#endif -int kbase_soft_event_update(struct kbase_context *kctx, u64 event, unsigned char new_status); - -void kbasep_soft_job_timeout_worker(struct timer_list *timer); -void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt); -#endif /* !MALI_USE_CSF */ - void kbasep_as_do_poke(struct work_struct *work); /** @@ -549,7 +360,6 @@ void kbase_pm_metrics_start(struct kbase_device *kbdev); */ void kbase_pm_metrics_stop(struct kbase_device *kbdev); -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) /** * kbase_pm_handle_runtime_suspend - Handle the runtime suspend of GPU * @@ -587,43 +397,6 @@ int kbase_pm_handle_runtime_suspend(struct kbase_device *kbdev); * Return: 0 if the wake up was successful. */ int kbase_pm_force_mcu_wakeup_after_sleep(struct kbase_device *kbdev); -#endif - -#if !MALI_USE_CSF -/** - * kbase_jd_atom_id - Return the atom's ID, as was originally supplied by userspace in - * base_jd_atom::atom_number - * @kctx: KBase context pointer - * @katom: Atome for which to return ID - * - * Return: the atom's ID. - */ -static inline unsigned int kbase_jd_atom_id(struct kbase_context *kctx, - const struct kbase_jd_atom *katom) -{ - unsigned int result; - - KBASE_DEBUG_ASSERT(kctx); - KBASE_DEBUG_ASSERT(katom); - KBASE_DEBUG_ASSERT(katom->kctx == kctx); - - result = katom - &kctx->jctx.atoms[0]; - KBASE_DEBUG_ASSERT(result <= BASE_JD_ATOM_COUNT); - return result; -} - -/** - * kbase_jd_atom_from_id - Return the atom structure for the given atom ID - * @kctx: Context pointer - * @id: ID of atom to retrieve - * - * Return: Pointer to struct kbase_jd_atom associated with the supplied ID - */ -static inline struct kbase_jd_atom *kbase_jd_atom_from_id(struct kbase_context *kctx, int id) -{ - return &kctx->jctx.atoms[id]; -} -#endif /* !MALI_USE_CSF */ /** * kbase_disjoint_init - Initialize the disjoint state @@ -730,8 +503,6 @@ int kbase_device_pcm_dev_init(struct kbase_device *const kbdev); */ void kbase_device_pcm_dev_term(struct kbase_device *const kbdev); -#if MALI_USE_CSF - /** * kbasep_adjust_prioritized_process() - Adds or removes the specified PID from * the list of prioritized processes. @@ -744,8 +515,6 @@ void kbase_device_pcm_dev_term(struct kbase_device *const kbdev); */ bool kbasep_adjust_prioritized_process(struct kbase_device *kbdev, bool add, uint32_t tgid); -#endif /* MALI_USE_CSF */ - /** * KBASE_DISJOINT_STATE_INTERLEAVED_CONTEXT_COUNT_THRESHOLD - If a job is soft stopped * and the number of contexts is >= this value it is reported as a disjoint event diff --git a/drivers/gpu/arm/valhall/mali_kbase_config.c b/drivers/gpu/arm/valhall/mali_kbase_config.c index 37dbca129f86..c90952dd9d44 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_config.c +++ b/drivers/gpu/arm/valhall/mali_kbase_config.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2015, 2017, 2020-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -62,43 +62,3 @@ void kbasep_platform_device_late_term(struct kbase_device *kbdev) if (platform_funcs_p && platform_funcs_p->platform_late_term_func) platform_funcs_p->platform_late_term_func(kbdev); } - -#if !MALI_USE_CSF -int kbasep_platform_context_init(struct kbase_context *kctx) -{ - struct kbase_platform_funcs_conf *platform_funcs_p; - - platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; - if (platform_funcs_p && platform_funcs_p->platform_handler_context_init_func) - return platform_funcs_p->platform_handler_context_init_func(kctx); - - return 0; -} - -void kbasep_platform_context_term(struct kbase_context *kctx) -{ - struct kbase_platform_funcs_conf *platform_funcs_p; - - platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; - if (platform_funcs_p && platform_funcs_p->platform_handler_context_term_func) - platform_funcs_p->platform_handler_context_term_func(kctx); -} - -void kbasep_platform_event_atom_submit(struct kbase_jd_atom *katom) -{ - struct kbase_platform_funcs_conf *platform_funcs_p; - - platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; - if (platform_funcs_p && platform_funcs_p->platform_handler_atom_submit_func) - platform_funcs_p->platform_handler_atom_submit_func(katom); -} - -void kbasep_platform_event_atom_complete(struct kbase_jd_atom *katom) -{ - struct kbase_platform_funcs_conf *platform_funcs_p; - - platform_funcs_p = (struct kbase_platform_funcs_conf *)PLATFORM_FUNCS; - if (platform_funcs_p && platform_funcs_p->platform_handler_atom_complete_func) - platform_funcs_p->platform_handler_atom_complete_func(katom); -} -#endif diff --git a/drivers/gpu/arm/valhall/mali_kbase_config.h b/drivers/gpu/arm/valhall/mali_kbase_config.h index 2f9e28aaec9a..aefa8e631650 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_config.h +++ b/drivers/gpu/arm/valhall/mali_kbase_config.h @@ -33,14 +33,6 @@ /* Forward declaration of struct kbase_device */ struct kbase_device; -#if !MALI_USE_CSF -/* Forward declaration of struct kbase_context */ -struct kbase_context; - -/* Forward declaration of struct kbase_atom */ -struct kbase_jd_atom; -#endif - /** * struct kbase_platform_funcs_conf - Specifies platform integration function * pointers for DDK events such as device init and term. @@ -103,57 +95,6 @@ struct kbase_platform_funcs_conf { * can be accessed (and possibly terminated) in here. */ void (*platform_late_term_func)(struct kbase_device *kbdev); - -#if !MALI_USE_CSF - /** - * @platform_handler_context_init_func: platform specific handler for - * when a new kbase_context is created. - * @kctx - kbase_context pointer - * - * Returns 0 on success, negative error code otherwise. - * - * Function pointer for platform specific initialization of a kernel - * context or NULL if not required. Called at the last stage of kernel - * context initialization. - */ - int (*platform_handler_context_init_func)(struct kbase_context *kctx); - /** - * @platform_handler_context_term_func: platform specific handler for - * when a kbase_context is terminated. - * @kctx - kbase_context pointer - * - * Function pointer for platform specific termination of a kernel - * context or NULL if not required. Called at the first stage of kernel - * context termination. - */ - void (*platform_handler_context_term_func)(struct kbase_context *kctx); - /** - * @platform_handler_atom_submit_func: platform specific handler for - * when a kbase_jd_atom is submitted. - * @katom - kbase_jd_atom pointer - * - * Function pointer for platform specific handling at the point when an - * atom is submitted to the GPU or set to NULL if not required. The - * function cannot assume that it is running in a process context. - * - * Context: The caller must hold the hwaccess_lock. Function must be - * runnable in an interrupt context. - */ - void (*platform_handler_atom_submit_func)(struct kbase_jd_atom *katom); - /** - * @platform_handler_atom_complete_func: platform specific handler for - * when a kbase_jd_atom completes. - * @katom - kbase_jd_atom pointer - * - * Function pointer for platform specific handling at the point when an - * atom stops running on the GPU or set to NULL if not required. The - * function cannot assume that it is running in a process context. - * - * Context: The caller must hold the hwaccess_lock. Function must be - * runnable in an interrupt context. - */ - void (*platform_handler_atom_complete_func)(struct kbase_jd_atom *katom); -#endif }; /* @@ -232,7 +173,7 @@ struct kbase_pm_callback_conf { * to the OS from within this function. * The runtime calls can be triggered by calls from @ref power_off_callback * and @ref power_on_callback. - * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * Note: for linux the kernel must have CONFIG_PM enabled to use this feature. * * @return 0 on success, else int error code. */ @@ -243,21 +184,21 @@ struct kbase_pm_callback_conf { * The runtime power management callbacks @ref power_runtime_off_callback * and @ref power_runtime_on_callback should no longer be called by the * OS on completion of this function. - * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * Note: for linux the kernel must have CONFIG_PM enabled to use this feature. */ void (*power_runtime_term_callback)(struct kbase_device *kbdev); /** Callback for runtime power-off power management callback * * For linux this callback will be called by the kernel runtime_suspend callback. - * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * Note: for linux the kernel must have CONFIG_PM enabled to use this feature. */ void (*power_runtime_off_callback)(struct kbase_device *kbdev); /** Callback for runtime power-on power management callback * * For linux this callback will be called by the kernel runtime_resume callback. - * Note: for linux the kernel must have CONFIG_PM_RUNTIME enabled to use this feature. + * Note: for linux the kernel must have CONFIG_PM enabled to use this feature. * * @return 0 on success, else OS error code. */ @@ -281,7 +222,7 @@ struct kbase_pm_callback_conf { * This callback is optional and if not provided regular autosuspend * will be triggered. * - * Note: The Linux kernel must have CONFIG_PM_RUNTIME enabled to use + * Note: The Linux kernel must have CONFIG_PM enabled to use * this feature. * * Return 0 if GPU can be suspended, positive value if it can not be @@ -316,7 +257,7 @@ struct kbase_pm_callback_conf { * GPU registers still remain accessible until @power_off_callback gets * invoked later on the expiry of auto-suspend timer. * - * Note: The Linux kernel must have CONFIG_PM_RUNTIME enabled to use + * Note: The Linux kernel must have CONFIG_PM enabled to use * this feature. */ void (*power_runtime_gpu_idle_callback)(struct kbase_device *kbdev); @@ -339,7 +280,7 @@ struct kbase_pm_callback_conf { * to avoid a potential deadlock due to the runtime suspend happening * simultaneously from some other thread. * - * Note: The Linux kernel must have CONFIG_PM_RUNTIME enabled to use + * Note: The Linux kernel must have CONFIG_PM enabled to use * this feature. */ void (*power_runtime_gpu_active_callback)(struct kbase_device *kbdev); @@ -514,56 +455,6 @@ int kbasep_platform_device_late_init(struct kbase_device *kbdev); */ void kbasep_platform_device_late_term(struct kbase_device *kbdev); -#if !MALI_USE_CSF -/** - * kbasep_platform_context_init - Platform specific callback when a kernel - * context is created - * @kctx: kbase_context pointer - * - * Function calls a platform defined routine if specified in the configuration - * attributes. The routine can initialize any per kernel context structures - * that are required for the GPU block to function. - * - * Return: 0 if no errors were encountered. Negative error code otherwise. - */ -int kbasep_platform_context_init(struct kbase_context *kctx); - -/** - * kbasep_platform_context_term - Platform specific callback when a kernel - * context is terminated - * @kctx: kbase_context pointer - * - * Function calls a platform defined routine if specified in the configuration - * attributes. The routine should terminate any per kernel context structures - * created as part of &kbasep_platform_context_init. - * - */ -void kbasep_platform_context_term(struct kbase_context *kctx); - -/** - * kbasep_platform_event_atom_submit - Platform specific callback when an atom - * is submitted to the GPU - * @katom: kbase_jd_atom pointer - * - * Function calls a platform defined routine if specified in the configuration - * attributes. The routine should not assume that it is in a process context. - * - * Return: 0 if no errors were encountered. Negative error code otherwise. - */ -void kbasep_platform_event_atom_submit(struct kbase_jd_atom *katom); - -/** - * kbasep_platform_event_atom_complete - Platform specific callback when an atom - * has stopped running on the GPU - * @katom: kbase_jd_atom pointer - * - * Function calls a platform defined routine if specified in the configuration - * attributes. The routine should not assume that it is in a process context. - * - */ -void kbasep_platform_event_atom_complete(struct kbase_jd_atom *katom); -#endif - #ifndef CONFIG_OF /** * kbase_platform_register - Register a platform device for the GPU diff --git a/drivers/gpu/arm/valhall/mali_kbase_config_defaults.h b/drivers/gpu/arm/valhall/mali_kbase_config_defaults.h index 06298c5d1509..76b2ce2c6895 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_config_defaults.h +++ b/drivers/gpu/arm/valhall/mali_kbase_config_defaults.h @@ -314,13 +314,6 @@ enum { /* MAX allowed timeout value(ms) on host side, should be less than ANR timeout */ #define MAX_TIMEOUT_MS (4500) -#if !MALI_USE_CSF -/* Default number of milliseconds given for other jobs on the GPU to be - * soft-stopped when the GPU needs to be reset. - */ -#define JM_DEFAULT_RESET_TIMEOUT_MS (1) /* 1 ms */ -#endif /* !MALI_USE_CSF */ - /* Timeout for polling the GPU PRFCNT_ACTIVE bit in clock cycles. * * Based on 120s timeout at 100MHz, based on original MAX_LOOPS value. diff --git a/drivers/gpu/arm/valhall/mali_kbase_core_linux.c b/drivers/gpu/arm/valhall/mali_kbase_core_linux.c index bc7c487611e9..b7913d22ebbc 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/valhall/mali_kbase_core_linux.c @@ -41,28 +41,20 @@ #include "mali_kbase_debugfs_helper.h" #include #include -#if !MALI_USE_CSF -#include -#endif /* !MALI_USE_CSF */ #ifdef CONFIG_MALI_VALHALL_PRFCNT_SET_SELECT_VIA_DEBUG_FS #include #endif #include #include -#if !MALI_USE_CSF -#include "mali_kbase_kinstr_jm.h" -#endif #include "hwcnt/mali_kbase_hwcnt_context.h" #include "hwcnt/mali_kbase_hwcnt_virtualizer.h" #include "mali_kbase_kinstr_prfcnt.h" -#if MALI_USE_CSF #include "csf/mali_kbase_csf_firmware.h" #include "csf/mali_kbase_csf_tiler_heap.h" #include "csf/mali_kbase_csf_csg_debugfs.h" #include "csf/mali_kbase_csf_cpu_queue.h" #include "csf/mali_kbase_csf_event.h" #include "csf/mali_kbase_csf_ne_debugfs.h" -#endif #include "arbiter/mali_kbase_arbiter_pm.h" #include "mali_kbase_cs_experimental.h" @@ -150,7 +142,6 @@ struct mali_kbase_capability_def { * in the table. Less efficient but potentially safer. */ static const struct mali_kbase_capability_def kbase_caps_table[MALI_KBASE_NUM_CAPS] = { -#if MALI_USE_CSF { 1, 0 }, /* SYSTEM_MONITOR */ { 1, 0 }, /* JIT_PRESSURE_LIMIT */ { 1, 22 }, /* QUERY_MEM_DONT_NEED */ @@ -169,26 +160,6 @@ static const struct mali_kbase_capability_def kbase_caps_table[MALI_KBASE_NUM_CA { 1, 32 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_7 */ { U16_MAX, U16_MAX }, /* REJECT_ALLOC_MEM_UNUSED_BIT_29 */ { 1, 35 } /* CSG_CS_USER_PAGE_ALLOCATION */ -#else - { 11, 15 }, /* SYSTEM_MONITOR */ - { 11, 25 }, /* JIT_PRESSURE_LIMIT */ - { 11, 40 }, /* QUERY_MEM_DONT_NEED */ - { 11, 2 }, /* QUERY_MEM_GROW_ON_GPF */ - { 11, 2 }, /* QUERY_MEM_PROTECTED */ - { 11, 43 }, /* QUERY_MEM_IMPORT_SYNC_ON_MAP_UNMAP */ - { 11, 43 }, /* QUERY_MEM_KERNEL_SYNC */ - { 11, 44 }, /* QUERY_MEM_SAME_VA */ - { 11, 46 }, /* REJECT_ALLOC_MEM_DONT_NEED */ - { 11, 46 }, /* REJECT_ALLOC_MEM_PROTECTED_IN_UNPROTECTED_ALLOCS */ - { 11, 46 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_8 */ - { 11, 46 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_19 */ - { U16_MAX, U16_MAX }, /* REJECT_ALLOC_MEM_UNUSED_BIT_20 */ - { 11, 48 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_27 */ - { 11, 48 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_5 */ - { 11, 48 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_7 */ - { 11, 48 }, /* REJECT_ALLOC_MEM_UNUSED_BIT_29 */ - { U16_MAX, U16_MAX } /* CSG_CS_USER_PAGE_ALLOCATION */ -#endif }; #if (KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE) @@ -496,7 +467,6 @@ static int get_irqs(struct kbase_device *kbdev, struct platform_device *pdev) return 0; } -#if MALI_USE_CSF /** * get_irq_irqaw - Get interrupt information from the device tree. * @@ -531,7 +501,6 @@ static int get_irq_irqaw(struct kbase_device *kbdev, struct platform_device *pde return 0; } -#endif /* MALI_USE_CSF */ int kbase_get_irqs(struct kbase_device *kbdev) { @@ -543,7 +512,6 @@ int kbase_get_irqs(struct kbase_device *kbdev) if (!result) return result; -#if MALI_USE_CSF /* return error if any one of the GPU, JOB, MMU * interrupts missing. Don't lookup for IRQAW. */ @@ -553,7 +521,6 @@ int kbase_get_irqs(struct kbase_device *kbdev) } result = get_irq_irqaw(kbdev, pdev); -#endif /* MALI_USE_CSF */ if (result) dev_err(kbdev->dev, "Invalid or No interrupt resources"); @@ -811,11 +778,6 @@ static int kbase_api_set_flags(struct kbase_file *kfile, struct kbase_ioctl_set_ if (mali_kbase_supports_system_monitor(api_version)) { err = kbase_file_create_kctx(kfile, flags->create_flags); } else { -#if !MALI_USE_CSF - struct kbasep_js_kctx_info *js_kctx_info = NULL; - unsigned long irq_flags = 0; -#endif - /* If setup is incomplete (e.g. because the API version * wasn't set) then we have to give up. */ @@ -823,35 +785,15 @@ static int kbase_api_set_flags(struct kbase_file *kfile, struct kbase_ioctl_set_ if (unlikely(!kctx)) return -EPERM; -#if MALI_USE_CSF - /* On CSF GPUs Job Manager interface isn't used to submit jobs + /* On CSF GPUs Job Manager interface isn't used to submit jobs * (there are no job slots). So the legacy job manager path to * submit jobs needs to remain disabled for CSF GPUs. */ -#else - js_kctx_info = &kctx->jctx.sched_info; - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags); - /* Translate the flags */ - if ((flags->create_flags & BASE_CONTEXT_SYSTEM_MONITOR_SUBMIT_DISABLED) == 0) - kbase_ctx_flag_clear(kctx, KCTX_SUBMIT_DISABLED); - - spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); -#endif } return err; } -#if !MALI_USE_CSF -static int kbase_api_job_submit(struct kbase_context *kctx, struct kbase_ioctl_job_submit *submit) -{ - return kbase_jd_submit(kctx, u64_to_user_ptr(submit->addr), submit->nr_atoms, - submit->stride, false); -} -#endif /* !MALI_USE_CSF */ - static int kbase_api_get_gpuprops(struct kbase_file *kfile, struct kbase_ioctl_get_gpuprops *get_props) { @@ -875,15 +817,6 @@ static int kbase_api_get_gpuprops(struct kbase_file *kfile, return (int)kprops->prop_buffer_size; } -#if !MALI_USE_CSF -static int kbase_api_post_term(struct kbase_context *kctx) -{ - kbase_event_close(kctx); - return 0; -} -#endif /* !MALI_USE_CSF */ - -#if MALI_USE_CSF static int kbase_api_mem_alloc_ex(struct kbase_context *kctx, union kbase_ioctl_mem_alloc_ex *alloc_ex) { @@ -994,46 +927,6 @@ static int kbase_api_mem_alloc(struct kbase_context *kctx, union kbase_ioctl_mem return ret; } -#else -static int kbase_api_mem_alloc(struct kbase_context *kctx, union kbase_ioctl_mem_alloc *alloc) -{ - struct kbase_va_region *reg; - base_mem_alloc_flags flags = alloc->in.flags; - u64 gpu_va; - - /* Calls to this function are inherently asynchronous, with respect to - * MMU operations. - */ - const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; - - if (!kbase_mem_allow_alloc(kctx)) - return -EINVAL; - - if (flags & BASE_MEM_FLAGS_KERNEL_ONLY) - return -ENOMEM; - - /* Force SAME_VA if a 64-bit client. - * The only exception is GPU-executable memory if an EXEC_VA zone - * has been initialized. In that case, GPU-executable memory may - * or may not be SAME_VA. - */ - if ((!kbase_ctx_flag(kctx, KCTX_COMPAT)) && kbase_ctx_flag(kctx, KCTX_FORCE_SAME_VA)) { - if (!(flags & BASE_MEM_PROT_GPU_EX) || !kbase_has_exec_va_zone(kctx)) - flags |= BASE_MEM_SAME_VA; - } - - reg = kbase_mem_alloc(kctx, alloc->in.va_pages, alloc->in.commit_pages, alloc->in.extension, - &flags, &gpu_va, mmu_sync_info); - - if (!reg) - return -ENOMEM; - - alloc->out.flags = flags; - alloc->out.gpu_va = gpu_va; - - return 0; -} -#endif /* MALI_USE_CSF */ static int kbase_api_mem_query(struct kbase_context *kctx, union kbase_ioctl_mem_query *query) { @@ -1045,13 +938,6 @@ static int kbase_api_mem_free(struct kbase_context *kctx, struct kbase_ioctl_mem return kbase_mem_free(kctx, free->gpu_addr); } -#if !MALI_USE_CSF -static int kbase_api_kinstr_jm_fd(struct kbase_context *kctx, union kbase_kinstr_jm_fd *arg) -{ - return kbase_kinstr_jm_get_fd(kctx->kinstr_jm, arg); -} -#endif - static int kbase_api_get_cpu_gpu_timeinfo(struct kbase_context *kctx, union kbase_ioctl_get_cpu_gpu_timeinfo *timeinfo) { @@ -1060,6 +946,9 @@ static int kbase_api_get_cpu_gpu_timeinfo(struct kbase_context *kctx, u64 timestamp = 0; u64 cycle_cnt = 0; + if (kbase_io_is_aw_removed(kctx->kbdev)) + return -ENODEV; + kbase_pm_context_active(kctx->kbdev); kbase_backend_get_gpu_time(kctx->kbdev, @@ -1137,7 +1026,7 @@ static int kbase_api_mem_exec_init(struct kbase_context *kctx, static int kbase_api_mem_sync(struct kbase_context *kctx, struct kbase_ioctl_mem_sync *sync) { - struct basep_syncset sset = { .mem_handle.basep.handle = sync->handle, + struct basep_syncset sset = { .gpu_va = sync->gpu_va, .user_addr = sync->user_addr, .size = sync->size, .type = sync->type }; @@ -1327,17 +1216,6 @@ static int kbase_api_mem_profile_add(struct kbase_context *kctx, return kbasep_mem_profile_debugfs_insert(kctx, buf, data->len); } -#if !MALI_USE_CSF -static int kbase_api_soft_event_update(struct kbase_context *kctx, - struct kbase_ioctl_soft_event_update *update) -{ - if (update->flags != 0) - return -EINVAL; - - return kbase_soft_event_update(kctx, update->event, update->new_status); -} -#endif /* !MALI_USE_CSF */ - static int kbase_api_sticky_resource_map(struct kbase_context *kctx, struct kbase_ioctl_sticky_resource_map *map) { @@ -1426,7 +1304,6 @@ static int kbase_api_tlstream_stats(struct kbase_context *kctx, } #endif /* MALI_UNIT_TEST */ -#if MALI_USE_CSF static int kbasep_cs_event_signal(struct kbase_context *kctx) { kbase_csf_event_signal_notify_gpu(kctx); @@ -1703,8 +1580,16 @@ static int kbasep_ioctl_cs_cpu_queue_dump(struct kbase_context *kctx, return kbase_csf_cpu_queue_dump_buffer(kctx, cpu_queue_info->buffer, cpu_queue_info->size); } +#if MALI_UNIT_TEST +int kbase_ioctl_read_user_page(struct kbase_context *kctx, + union kbase_ioctl_read_user_page *user_page); + +int kbase_ioctl_read_user_page(struct kbase_context *kctx, + union kbase_ioctl_read_user_page *user_page) +#else static int kbase_ioctl_read_user_page(struct kbase_context *kctx, union kbase_ioctl_read_user_page *user_page) +#endif { struct kbase_device *kbdev = kctx->kbdev; unsigned long flags; @@ -1714,7 +1599,7 @@ static int kbase_ioctl_read_user_page(struct kbase_context *kctx, return -EINVAL; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - if (!kbase_io_is_gpu_powered(kbdev) || kbase_io_is_aw_removed(kbdev)) + if (!kbase_io_has_gpu(kbdev)) user_page->out.val_lo = POWER_DOWN_LATEST_FLUSH_VALUE; else user_page->out.val_lo = kbase_reg_read32(kbdev, USER_ENUM(LATEST_FLUSH)); @@ -1723,19 +1608,15 @@ static int kbase_ioctl_read_user_page(struct kbase_context *kctx, return 0; } -#endif /* MALI_USE_CSF */ +#if MALI_UNIT_TEST +KBASE_EXPORT_TEST_API(kbase_ioctl_read_user_page); +#endif static int kbasep_ioctl_context_priority_check(struct kbase_context *kctx, struct kbase_ioctl_context_priority_check *priority_check) { -#if MALI_USE_CSF priority_check->priority = kbase_csf_priority_check(kctx->kbdev, priority_check->priority); -#else - base_jd_prio req_priority = (base_jd_prio)priority_check->priority; - - priority_check->priority = (u8)kbase_js_priority_check(kctx->kbdev, req_priority); -#endif return 0; } @@ -1811,27 +1692,14 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* Normal ioctls */ switch (cmd) { -#if !MALI_USE_CSF - case KBASE_IOCTL_JOB_SUBMIT: - KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_JOB_SUBMIT, kbase_api_job_submit, - struct kbase_ioctl_job_submit, kctx); - break; -#endif /* !MALI_USE_CSF */ -#if !MALI_USE_CSF - case KBASE_IOCTL_POST_TERM: - KBASE_HANDLE_IOCTL(KBASE_IOCTL_POST_TERM, kbase_api_post_term, kctx); - break; -#endif /* !MALI_USE_CSF */ case KBASE_IOCTL_MEM_ALLOC: KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_ALLOC, kbase_api_mem_alloc, union kbase_ioctl_mem_alloc, kctx); break; -#if MALI_USE_CSF case KBASE_IOCTL_MEM_ALLOC_EX: KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_ALLOC_EX, kbase_api_mem_alloc_ex, union kbase_ioctl_mem_alloc_ex, kctx); break; -#endif case KBASE_IOCTL_MEM_QUERY: KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_MEM_QUERY, kbase_api_mem_query, union kbase_ioctl_mem_query, kctx); @@ -1910,13 +1778,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct kbase_ioctl_mem_profile_add, kctx); break; -#if !MALI_USE_CSF - case KBASE_IOCTL_SOFT_EVENT_UPDATE: - KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_SOFT_EVENT_UPDATE, kbase_api_soft_event_update, - struct kbase_ioctl_soft_event_update, kctx); - break; -#endif /* !MALI_USE_CSF */ - case KBASE_IOCTL_STICKY_RESOURCE_MAP: KBASE_HANDLE_IOCTL_IN(KBASE_IOCTL_STICKY_RESOURCE_MAP, kbase_api_sticky_resource_map, @@ -1929,12 +1790,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; /* Instrumentation. */ -#if !MALI_USE_CSF - case KBASE_IOCTL_KINSTR_JM_FD: - KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_KINSTR_JM_FD, kbase_api_kinstr_jm_fd, - union kbase_kinstr_jm_fd, kctx); - break; -#endif case KBASE_IOCTL_GET_CPU_GPU_TIMEINFO: KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_GET_CPU_GPU_TIMEINFO, kbase_api_get_cpu_gpu_timeinfo, @@ -1946,7 +1801,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct kbase_ioctl_hwcnt_values, kctx); break; #endif /* CONFIG_MALI_VALHALL_NO_MALI */ -#if MALI_USE_CSF case KBASE_IOCTL_CS_EVENT_SIGNAL: KBASE_HANDLE_IOCTL(KBASE_IOCTL_CS_EVENT_SIGNAL, kbasep_cs_event_signal, kctx); break; @@ -2042,7 +1896,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) KBASE_HANDLE_IOCTL_INOUT(KBASE_IOCTL_READ_USER_PAGE, kbase_ioctl_read_user_page, union kbase_ioctl_read_user_page, kctx); break; -#endif /* MALI_USE_CSF */ #if MALI_UNIT_TEST case KBASE_IOCTL_TLSTREAM_STATS: KBASE_HANDLE_IOCTL_OUT(KBASE_IOCTL_TLSTREAM_STATS, kbase_api_tlstream_stats, @@ -2066,7 +1919,6 @@ static long kbase_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOIOCTLCMD; } -#if MALI_USE_CSF static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct kbase_file *const kfile = filp->private_data; @@ -2110,54 +1962,6 @@ static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, lof return data_size; } -#else /* MALI_USE_CSF */ -static ssize_t kbase_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) -{ - struct kbase_file *const kfile = filp->private_data; - struct kbase_context *const kctx = kbase_file_get_kctx_if_setup_complete(kfile); - struct base_jd_event_v2 uevent; - int out_count = 0; - - CSTD_UNUSED(f_pos); - - if (unlikely(!kctx)) - return -EPERM; - - if (count < sizeof(uevent)) - return -ENOBUFS; - - memset(&uevent, 0, sizeof(uevent)); - - do { - while (kbase_event_dequeue(kctx, &uevent)) { - if (out_count > 0) - goto out; - - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - - if (wait_event_interruptible(kctx->event_queue, - kbase_event_pending(kctx)) != 0) - return -ERESTARTSYS; - } - if (uevent.event_code == BASE_JD_EVENT_DRV_TERMINATED) { - if (out_count == 0) - return -EPIPE; - goto out; - } - - if (copy_to_user(buf, &uevent, sizeof(uevent)) != 0) - return -EFAULT; - - buf += sizeof(uevent); - out_count++; - count -= sizeof(uevent); - } while (count >= sizeof(uevent)); - -out: - return out_count * sizeof(uevent); -} -#endif /* MALI_USE_CSF */ static __poll_t kbase_poll(struct file *filp, poll_table *wait) { @@ -2193,7 +1997,6 @@ void kbase_event_wakeup(struct kbase_context *kctx) KBASE_EXPORT_TEST_API(kbase_event_wakeup); -#if MALI_USE_CSF int kbase_event_pending(struct kbase_context *kctx) { KBASE_DEBUG_ASSERT(kctx); @@ -2204,17 +2007,6 @@ int kbase_event_pending(struct kbase_context *kctx) return (atomic_read(&kctx->event_count) != 0) || kbase_csf_event_error_pending(kctx) || kbase_csf_cpu_queue_dump_needed(kctx); } -#else -int kbase_event_pending(struct kbase_context *kctx) -{ - KBASE_DEBUG_ASSERT(kctx); - - if (unlikely(!kctx)) - return -EPERM; - - return (atomic_read(&kctx->event_count) != 0) || (atomic_read(&kctx->event_closed) != 0); -} -#endif KBASE_EXPORT_TEST_API(kbase_event_pending); @@ -2396,10 +2188,9 @@ static ssize_t core_mask_show(struct device *dev, struct device_attribute *attr, { struct kbase_device *kbdev; unsigned long flags; + u64 debug_mask; + u64 ca_mask; ssize_t ret = 0; -#if !MALI_USE_CSF - size_t i; -#endif CSTD_UNUSED(attr); @@ -2410,35 +2201,30 @@ static ssize_t core_mask_show(struct device *dev, struct device_attribute *attr, spin_lock_irqsave(&kbdev->hwaccess_lock, flags); -#if MALI_USE_CSF - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "Current debug core mask : 0x%llX\n", - kbdev->pm.debug_core_mask); - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), - "Current desired core mask : 0x%llX\n", kbase_pm_ca_get_core_mask(kbdev)); - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), - "Current in use core mask : 0x%llX\n", kbdev->pm.backend.shaders_avail); -#else - for (i = 0; i < BASE_JM_MAX_NR_SLOTS; i++) { - if (PAGE_SIZE < ret) - goto out_unlock; - - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), - "Current core mask (JS%zu) : 0x%llX\n", i, - kbdev->pm.debug_core_mask[i]); + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + ca_mask = kbase_pm_ca_get_gov_core_mask(kbdev); + debug_mask = kbase_pm_ca_get_sysfs_gov_core_mask(kbdev); + } else { + ca_mask = kbase_pm_ca_get_core_mask(kbdev); + debug_mask = kbase_pm_ca_get_debug_core_mask(kbdev); } -#endif /* MALI_USE_CSF */ + ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "Current debug core mask : 0x%llX\n", + debug_mask); + ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), + "Current desired core mask : 0x%llX\n", ca_mask); + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) + ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), + "Current in use core mask : 0x%llX\n", + kbdev->pm.backend.shaders_avail); ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "Available core mask : 0x%llX\n", kbdev->gpu_props.shader_present); -#if !MALI_USE_CSF -out_unlock: -#endif + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); return ret; } -#if MALI_USE_CSF struct kbase_core_mask { u64 new_core_mask; }; @@ -2458,6 +2244,8 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con { u64 new_core_mask = new_mask->new_core_mask; u64 shader_present; + u64 ca_mask; + u64 debug_mask; unsigned long flags; int ret = 0; @@ -2465,6 +2253,14 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con kbase_pm_lock(kbdev); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT)) { + ca_mask = kbdev->pm.backend.ca_gov_cores_enabled; + debug_mask = kbase_pm_ca_get_sysfs_gov_core_mask(kbdev); + } else { + ca_mask = kbdev->pm.backend.ca_cores_enabled; + debug_mask = kbase_pm_ca_get_debug_core_mask(kbdev); + } + shader_present = kbdev->gpu_props.shader_present; if ((new_core_mask & shader_present) != new_core_mask) { @@ -2473,13 +2269,16 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con new_core_mask, shader_present); ret = -EINVAL; goto exit; - } else if (!(new_core_mask & shader_present & kbdev->pm.backend.ca_cores_enabled)) { - dev_err(kbdev->dev, - "Invalid requested core mask 0x%llX: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)", - new_core_mask, kbdev->gpu_props.shader_present, - kbdev->pm.backend.ca_cores_enabled); - ret = -EINVAL; - goto exit; + } else if (!(new_core_mask & shader_present & ca_mask)) { + if (!kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT) || + (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_GOV_CORE_MASK_SUPPORT) && + new_core_mask != 0)) { + dev_err(kbdev->dev, + "Invalid requested core mask 0x%llX: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)", + new_core_mask, kbdev->gpu_props.shader_present, ca_mask); + ret = -EINVAL; + goto exit; + } } if (kbase_csf_dev_has_ne(kbdev)) { @@ -2502,7 +2301,7 @@ static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *con } } - if (kbdev->pm.debug_core_mask != new_core_mask) + if (debug_mask != new_core_mask) kbase_pm_set_debug_core_mask(kbdev, new_core_mask); exit: @@ -2512,97 +2311,6 @@ exit: return ret; } -#else -struct kbase_core_mask { - u64 new_core_mask[BASE_JM_MAX_NR_SLOTS]; -}; - -static int core_mask_parse(struct kbase_device *const kbdev, const char *const buf, - struct kbase_core_mask *const mask) -{ - int items; - - items = sscanf(buf, "%llx %llx %llx", &mask->new_core_mask[0], &mask->new_core_mask[1], - &mask->new_core_mask[2]); - - if (items != 1 && items != BASE_JM_MAX_NR_SLOTS) { - dev_err(kbdev->dev, "Couldn't process core mask write operation.\n" - "Use format \n" - "or \n"); - return -EINVAL; - } - - /* If only one value was provided, set all other core masks equal to the value. */ - if (items == 1) { - size_t i; - - for (i = 1; i < BASE_JM_MAX_NR_SLOTS; i++) - mask->new_core_mask[i] = mask->new_core_mask[0]; - } - - return 0; -} - -static int core_mask_set(struct kbase_device *kbdev, struct kbase_core_mask *const new_mask) -{ - u64 shader_present = kbdev->gpu_props.shader_present; - u64 group_core_mask = kbdev->gpu_props.coherency_info.group.core_mask; - u64 *new_core_mask; - unsigned long flags; - int ret = 0; - size_t i; - - kbase_pm_lock(kbdev); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - new_core_mask = &new_mask->new_core_mask[0]; - - for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) { - if ((new_core_mask[i] & shader_present) != new_core_mask[i]) { - dev_err(kbdev->dev, - "Invalid core mask 0x%llX for JS %zu: Includes non-existent cores (present = 0x%llX)", - new_core_mask[i], i, shader_present); - ret = -EINVAL; - goto exit; - - } else if (!(new_core_mask[i] & shader_present & - kbdev->pm.backend.ca_cores_enabled)) { - dev_err(kbdev->dev, - "Invalid core mask 0x%llX for JS %zu: No intersection with currently available cores (present = 0x%llX, CA enabled = 0x%llX)", - new_core_mask[i], i, kbdev->gpu_props.shader_present, - kbdev->pm.backend.ca_cores_enabled); - ret = -EINVAL; - goto exit; - } else if (!(new_core_mask[i] & group_core_mask)) { - dev_err(kbdev->dev, - "Invalid core mask 0x%llX for JS %zu: No intersection with group 0 core mask 0x%llX", - new_core_mask[i], i, group_core_mask); - ret = -EINVAL; - goto exit; - } else if (!(new_core_mask[i] & kbdev->gpu_props.curr_config.shader_present)) { - dev_err(kbdev->dev, - "Invalid core mask 0x%llX for JS %zu: No intersection with current core mask 0x%llX", - new_core_mask[i], i, kbdev->gpu_props.curr_config.shader_present); - ret = -EINVAL; - goto exit; - } - } - - for (i = 0; i < BASE_JM_MAX_NR_SLOTS; i++) { - if (kbdev->pm.debug_core_mask[i] != new_core_mask[i]) { - kbase_pm_set_debug_core_mask(kbdev, new_core_mask, BASE_JM_MAX_NR_SLOTS); - break; - } - } - -exit: - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - kbase_pm_unlock(kbdev); - - return ret; -} - -#endif /** * core_mask_store - Store callback for the core_mask sysfs file. @@ -2652,446 +2360,6 @@ static ssize_t core_mask_store(struct device *dev, struct device_attribute *attr */ static DEVICE_ATTR_RW(core_mask); -#if !MALI_USE_CSF -/** - * soft_job_timeout_store - Store callback for the soft_job_timeout sysfs - * file. - * - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The value written to the sysfs file. - * @count: The number of bytes to write to the sysfs file. - * - * This allows setting the timeout for software jobs. Waiting soft event wait - * jobs will be cancelled after this period expires, while soft fence wait jobs - * will print debug information if the fence debug feature is enabled. - * - * This is expressed in milliseconds. - * - * Return: count if the function succeeded. An error code on failure. - */ -static ssize_t soft_job_timeout_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *kbdev; - int soft_job_timeout_ms; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - if ((kstrtoint(buf, 0, &soft_job_timeout_ms) != 0) || (soft_job_timeout_ms <= 0)) - return -EINVAL; - - atomic_set(&kbdev->js_data.soft_job_timeout_ms, soft_job_timeout_ms); - - return (ssize_t)count; -} - -/** - * soft_job_timeout_show - Show callback for the soft_job_timeout sysfs - * file. - * - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer for the sysfs file contents. - * - * This will return the timeout for the software jobs. - * - * Return: The number of bytes output to buf. - */ -static ssize_t soft_job_timeout_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *kbdev; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - return scnprintf(buf, PAGE_SIZE, "%i\n", atomic_read(&kbdev->js_data.soft_job_timeout_ms)); -} - -static DEVICE_ATTR_RW(soft_job_timeout); - -static u32 timeout_ms_to_ticks(struct kbase_device *kbdev, long timeout_ms, int default_ticks, - u32 old_ticks) -{ - if (timeout_ms > 0) { - u64 ticks = (u64)timeout_ms * 1000000ULL; - - do_div(ticks, kbdev->js_data.scheduling_period_ns); - if (!ticks) - return 1; - return ticks; - } else if (timeout_ms < 0) { - return (u32)default_ticks; - } else { - return old_ticks; - } -} - -/** - * js_timeouts_store - Store callback for the js_timeouts sysfs file. - * - * @dev: The device with sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The value written to the sysfs file - * @count: The number of bytes to write to the sysfs file - * - * This function is called to get the contents of the js_timeouts sysfs - * file. This file contains five values separated by whitespace. The values - * are basically the same as %JS_SOFT_STOP_TICKS, %JS_HARD_STOP_TICKS_SS, - * %JS_HARD_STOP_TICKS_DUMPING, %JS_RESET_TICKS_SS, %JS_RESET_TICKS_DUMPING - * configuration values (in that order), with the difference that the js_timeout - * values are expressed in MILLISECONDS. - * - * The js_timeouts sysfile file allows the current values in - * use by the job scheduler to get override. Note that a value needs to - * be other than 0 for it to override the current job scheduler value. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t js_timeouts_store(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) -{ - struct kbase_device *kbdev; - int items; - long js_soft_stop_ms; - long js_soft_stop_ms_cl; - long js_hard_stop_ms_ss; - long js_hard_stop_ms_cl; - long js_hard_stop_ms_dumping; - long js_reset_ms_ss; - long js_reset_ms_cl; - long js_reset_ms_dumping; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - items = sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld", &js_soft_stop_ms, - &js_soft_stop_ms_cl, &js_hard_stop_ms_ss, &js_hard_stop_ms_cl, - &js_hard_stop_ms_dumping, &js_reset_ms_ss, &js_reset_ms_cl, - &js_reset_ms_dumping); - - if (items == 8) { - struct kbasep_js_device_data *js_data = &kbdev->js_data; - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - -#define UPDATE_TIMEOUT(ticks_name, ms_name, default) \ - do { \ - js_data->ticks_name = \ - timeout_ms_to_ticks(kbdev, ms_name, default, js_data->ticks_name); \ - dev_dbg(kbdev->dev, "Overriding " #ticks_name " with %lu ticks (%lu ms)\n", \ - (unsigned long)js_data->ticks_name, ms_name); \ - } while (0) - - UPDATE_TIMEOUT(soft_stop_ticks, js_soft_stop_ms, DEFAULT_JS_SOFT_STOP_TICKS); - UPDATE_TIMEOUT(soft_stop_ticks_cl, js_soft_stop_ms_cl, - DEFAULT_JS_SOFT_STOP_TICKS_CL); - UPDATE_TIMEOUT(hard_stop_ticks_ss, js_hard_stop_ms_ss, - DEFAULT_JS_HARD_STOP_TICKS_SS); - UPDATE_TIMEOUT(hard_stop_ticks_cl, js_hard_stop_ms_cl, - DEFAULT_JS_HARD_STOP_TICKS_CL); - UPDATE_TIMEOUT(hard_stop_ticks_dumping, js_hard_stop_ms_dumping, - DEFAULT_JS_HARD_STOP_TICKS_DUMPING); - UPDATE_TIMEOUT(gpu_reset_ticks_ss, js_reset_ms_ss, DEFAULT_JS_RESET_TICKS_SS); - UPDATE_TIMEOUT(gpu_reset_ticks_cl, js_reset_ms_cl, DEFAULT_JS_RESET_TICKS_CL); - UPDATE_TIMEOUT(gpu_reset_ticks_dumping, js_reset_ms_dumping, - DEFAULT_JS_RESET_TICKS_DUMPING); - - kbase_js_set_timeouts(kbdev); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return (ssize_t)count; - } - - dev_err(kbdev->dev, - "Couldn't process js_timeouts write operation.\n" - "Use format \n" - "Write 0 for no change, -1 to restore default timeout\n"); - return -EINVAL; -} - -static unsigned long get_js_timeout_in_ms(u32 scheduling_period_ns, u32 ticks) -{ - u64 ms = (u64)ticks * scheduling_period_ns; - - do_div(ms, 1000000UL); - return ms; -} - -/** - * js_timeouts_show - Show callback for the js_timeouts sysfs file. - * - * @dev: The device this sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The output buffer for the sysfs file contents - * - * This function is called to get the contents of the js_timeouts sysfs - * file. It returns the last set values written to the js_timeouts sysfs file. - * If the file didn't get written yet, the values will be current setting in - * use. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t js_timeouts_show(struct device *dev, struct device_attribute *attr, char *const buf) -{ - struct kbase_device *kbdev; - ssize_t ret; - unsigned long js_soft_stop_ms; - unsigned long js_soft_stop_ms_cl; - unsigned long js_hard_stop_ms_ss; - unsigned long js_hard_stop_ms_cl; - unsigned long js_hard_stop_ms_dumping; - unsigned long js_reset_ms_ss; - unsigned long js_reset_ms_cl; - unsigned long js_reset_ms_dumping; - u32 scheduling_period_ns; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - scheduling_period_ns = kbdev->js_data.scheduling_period_ns; - -#define GET_TIMEOUT(name) get_js_timeout_in_ms(scheduling_period_ns, kbdev->js_data.name) - - js_soft_stop_ms = GET_TIMEOUT(soft_stop_ticks); - js_soft_stop_ms_cl = GET_TIMEOUT(soft_stop_ticks_cl); - js_hard_stop_ms_ss = GET_TIMEOUT(hard_stop_ticks_ss); - js_hard_stop_ms_cl = GET_TIMEOUT(hard_stop_ticks_cl); - js_hard_stop_ms_dumping = GET_TIMEOUT(hard_stop_ticks_dumping); - js_reset_ms_ss = GET_TIMEOUT(gpu_reset_ticks_ss); - js_reset_ms_cl = GET_TIMEOUT(gpu_reset_ticks_cl); - js_reset_ms_dumping = GET_TIMEOUT(gpu_reset_ticks_dumping); - -#undef GET_TIMEOUT - - ret = scnprintf(buf, PAGE_SIZE, "%lu %lu %lu %lu %lu %lu %lu %lu\n", js_soft_stop_ms, - js_soft_stop_ms_cl, js_hard_stop_ms_ss, js_hard_stop_ms_cl, - js_hard_stop_ms_dumping, js_reset_ms_ss, js_reset_ms_cl, - js_reset_ms_dumping); - - if (ret >= (ssize_t)PAGE_SIZE) { - buf[PAGE_SIZE - 2] = '\n'; - buf[PAGE_SIZE - 1] = '\0'; - ret = PAGE_SIZE - 1; - } - - return ret; -} - -/* - * The sysfs file js_timeouts. - * - * This is used to override the current job scheduler values for - * JS_STOP_STOP_TICKS_SS - * JS_STOP_STOP_TICKS_CL - * JS_HARD_STOP_TICKS_SS - * JS_HARD_STOP_TICKS_CL - * JS_HARD_STOP_TICKS_DUMPING - * JS_RESET_TICKS_SS - * JS_RESET_TICKS_CL - * JS_RESET_TICKS_DUMPING. - */ -static DEVICE_ATTR_RW(js_timeouts); - -static u32 get_new_js_timeout(u32 old_period, u32 old_ticks, u32 new_scheduling_period_ns) -{ - u64 ticks = (u64)old_period * (u64)old_ticks; - - do_div(ticks, new_scheduling_period_ns); - return ticks ? ticks : 1; -} - -/** - * js_scheduling_period_store - Store callback for the js_scheduling_period sysfs - * file - * @dev: The device the sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The value written to the sysfs file - * @count: The number of bytes to write to the sysfs file - * - * This function is called when the js_scheduling_period sysfs file is written - * to. It checks the data written, and if valid updates the js_scheduling_period - * value - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t js_scheduling_period_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *kbdev; - int ret; - unsigned int js_scheduling_period; - u32 new_scheduling_period_ns; - u32 old_period; - struct kbasep_js_device_data *js_data; - unsigned long flags; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - js_data = &kbdev->js_data; - - ret = kstrtouint(buf, 0, &js_scheduling_period); - if (ret || !js_scheduling_period) { - dev_err(kbdev->dev, "Couldn't process js_scheduling_period write operation.\n" - "Use format \n"); - return -EINVAL; - } - - new_scheduling_period_ns = js_scheduling_period * 1000000; - - /* Update scheduling timeouts */ - mutex_lock(&js_data->runpool_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* If no contexts have been scheduled since js_timeouts was last written - * to, the new timeouts might not have been latched yet. So check if an - * update is pending and use the new values if necessary. - */ - - /* Use previous 'new' scheduling period as a base if present. */ - old_period = js_data->scheduling_period_ns; - -#define SET_TIMEOUT(name) \ - (js_data->name = \ - get_new_js_timeout(old_period, kbdev->js_data.name, new_scheduling_period_ns)) - - SET_TIMEOUT(soft_stop_ticks); - SET_TIMEOUT(soft_stop_ticks_cl); - SET_TIMEOUT(hard_stop_ticks_ss); - SET_TIMEOUT(hard_stop_ticks_cl); - SET_TIMEOUT(hard_stop_ticks_dumping); - SET_TIMEOUT(gpu_reset_ticks_ss); - SET_TIMEOUT(gpu_reset_ticks_cl); - SET_TIMEOUT(gpu_reset_ticks_dumping); - -#undef SET_TIMEOUT - - js_data->scheduling_period_ns = new_scheduling_period_ns; - - kbase_js_set_timeouts(kbdev); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_data->runpool_mutex); - - dev_dbg(kbdev->dev, "JS scheduling period: %dms\n", js_scheduling_period); - - return (ssize_t)count; -} - -/** - * js_scheduling_period_show - Show callback for the js_scheduling_period sysfs - * entry. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the GPU information. - * - * This function is called to get the current period used for the JS scheduling - * period. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t js_scheduling_period_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *kbdev; - u32 period; - ssize_t ret; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - period = kbdev->js_data.scheduling_period_ns; - - ret = scnprintf(buf, PAGE_SIZE, "%d\n", period / 1000000); - - return ret; -} - -static DEVICE_ATTR_RW(js_scheduling_period); - -#ifdef CONFIG_MALI_VALHALL_DEBUG -static ssize_t js_softstop_always_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *kbdev; - int ret; - int softstop_always; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - ret = kstrtoint(buf, 0, &softstop_always); - if (ret || ((softstop_always != 0) && (softstop_always != 1))) { - dev_err(kbdev->dev, "Couldn't process js_softstop_always write operation.\n" - "Use format \n"); - return -EINVAL; - } - - kbdev->js_data.softstop_always = (bool)softstop_always; - dev_dbg(kbdev->dev, "Support for softstop on a single context: %s\n", - (kbdev->js_data.softstop_always) ? "Enabled" : "Disabled"); - return (ssize_t)count; -} - -static ssize_t js_softstop_always_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *kbdev; - ssize_t ret; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - ret = scnprintf(buf, PAGE_SIZE, "%d\n", kbdev->js_data.softstop_always); - - if (ret >= (ssize_t)PAGE_SIZE) { - buf[PAGE_SIZE - 2] = '\n'; - buf[PAGE_SIZE - 1] = '\0'; - ret = PAGE_SIZE - 1; - } - - return ret; -} - -/* - * By default, soft-stops are disabled when only a single context is present. - * The ability to enable soft-stop when only a single context is present can be - * used for debug and unit-testing purposes. - * (see CL t6xx_stress_1 unit-test as an example whereby this feature is used.) - */ -static DEVICE_ATTR_RW(js_softstop_always); -#endif /* CONFIG_MALI_VALHALL_DEBUG */ -#endif /* !MALI_USE_CSF */ - #ifdef CONFIG_MALI_VALHALL_DEBUG typedef void kbasep_debug_command_func(struct kbase_device *); @@ -3276,7 +2544,6 @@ static ssize_t gpuinfo_show(struct device *dev, struct device_attribute *attr, c } } -#if MALI_USE_CSF if (product_model == GPU_ID_PRODUCT_TTUX) { const bool rt_supported = gpu_props->gpu_features.ray_intersection; const u8 nr_cores = gpu_props->num_cores; @@ -3355,7 +2622,6 @@ static ssize_t gpuinfo_show(struct device *dev, struct device_attribute *attr, c dev_dbg(kbdev->dev, "GPU ID_Name: %s (ID: 0x%x), nr_cores(%u)\n", product_name, product_id, nr_cores); } -#endif /* MALI_USE_CSF */ return scnprintf(buf, PAGE_SIZE, "%s %d cores r%dp%d 0x%08X\n", product_name, kbdev->gpu_props.num_cores, gpu_props->gpu_id.version_major, @@ -3363,6 +2629,56 @@ static ssize_t gpuinfo_show(struct device *dev, struct device_attribute *attr, c } static DEVICE_ATTR_RO(gpuinfo); +/** + * gpumem_private_show - Show callback for the gpumem_private sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the current number of pages used by the GPU. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t private_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%llu\n", (u64)atomic_read(&(kbdev->memdev.used_pages)) << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(private_gpu_mem); + +/** + * total_gpu_mem_show - Show callback for the total_gpu_mem sysfs entry. + * @dev: The device this sysfs file is for. + * @attr: The attributes of the sysfs file. + * @buf: The output buffer to receive the GPU memory information. + * + * This function is called to get the total GPU memory including dmabuf memory. + * The returned value is in bytes. + * + * Return: The number of bytes output to @buf. + */ +static ssize_t total_gpu_mem_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct kbase_device *kbdev; + + CSTD_UNUSED(attr); + + kbdev = to_kbase_device(dev); + if (!kbdev) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%zu\n", kbdev->total_gpu_pages << PAGE_SHIFT); +} +static DEVICE_ATTR_RO(total_gpu_mem); + /** * dvfs_period_store - Store callback for the dvfs_period sysfs file. * @dev: The device with sysfs file is for @@ -3603,11 +2919,7 @@ static ssize_t reset_timeout_store(struct device *dev, struct device_attribute * return -EINVAL; } -#if MALI_USE_CSF default_reset_timeout = kbase_get_timeout_ms(kbdev, CSF_GPU_RESET_TIMEOUT); -#else /* MALI_USE_CSF */ - default_reset_timeout = JM_DEFAULT_RESET_TIMEOUT_MS; -#endif /* !MALI_USE_CSF */ if (reset_timeout < default_reset_timeout) dev_warn(kbdev->dev, "requested reset_timeout(%u) is smaller than default(%u)", @@ -3648,689 +2960,6 @@ static ssize_t reset_timeout_show(struct device *dev, struct device_attribute *a static DEVICE_ATTR_RW(reset_timeout); -static ssize_t mem_pool_size_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.small, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_size); -} - -static ssize_t mem_pool_size_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - ssize_t err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kbase_debugfs_helper_set_attr_from_string(buf, kbdev->mem_pools.small, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_trim); - - return err ? err : (ssize_t)count; -} - -static DEVICE_ATTR_RW(mem_pool_size); - -static ssize_t mem_pool_max_size_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.small, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_max_size); -} - -static ssize_t mem_pool_max_size_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - ssize_t err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kbase_debugfs_helper_set_attr_from_string(buf, kbdev->mem_pools.small, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_set_max_size); - - return err ? err : (ssize_t)count; -} - -static DEVICE_ATTR_RW(mem_pool_max_size); - -/** - * lp_mem_pool_size_show - Show size of the large memory pages pool. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the pool size. - * - * This function is called to get the number of large memory pages which currently populate the kbdev pool. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t lp_mem_pool_size_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.large, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_size); -} - -/** - * lp_mem_pool_size_store - Set size of the large memory pages pool. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The value written to the sysfs file. - * @count: The number of bytes written to the sysfs file. - * - * This function is called to set the number of large memory pages which should populate the kbdev pool. - * This may cause existing pages to be removed from the pool, or new pages to be created and then added to the pool. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t lp_mem_pool_size_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - ssize_t err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kbase_debugfs_helper_set_attr_from_string(buf, kbdev->mem_pools.large, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_trim); - - return err ? err : (ssize_t)count; -} - -static DEVICE_ATTR_RW(lp_mem_pool_size); - -/** - * lp_mem_pool_max_size_show - Show maximum size of the large memory pages pool. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the pool size. - * - * This function is called to get the maximum number of large memory pages that the kbdev pool can possibly contain. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t lp_mem_pool_max_size_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.large, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_max_size); -} - -/** - * lp_mem_pool_max_size_store - Set maximum size of the large memory pages pool. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The value written to the sysfs file. - * @count: The number of bytes written to the sysfs file. - * - * This function is called to set the maximum number of large memory pages that the kbdev pool can possibly contain. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t lp_mem_pool_max_size_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - ssize_t err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kbase_debugfs_helper_set_attr_from_string(buf, kbdev->mem_pools.large, - MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_debugfs_set_max_size); - - return err ? err : (ssize_t)count; -} - -static DEVICE_ATTR_RW(lp_mem_pool_max_size); - -/** - * show_simplified_mem_pool_max_size - Show the maximum size for the memory - * pool 0 of small (4KiB/16KiB/64KiB) pages. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the max size. - * - * This function is called to get the maximum size for the memory pool 0 of - * small pages. It is assumed that the maximum size value is same for - * all the pools. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t show_simplified_mem_pool_max_size(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.small, 1, - kbase_mem_pool_debugfs_max_size); -} - -/** - * set_simplified_mem_pool_max_size - Set the same maximum size for all the - * memory pools of small (4KiB/16KiB/64KiB) pages. - * @dev: The device with sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The value written to the sysfs file - * @count: The number of bytes written to the sysfs file - * - * This function is called to set the same maximum size for all the memory - * pools of small pages. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t set_simplified_mem_pool_max_size(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - unsigned long new_size; - size_t gid; - int err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kstrtoul(buf, 0, &new_size); - if (err) - return -EINVAL; - - for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid) - kbase_mem_pool_debugfs_set_max_size(kbdev->mem_pools.small, gid, (size_t)new_size); - - return (ssize_t)count; -} - -static DEVICE_ATTR(max_size, 0600, show_simplified_mem_pool_max_size, - set_simplified_mem_pool_max_size); - -/** - * show_simplified_lp_mem_pool_max_size - Show the maximum size for the memory - * pool 0 of large (2MiB) pages. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the total current pool size. - * - * This function is called to get the maximum size for the memory pool 0 of - * large (2MiB) pages. It is assumed that the maximum size value is same for - * all the pools. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t show_simplified_lp_mem_pool_max_size(struct device *dev, - struct device_attribute *attr, char *const buf) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - return kbase_debugfs_helper_get_attr_to_string(buf, PAGE_SIZE, kbdev->mem_pools.large, 1, - kbase_mem_pool_debugfs_max_size); -} - -/** - * set_simplified_lp_mem_pool_max_size - Set the same maximum size for all the - * memory pools of large (2MiB) pages. - * @dev: The device with sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The value written to the sysfs file - * @count: The number of bytes written to the sysfs file - * - * This function is called to set the same maximum size for all the memory - * pools of large (2MiB) pages. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t set_simplified_lp_mem_pool_max_size(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct kbase_device *const kbdev = to_kbase_device(dev); - unsigned long new_size; - size_t gid; - int err; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - err = kstrtoul(buf, 0, &new_size); - if (err) - return -EINVAL; - - for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid) - kbase_mem_pool_debugfs_set_max_size(kbdev->mem_pools.large, gid, (size_t)new_size); - - return (ssize_t)count; -} - -static DEVICE_ATTR(lp_max_size, 0600, show_simplified_lp_mem_pool_max_size, - set_simplified_lp_mem_pool_max_size); - -/** - * show_simplified_ctx_default_max_size - Show the default maximum size for the - * memory pool 0 of small (4KiB/16KiB/64KiB) pages. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the pool size. - * - * This function is called to get the default ctx maximum size for the memory - * pool 0 of small pages. It is assumed that maximum size value is same - * for all the pools. The maximum size for the pool of large (2MiB) pages will - * be same as max size of the pool of small pages in terms of bytes. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t show_simplified_ctx_default_max_size(struct device *dev, - struct device_attribute *attr, char *const buf) -{ - struct kbase_device *kbdev = to_kbase_device(dev); - size_t max_size; - - CSTD_UNUSED(attr); - - if (!kbdev) - return -ENODEV; - - max_size = kbase_mem_pool_config_debugfs_max_size(kbdev->mem_pool_defaults.small, 0); - - return scnprintf(buf, PAGE_SIZE, "%zu\n", max_size); -} - -/** - * set_simplified_ctx_default_max_size - Set the same default maximum size for - * all the pools created for new - * contexts. This covers the pool of - * large pages as well and its max size - * will be same as max size of the pool - * of small pages in terms of bytes. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The value written to the sysfs file. - * @count: The number of bytes written to the sysfs file. - * - * This function is called to set the same maximum size for all pools created - * for new contexts. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t set_simplified_ctx_default_max_size(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct kbase_device *kbdev; - unsigned long new_size; - int err; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - err = kstrtoul(buf, 0, &new_size); - if (err) - return -EINVAL; - - kbase_mem_pool_group_config_set_max_size(&kbdev->mem_pool_defaults, (size_t)new_size); - - return (ssize_t)count; -} - -static DEVICE_ATTR(ctx_default_max_size, 0600, show_simplified_ctx_default_max_size, - set_simplified_ctx_default_max_size); - -#if !MALI_USE_CSF -/** - * js_ctx_scheduling_mode_show - Show callback for js_ctx_scheduling_mode sysfs - * entry. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The output buffer to receive the context scheduling mode information. - * - * This function is called to get the context scheduling mode being used by JS. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t js_ctx_scheduling_mode_show(struct device *dev, struct device_attribute *attr, - char *const buf) -{ - struct kbase_device *kbdev; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - return scnprintf(buf, PAGE_SIZE, "%u\n", kbdev->js_ctx_scheduling_mode); -} - -/** - * js_ctx_scheduling_mode_store - Set callback for js_ctx_scheduling_mode sysfs - * entry. - * @dev: The device this sysfs file is for. - * @attr: The attributes of the sysfs file. - * @buf: The value written to the sysfs file. - * @count: The number of bytes written to the sysfs file. - * - * This function is called when the js_ctx_scheduling_mode sysfs file is written - * to. It checks the data written, and if valid updates the ctx scheduling mode - * being by JS. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t js_ctx_scheduling_mode_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kbase_context *kctx; - u32 new_js_ctx_scheduling_mode; - struct kbase_device *kbdev; - unsigned long flags; - int ret; - - CSTD_UNUSED(attr); - - kbdev = to_kbase_device(dev); - if (!kbdev) - return -ENODEV; - - ret = kstrtouint(buf, 0, &new_js_ctx_scheduling_mode); - if (ret || new_js_ctx_scheduling_mode >= KBASE_JS_PRIORITY_MODE_COUNT) { - dev_err(kbdev->dev, "Couldn't process js_ctx_scheduling_mode" - " write operation.\n" - "Use format \n"); - return -EINVAL; - } - - if (new_js_ctx_scheduling_mode == kbdev->js_ctx_scheduling_mode) - return (ssize_t)count; - - mutex_lock(&kbdev->kctx_list_lock); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* Update the context priority mode */ - kbdev->js_ctx_scheduling_mode = new_js_ctx_scheduling_mode; - - /* Adjust priority of all the contexts as per the new mode */ - list_for_each_entry(kctx, &kbdev->kctx_list, kctx_list_link) - kbase_js_update_ctx_priority(kctx); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->kctx_list_lock); - - dev_dbg(kbdev->dev, "JS ctx scheduling mode: %u\n", new_js_ctx_scheduling_mode); - - return (ssize_t)count; -} - -static DEVICE_ATTR_RW(js_ctx_scheduling_mode); - -/* Number of entries in serialize_jobs_settings[] */ -#define NR_SERIALIZE_JOBS_SETTINGS 5 -/* Maximum string length in serialize_jobs_settings[].name */ -#define MAX_SERIALIZE_JOBS_NAME_LEN 16 - -static struct { - char *name; - u8 setting; -} serialize_jobs_settings[NR_SERIALIZE_JOBS_SETTINGS] = { - { "none", 0 }, - { "intra-slot", KBASE_SERIALIZE_INTRA_SLOT }, - { "inter-slot", KBASE_SERIALIZE_INTER_SLOT }, - { "full", KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT }, - { "full-reset", - KBASE_SERIALIZE_INTRA_SLOT | KBASE_SERIALIZE_INTER_SLOT | KBASE_SERIALIZE_RESET } -}; - -/** - * update_serialize_jobs_setting - Update the serialization setting for the - * submission of GPU jobs. - * - * @kbdev: An instance of the GPU platform device, allocated from the probe - * method of the driver. - * @buf: Buffer containing the value written to the sysfs/debugfs file. - * @count: The number of bytes to write to the sysfs/debugfs file. - * - * This function is called when the serialize_jobs sysfs/debugfs file is - * written to. It matches the requested setting against the available settings - * and if a matching setting is found updates kbdev->serialize_jobs. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t update_serialize_jobs_setting(struct kbase_device *kbdev, const char *buf, - size_t count) -{ - int i; - bool valid = false; - - for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) { - if (sysfs_streq(serialize_jobs_settings[i].name, buf)) { - kbdev->serialize_jobs = serialize_jobs_settings[i].setting; - valid = true; - break; - } - } - - if (!valid) { - dev_err(kbdev->dev, "serialize_jobs: invalid setting"); - return -EINVAL; - } - - return (ssize_t)count; -} - -#if IS_ENABLED(CONFIG_DEBUG_FS) -/** - * kbasep_serialize_jobs_seq_debugfs_show - Show callback for the serialize_jobs - * debugfs file - * @sfile: seq_file pointer - * @data: Private callback data - * - * This function is called to get the contents of the serialize_jobs debugfs - * file. This is a list of the available settings with the currently active one - * surrounded by square brackets. - * - * Return: 0 on success, or an error code on error - */ -static int kbasep_serialize_jobs_seq_debugfs_show(struct seq_file *sfile, void *data) -{ - struct kbase_device *kbdev = sfile->private; - int i; - - CSTD_UNUSED(data); - - for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) { - if (kbdev->serialize_jobs == serialize_jobs_settings[i].setting) - seq_printf(sfile, "[%s] ", serialize_jobs_settings[i].name); - else - seq_printf(sfile, "%s ", serialize_jobs_settings[i].name); - } - - seq_puts(sfile, "\n"); - - return 0; -} - -/** - * kbasep_serialize_jobs_debugfs_write - Store callback for the serialize_jobs - * debugfs file. - * @file: File pointer - * @ubuf: User buffer containing data to store - * @count: Number of bytes in user buffer - * @ppos: File position - * - * This function is called when the serialize_jobs debugfs file is written to. - * It matches the requested setting against the available settings and if a - * matching setting is found updates kbdev->serialize_jobs. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t kbasep_serialize_jobs_debugfs_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct seq_file *s = file->private_data; - struct kbase_device *kbdev = s->private; - char buf[MAX_SERIALIZE_JOBS_NAME_LEN]; - - CSTD_UNUSED(ppos); - - count = min_t(size_t, sizeof(buf) - 1, count); - if (copy_from_user(buf, ubuf, count)) - return -EFAULT; - - buf[count] = 0; - - return update_serialize_jobs_setting(kbdev, buf, count); -} - -/** - * kbasep_serialize_jobs_debugfs_open - Open callback for the serialize_jobs - * debugfs file - * @in: inode pointer - * @file: file pointer - * - * Return: Zero on success, error code on failure - */ -static int kbasep_serialize_jobs_debugfs_open(struct inode *in, struct file *file) -{ - return single_open(file, kbasep_serialize_jobs_seq_debugfs_show, in->i_private); -} - -static const struct file_operations kbasep_serialize_jobs_debugfs_fops = { - .owner = THIS_MODULE, - .open = kbasep_serialize_jobs_debugfs_open, - .read = seq_read, - .write = kbasep_serialize_jobs_debugfs_write, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* CONFIG_DEBUG_FS */ - -/** - * show_serialize_jobs_sysfs - Show callback for serialize_jobs sysfs file. - * - * @dev: The device this sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The output buffer for the sysfs file contents - * - * This function is called to get the contents of the serialize_jobs sysfs - * file. This is a list of the available settings with the currently active - * one surrounded by square brackets. - * - * Return: The number of bytes output to @buf. - */ -static ssize_t show_serialize_jobs_sysfs(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct kbase_device *kbdev = to_kbase_device(dev); - ssize_t ret = 0; - int i; - - CSTD_UNUSED(attr); - - for (i = 0; i < NR_SERIALIZE_JOBS_SETTINGS; i++) { - if (kbdev->serialize_jobs == serialize_jobs_settings[i].setting) - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "[%s]", - serialize_jobs_settings[i].name); - else - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "%s ", - serialize_jobs_settings[i].name); - } - - if (ret < (ssize_t)(PAGE_SIZE - 1)) { - ret += scnprintf(buf + ret, (size_t)(PAGE_SIZE - ret), "\n"); - } else { - buf[PAGE_SIZE - 2] = '\n'; - buf[PAGE_SIZE - 1] = '\0'; - ret = PAGE_SIZE - 1; - } - - return ret; -} - -/** - * store_serialize_jobs_sysfs - Store callback for serialize_jobs sysfs file. - * - * @dev: The device this sysfs file is for - * @attr: The attributes of the sysfs file - * @buf: The value written to the sysfs file - * @count: The number of bytes to write to the sysfs file - * - * This function is called when the serialize_jobs sysfs file is written to. - * It matches the requested setting against the available settings and if a - * matching setting is found updates kbdev->serialize_jobs. - * - * Return: @count if the function succeeded. An error code on failure. - */ -static ssize_t store_serialize_jobs_sysfs(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - CSTD_UNUSED(attr); - return update_serialize_jobs_setting(to_kbase_device(dev), buf, count); -} - -static DEVICE_ATTR(serialize_jobs, 0600, show_serialize_jobs_sysfs, store_serialize_jobs_sysfs); -#endif /* !MALI_USE_CSF */ - static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data) { struct kbase_device *kbdev = @@ -4340,11 +2969,7 @@ static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data) bool do_disable; -#if MALI_USE_CSF backend_lock = &kbdev->csf.scheduler.interrupt_lock; -#else - backend_lock = &kbdev->hwaccess_lock; -#endif spin_lock_irqsave(backend_lock, flags); do_disable = !kbdev->protected_mode_hwcnt_desired && !kbdev->protected_mode_hwcnt_disabled; @@ -4364,9 +2989,6 @@ static void kbasep_protected_mode_hwcnt_disable_worker(struct work_struct *data) * the state machine. */ kbdev->protected_mode_hwcnt_disabled = true; -#if !MALI_USE_CSF - kbase_backend_slot_update(kbdev); -#endif /* !MALI_USE_CSF */ } else { /* Protected mode state was updated while we were doing the * disable, so we need to undo the disable we just performed. @@ -4565,25 +3187,6 @@ int kbase_device_backend_init(struct kbase_device *kbdev) err = kbase_arbiter_pm_early_init(kbdev); if (err == 0) { -#if !MALI_USE_CSF - u32 product_model; - - /* - * Attempt to obtain and parse gpu_id in the event an external AW module - * is used for messaging. We should have access to GPU at this point. - */ - if (kbdev->gpu_props.gpu_id.arch_major == 0) - kbase_gpuprops_parse_gpu_id(&kbdev->gpu_props.gpu_id, - kbase_reg_get_gpu_id(kbdev)); - - product_model = kbdev->gpu_props.gpu_id.product_model; - if (product_model != GPU_ID_PRODUCT_TGOX && product_model != GPU_ID_PRODUCT_TNOX && - product_model != GPU_ID_PRODUCT_TBAX) { - kbase_arbiter_pm_early_term(kbdev); - dev_dbg(kbdev->dev, "GPU platform not suitable for arbitration"); - return -EPERM; - } -#endif /* !MALI_USE_CSF */ dev_info(kbdev->dev, "Arbitration interface enabled"); } #endif /* defined(CONFIG_OF) */ @@ -4787,9 +3390,7 @@ MAKE_QUIRK_ACCESSORS(sc); MAKE_QUIRK_ACCESSORS(tiler); MAKE_QUIRK_ACCESSORS(mmu); MAKE_QUIRK_ACCESSORS(gpu); -#if MALI_USE_CSF MAKE_QUIRK_ACCESSORS(ne); -#endif /** * kbase_device_debugfs_reset_write() - Reset the GPU @@ -4859,36 +3460,52 @@ static const struct file_operations fops_protected_debug_mode = { .llseek = default_llseek, }; -static int kbase_device_debugfs_mem_pool_max_size_show(struct seq_file *sfile, void *data) +static int kbase_device_debugfs_heap_reclaim_offslot_show(struct seq_file *sfile, void *data) { + struct kbase_csf_heap_reclaim_offslot *const setting = sfile->private; + CSTD_UNUSED(data); - return kbase_debugfs_helper_seq_read(sfile, MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_config_debugfs_max_size); + + seq_printf(sfile, "%u %u\n", setting->timeout_ms, setting->pages); + + return 0; } -static ssize_t kbase_device_debugfs_mem_pool_max_size_write(struct file *file, - const char __user *ubuf, size_t count, - loff_t *ppos) +static ssize_t kbase_device_debugfs_heap_reclaim_offslot_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) { - ssize_t err = 0; + const struct seq_file *const sfile = (struct seq_file *)file->private_data; + struct kbase_csf_heap_reclaim_offslot *const setting = sfile->private; + u32 read_len, timeout_ms, pages; + char kbuf[32]; CSTD_UNUSED(ppos); - err = kbase_debugfs_helper_seq_write(file, ubuf, count, MEMORY_GROUP_MANAGER_NR_GROUPS, - kbase_mem_pool_config_debugfs_set_max_size); - return err ? err : (ssize_t)count; + read_len = count < (sizeof(kbuf) - 1) ? count : (sizeof(kbuf) - 1); + if (copy_from_user(kbuf, ubuf, read_len)) + return -EFAULT; + kbuf[read_len] = '\0'; + + if (sscanf(kbuf, "%u %u", &timeout_ms, &pages) != 2) + return -EINVAL; + + setting->timeout_ms = timeout_ms; + setting->pages = pages; + + return count; } -static int kbase_device_debugfs_mem_pool_max_size_open(struct inode *in, struct file *file) +static int kbase_device_debugfs_heap_reclaim_offslot_open(struct inode *in, struct file *file) { - return single_open(file, kbase_device_debugfs_mem_pool_max_size_show, in->i_private); + return single_open(file, kbase_device_debugfs_heap_reclaim_offslot_show, in->i_private); } -static const struct file_operations kbase_device_debugfs_mem_pool_max_size_fops = { +static const struct file_operations kbase_device_debugfs_heap_reclaim_offslot_fops = { .owner = THIS_MODULE, - .open = kbase_device_debugfs_mem_pool_max_size_open, + .open = kbase_device_debugfs_heap_reclaim_offslot_open, .read = seq_read, - .write = kbase_device_debugfs_mem_pool_max_size_write, + .write = kbase_device_debugfs_heap_reclaim_offslot_write, .llseek = seq_lseek, .release = single_release, }; @@ -4916,20 +3533,6 @@ static struct dentry *debugfs_ctx_defaults_init(struct kbase_device *const kbdev debugfs_create_bool("infinite_cache", mode, debugfs_ctx_defaults_directory, &kbdev->infinite_cache_active_default); - dentry = debugfs_create_file("mem_pool_max_size", mode, debugfs_ctx_defaults_directory, - &kbdev->mem_pool_defaults.small, - &kbase_device_debugfs_mem_pool_max_size_fops); - if (IS_ERR_OR_NULL(dentry)) { - dev_err(kbdev->dev, "Unable to create mem_pool_max_size debugfs entry\n"); - return dentry; - } - - dentry = debugfs_create_file("lp_mem_pool_max_size", mode, debugfs_ctx_defaults_directory, - &kbdev->mem_pool_defaults.large, - &kbase_device_debugfs_mem_pool_max_size_fops); - if (IS_ERR_OR_NULL(dentry)) - dev_err(kbdev->dev, "Unable to create lp_mem_pool_max_size debugfs entry\n"); - return dentry; } @@ -4965,11 +3568,7 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) kbasep_regs_history_debugfs_init(kbdev); -#if MALI_USE_CSF kbase_debug_csf_fault_debugfs_init(kbdev); -#else /* MALI_USE_CSF */ - kbase_debug_job_fault_debugfs_init(kbdev); -#endif /* !MALI_USE_CSF */ kbasep_gpu_memory_debugfs_init(kbdev); kbase_as_fault_debugfs_init(kbdev); @@ -4977,6 +3576,7 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) kbase_instr_backend_debugfs_init(kbdev); #endif kbase_pbha_debugfs_init(kbdev); + kbase_gpu_timestamp_offset_debugfs_init(kbdev); /* fops_* variables created by invocations of macro * MAKE_QUIRK_ACCESSORS() above. @@ -5009,7 +3609,6 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) return dentry; } -#if MALI_USE_CSF if (kbase_csf_dev_has_ne(kbdev)) { dentry = debugfs_create_file("quirks_ne", 0644, kbdev->mali_debugfs_directory, kbdev, &fops_ne_quirks); @@ -5021,7 +3620,6 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) if (kbase_csf_ne_control_debugfs_init(kbdev)) return NULL; } -#endif dentry = debugfs_ctx_defaults_init(kbdev); if (IS_ERR_OR_NULL(dentry)) @@ -5045,6 +3643,20 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) return dentry; } + { + struct kbase_csf_scheduler *const scheduler = &kbdev->csf.scheduler; + struct kbase_csf_sched_heap_reclaim_mgr *const mgr = &scheduler->reclaim_mgr; + + dentry = debugfs_create_file("heap_reclaim_offslot", 0644, + kbdev->mali_debugfs_directory, &mgr->offslot_setting, + &kbase_device_debugfs_heap_reclaim_offslot_fops); + if (IS_ERR_OR_NULL(dentry)) { + dev_err(kbdev->dev, + "Unable to create heap_reclaim_offslot debugfs entry\n"); + return dentry; + } + } + kbase_ktrace_debugfs_init(kbdev); #ifdef CONFIG_MALI_VALHALL_DEVFREQ @@ -5054,15 +3666,6 @@ static struct dentry *init_debugfs(struct kbase_device *kbdev) #endif /* CONFIG_DEVFREQ_THERMAL */ #endif /* CONFIG_MALI_VALHALL_DEVFREQ */ -#if !MALI_USE_CSF - dentry = debugfs_create_file("serialize_jobs", 0644, kbdev->mali_debugfs_directory, kbdev, - &kbasep_serialize_jobs_debugfs_fops); - if (IS_ERR_OR_NULL(dentry)) { - dev_err(kbdev->dev, "Unable to create serialize_jobs debugfs entry\n"); - return dentry; - } - kbase_timeline_io_debugfs_init(kbdev); -#endif kbase_dvfs_status_debugfs_init(kbdev); @@ -5140,7 +3743,7 @@ static bool kbase_device_supports_coherency_mode(struct kbase_device *kbdev, u32 * on CSF GPUs. */ if (coherency_mode == COHERENCY_ACE) { - if (IS_ENABLED(MALI_USE_CSF) && !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI)) { + if (!IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI)) { dev_err(kbdev->dev, "ACE coherency not supported on CSF, wrong DT configuration"); return false; @@ -5208,8 +3811,6 @@ early_exit: } -#if MALI_USE_CSF - bool kbasep_adjust_prioritized_process(struct kbase_device *kbdev, bool add, uint32_t tgid) { struct kbase_context *kctx; @@ -5723,33 +4324,18 @@ static ssize_t mcu_shader_pwroff_timeout_ns_store(struct device *dev, struct dev static DEVICE_ATTR_RW(mcu_shader_pwroff_timeout_ns); -#endif /* MALI_USE_CSF */ - -static struct attribute *kbase_scheduling_attrs[] = { -#if !MALI_USE_CSF - &dev_attr_serialize_jobs.attr, -#endif /* !MALI_USE_CSF */ - NULL -}; +static struct attribute *kbase_scheduling_attrs[] = { NULL }; static struct attribute *kbase_attrs[] = { #ifdef CONFIG_MALI_VALHALL_DEBUG &dev_attr_debug_command.attr, -#if !MALI_USE_CSF - &dev_attr_js_softstop_always.attr, -#endif /* !MALI_USE_CSF */ #endif -#if !MALI_USE_CSF - &dev_attr_js_timeouts.attr, - &dev_attr_soft_job_timeout.attr, -#endif /* !MALI_USE_CSF */ &dev_attr_gpuinfo.attr, + &dev_attr_total_gpu_mem.attr, + &dev_attr_private_gpu_mem.attr, &dev_attr_dvfs_period.attr, &dev_attr_pm_poweroff.attr, &dev_attr_reset_timeout.attr, -#if !MALI_USE_CSF - &dev_attr_js_scheduling_period.attr, -#else &dev_attr_csg_scheduling_period.attr, &dev_attr_add_prioritized_process.attr, &dev_attr_remove_prioritized_process.attr, @@ -5758,35 +4344,17 @@ static struct attribute *kbase_attrs[] = { &dev_attr_idle_hysteresis_time_ns.attr, &dev_attr_mcu_shader_pwroff_timeout.attr, &dev_attr_mcu_shader_pwroff_timeout_ns.attr, -#endif /* !MALI_USE_CSF */ &dev_attr_power_policy.attr, &dev_attr_core_mask.attr, - &dev_attr_mem_pool_size.attr, - &dev_attr_mem_pool_max_size.attr, - &dev_attr_lp_mem_pool_size.attr, - &dev_attr_lp_mem_pool_max_size.attr, -#if !MALI_USE_CSF - &dev_attr_js_ctx_scheduling_mode.attr, -#endif /* !MALI_USE_CSF */ NULL }; -static struct attribute *kbase_mempool_attrs[] = { &dev_attr_max_size.attr, - &dev_attr_lp_max_size.attr, - &dev_attr_ctx_default_max_size.attr, NULL }; - #define SYSFS_SCHEDULING_GROUP "scheduling" static const struct attribute_group kbase_scheduling_attr_group = { .name = SYSFS_SCHEDULING_GROUP, .attrs = kbase_scheduling_attrs, }; -#define SYSFS_MEMPOOL_GROUP "mempool" -static const struct attribute_group kbase_mempool_attr_group = { - .name = SYSFS_MEMPOOL_GROUP, - .attrs = kbase_mempool_attrs, -}; - static const struct attribute_group kbase_attr_group = { .attrs = kbase_attrs, }; @@ -5812,21 +4380,20 @@ int kbase_sysfs_init(struct kbase_device *kbdev) return err; } - err = sysfs_create_group(&kbdev->dev->kobj, &kbase_mempool_attr_group); - if (err) { - dev_err(kbdev->dev, "Creation of %s sysfs group failed", SYSFS_MEMPOOL_GROUP); + kbdev->kprcs_kobj = kobject_create_and_add("kprcs", &kbdev->dev->kobj); + if (!kbdev->kprcs_kobj) { + dev_err(kbdev->dev, "Creation of kprcs sysfs group failed"); sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); } - return err; } void kbase_sysfs_term(struct kbase_device *kbdev) { - sysfs_remove_group(&kbdev->dev->kobj, &kbase_mempool_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_scheduling_attr_group); sysfs_remove_group(&kbdev->dev->kobj, &kbase_attr_group); + kobject_put(kbdev->kprcs_kobj); put_device(kbdev->dev); } @@ -6013,10 +4580,6 @@ static int kbase_device_resume(struct device *dev) kbase_devfreq_enqueue_work(kbdev, DEVFREQ_WORK_RESUME); #endif -#if !MALI_USE_CSF - kbase_enable_quick_reset(kbdev); -#endif - return 0; } @@ -6031,23 +4594,23 @@ static int kbase_device_resume(struct device *dev) * * Return: A standard Linux error code */ -#ifdef KBASE_PM_RUNTIME static int kbase_device_runtime_suspend(struct device *dev) { struct kbase_device *kbdev = to_kbase_device(dev); int ret = 0; + if (!IS_ENABLED(CONFIG_PM)) + return 0; + if (!kbdev) return -ENODEV; dev_dbg(dev, "Callback %s\n", __func__); KBASE_KTRACE_ADD(kbdev, PM_RUNTIME_SUSPEND_CALLBACK, NULL, 0); -#if MALI_USE_CSF ret = kbase_pm_handle_runtime_suspend(kbdev); if (ret) return ret; -#endif #ifdef CONFIG_MALI_VALHALL_DVFS kbase_pm_metrics_stop(kbdev); @@ -6063,9 +4626,8 @@ static int kbase_device_runtime_suspend(struct device *dev) kbdev->is_runtime_resumed = false; dev_dbg(dev, "runtime suspend\n"); } - return ret; + return 0; } -#endif /* KBASE_PM_RUNTIME */ /** * kbase_device_runtime_resume - Runtime resume callback from the OS. @@ -6077,12 +4639,14 @@ static int kbase_device_runtime_suspend(struct device *dev) * Return: A standard Linux error code */ -#ifdef KBASE_PM_RUNTIME static int kbase_device_runtime_resume(struct device *dev) { int ret = 0; struct kbase_device *kbdev = to_kbase_device(dev); + if (!IS_ENABLED(CONFIG_PM)) + return 0; + if (!kbdev) return -ENODEV; @@ -6105,9 +4669,7 @@ static int kbase_device_runtime_resume(struct device *dev) return ret; } -#endif /* KBASE_PM_RUNTIME */ -#ifdef KBASE_PM_RUNTIME /** * kbase_device_runtime_idle - Runtime idle callback from the OS. * @dev: The device to suspend @@ -6122,6 +4684,9 @@ static int kbase_device_runtime_idle(struct device *dev) { struct kbase_device *kbdev = to_kbase_device(dev); + if (!IS_ENABLED(CONFIG_PM)) + return 0; + if (!kbdev) return -ENODEV; @@ -6136,18 +4701,15 @@ static int kbase_device_runtime_idle(struct device *dev) pm_runtime_mark_last_busy(kbdev->dev); return 0; } -#endif /* KBASE_PM_RUNTIME */ /* The power management operations for the platform driver. */ static const struct dev_pm_ops kbase_pm_ops = { SYSTEM_SLEEP_PM_OPS(kbase_device_suspend, kbase_device_resume) -#ifdef KBASE_PM_RUNTIME .runtime_suspend = kbase_device_runtime_suspend, .runtime_resume = kbase_device_runtime_resume, .runtime_idle = kbase_device_runtime_idle, -#endif /* KBASE_PM_RUNTIME */ }; #if IS_ENABLED(CONFIG_OF) diff --git a/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.c b/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.c index e64a5715b126..f9b3069e7128 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.c +++ b/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.c @@ -24,11 +24,7 @@ #include #include "mali_kbase_ctx_sched.h" #include "tl/mali_kbase_tracepoints.h" -#if MALI_USE_CSF #include "mali_kbase_reset_gpu.h" -#else -#include -#endif /* Helper for ktrace */ #if KBASE_KTRACE_ENABLE @@ -152,19 +148,12 @@ void kbase_ctx_sched_retain_ctx_refcount(struct kbase_context *kctx) struct kbase_device *const kbdev = kctx->kbdev; lockdep_assert_held(&kbdev->hwaccess_lock); -#if MALI_USE_CSF /* We expect the context to be active when this function is called, * except for the case where a page fault is reported for it during * the GPU reset sequence, in which case we can expect the refcount * to be 0. */ WARN_ON(!atomic_read(&kctx->refcount) && !kbase_reset_gpu_is_active(kbdev)); -#else - /* We expect the context to be active (and thus refcount should be non-zero) - * when this function is called - */ - WARN_ON(!atomic_read(&kctx->refcount)); -#endif if (likely((kctx->as_nr >= 0) && (kctx->as_nr < BASE_MAX_NR_AS))) WARN_ON(kbdev->as_to_kctx[kctx->as_nr] != kctx); else @@ -188,9 +177,6 @@ void kbase_ctx_sched_release_ctx(struct kbase_context *kctx) kbdev->as_to_kctx[kctx->as_nr] = NULL; kctx->as_nr = KBASEP_AS_NR_INVALID; kbase_ctx_flag_clear(kctx, KCTX_AS_DISABLED_ON_FAULT); -#if !MALI_USE_CSF - kbase_backend_slot_kctx_purge_locked(kbdev, kctx); -#endif } } } @@ -206,6 +192,19 @@ void kbase_ctx_sched_remove_ctx(struct kbase_context *kctx) mutex_lock(&kbdev->mmu_hw_mutex); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); + kbase_ctx_sched_remove_ctx_nolock(kctx); + + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); + mutex_unlock(&kbdev->mmu_hw_mutex); +} + +void kbase_ctx_sched_remove_ctx_nolock(struct kbase_context *kctx) +{ + struct kbase_device *const kbdev = kctx->kbdev; + + lockdep_assert_held(&kbdev->mmu_hw_mutex); + lockdep_assert_held(&kbdev->hwaccess_lock); + WARN_ON(atomic_read(&kctx->refcount) != 0); if ((kctx->as_nr >= 0) && (kctx->as_nr < BASE_MAX_NR_AS)) { @@ -215,9 +214,6 @@ void kbase_ctx_sched_remove_ctx(struct kbase_context *kctx) kbdev->as_to_kctx[kctx->as_nr] = NULL; kctx->as_nr = KBASEP_AS_NR_INVALID; } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); } void kbase_ctx_sched_restore_all_as(struct kbase_device *kbdev) @@ -234,12 +230,10 @@ void kbase_ctx_sched_restore_all_as(struct kbase_device *kbdev) for (i = 0; i != kbdev->nr_hw_address_spaces; ++i) { struct kbase_context *kctx; -#if MALI_USE_CSF if ((i == MCU_AS_NR) && kbdev->csf.firmware_inited) { kbase_mmu_update(kbdev, &kbdev->csf.mcu_mmu, MCU_AS_NR); continue; } -#endif kctx = kbdev->as_to_kctx[i]; if (kctx) { if (atomic_read(&kctx->refcount)) { @@ -378,7 +372,6 @@ void kbase_ctx_sched_release_ctx_lock(struct kbase_context *kctx) spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); } -#if MALI_USE_CSF bool kbase_ctx_sched_inc_refcount_if_as_valid(struct kbase_context *kctx) { struct kbase_device *kbdev; @@ -412,4 +405,3 @@ bool kbase_ctx_sched_inc_refcount_if_as_valid(struct kbase_context *kctx) return added_ref; } -#endif diff --git a/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.h b/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.h index fd1b82471d26..bdc9e8fa4784 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.h +++ b/drivers/gpu/arm/valhall/mali_kbase_ctx_sched.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2017-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2017-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -130,6 +130,20 @@ void kbase_ctx_sched_release_ctx(struct kbase_context *kctx); */ void kbase_ctx_sched_remove_ctx(struct kbase_context *kctx); +/** + * kbase_ctx_sched_remove_ctx_nolock - Unassign previously assigned address space + * @kctx: The context to be removed + * + * The following lock must be held by the caller: + * kbase_device::mmu_hw_mutex + * kbase_device::hwaccess_lock + * + * This function should be called when a context is being destroyed. The + * context must no longer have any reference. If it has been assigned an + * address space before then the AS will be unprogrammed. + */ +void kbase_ctx_sched_remove_ctx_nolock(struct kbase_context *kctx); + /** * kbase_ctx_sched_restore_all_as - Reprogram all address spaces * @kbdev: The device for which address spaces to be reprogrammed @@ -228,7 +242,6 @@ bool kbase_ctx_sched_inc_refcount(struct kbase_context *kctx); */ void kbase_ctx_sched_release_ctx_lock(struct kbase_context *kctx); -#if MALI_USE_CSF /** * kbase_ctx_sched_inc_refcount_if_as_valid - Refcount the context if it has GPU * address space slot assigned to it. @@ -244,6 +257,5 @@ void kbase_ctx_sched_release_ctx_lock(struct kbase_context *kctx); * was not assigned). */ bool kbase_ctx_sched_inc_refcount_if_as_valid(struct kbase_context *kctx); -#endif #endif /* _KBASE_CTX_SCHED_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.c b/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.c deleted file mode 100644 index 679dd75187db..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.c +++ /dev/null @@ -1,544 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include - -#if IS_ENABLED(CONFIG_DEBUG_FS) - -static bool kbase_is_job_fault_event_pending(struct kbase_device *kbdev) -{ - struct list_head *event_list = &kbdev->job_fault_event_list; - unsigned long flags; - bool ret; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - ret = !list_empty(event_list); - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - - return ret; -} - -static void kbase_ctx_remove_pending_event(struct kbase_context *kctx) -{ - struct list_head *event_list = &kctx->kbdev->job_fault_event_list; - struct base_job_fault_event *event; - unsigned long flags; - - spin_lock_irqsave(&kctx->kbdev->job_fault_event_lock, flags); - list_for_each_entry(event, event_list, head) { - if (event->katom->kctx == kctx) { - list_del(&event->head); - WARN_ON_ONCE(&event->job_fault_work != kctx->job_fault_work); - wake_up(&kctx->kbdev->job_fault_resume_wq); - /* job_fault_event_list can only have a single atom for - * each context. - */ - break; - } - } - spin_unlock_irqrestore(&kctx->kbdev->job_fault_event_lock, flags); - if (kctx->job_fault_work) - flush_work(kctx->job_fault_work); -} - -static bool kbase_ctx_has_no_event_pending(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - struct list_head *event_list = &kctx->kbdev->job_fault_event_list; - struct base_job_fault_event *event; - unsigned long flags; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - if (list_empty(event_list)) { - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - return true; - } - list_for_each_entry(event, event_list, head) { - if (event->katom->kctx == kctx) { - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - return false; - } - } - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - return true; -} - -static int wait_for_job_fault(struct kbase_device *kbdev) -{ -#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE - int ret = wait_event_interruptible_timeout(kbdev->job_fault_wq, - kbase_is_job_fault_event_pending(kbdev), - msecs_to_jiffies(2000)); - if (ret == 0) - return -EAGAIN; - else if (ret > 0) - return 0; - else - return ret; -#else - return wait_event_interruptible(kbdev->job_fault_wq, - kbase_is_job_fault_event_pending(kbdev)); -#endif -} - -/* wait until the fault happen and copy the event */ -static int kbase_job_fault_event_wait(struct kbase_device *kbdev, - struct base_job_fault_event *event) -{ - struct list_head *event_list = &kbdev->job_fault_event_list; - struct base_job_fault_event *event_in; - unsigned long flags; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - while (list_empty(event_list)) { - int err; - - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - - err = wait_for_job_fault(kbdev); - if (err) - return err; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - } - - event_in = list_entry(event_list->next, struct base_job_fault_event, head); - event->event_code = event_in->event_code; - event->katom = event_in->katom; - - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - - return 0; -} - -/* remove the event from the queue */ -static struct base_job_fault_event *kbase_job_fault_event_dequeue(struct kbase_device *kbdev, - struct list_head *event_list) -{ - struct base_job_fault_event *event; - - CSTD_UNUSED(kbdev); - - event = list_entry(event_list->next, struct base_job_fault_event, head); - list_del(event_list->next); - - return event; -} - -/* Remove all the following atoms after the failed atom in the same context - * Call the postponed bottom half of job done. - * Then, this context could be rescheduled. - */ -static void kbase_job_fault_resume_event_cleanup(struct kbase_context *kctx) -{ - struct list_head *event_list = &kctx->job_fault_resume_event_list; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - while (!list_empty(event_list)) { - struct base_job_fault_event *event; - - event = kbase_job_fault_event_dequeue(kctx->kbdev, - &kctx->job_fault_resume_event_list); - WARN_ON(work_pending(&event->katom->work)); - INIT_WORK(&event->katom->work, kbase_jd_done_worker); - queue_work(kctx->jctx.job_done_wq, &event->katom->work); - } -} - -static void kbase_job_fault_resume_worker(struct work_struct *data) -{ - struct base_job_fault_event *event = - container_of(data, struct base_job_fault_event, job_fault_work); - struct kbase_device *kbdev; - struct kbase_context *kctx; - struct kbase_jd_atom *katom; - unsigned long flags; - - katom = event->katom; - kctx = katom->kctx; - kbdev = kctx->kbdev; - - dev_info(kbdev->dev, "Job dumping wait\n"); - - /* When it was waked up, it need to check if queue is empty or the - * failed atom belongs to different context. If yes, wake up. Both - * of them mean the failed job has been dumped. Please note, it - * should never happen that the job_fault_event_list has the two - * atoms belong to the same context. - */ - wait_event(kbdev->job_fault_resume_wq, kbase_ctx_has_no_event_pending(kctx)); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - atomic_set(&kctx->job_fault_count, 0); - WARN_ON(work_pending(&katom->work)); - INIT_WORK(&katom->work, kbase_jd_done_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); - - /* In case the following atoms were scheduled during failed job dump - * the job_done_worker was held. We need to rerun it after the dump - * was finished - */ - kbase_job_fault_resume_event_cleanup(kctx); - dev_info(kbdev->dev, "Job dumping finish, resume scheduler\n"); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -} - -static struct base_job_fault_event *kbase_job_fault_event_queue(struct list_head *event_list, - struct kbase_jd_atom *atom, - u32 completion_code) -{ - struct base_job_fault_event *event; - - event = &atom->fault_event; - - event->katom = atom; - event->event_code = completion_code; - - list_add_tail(&event->head, event_list); - - return event; -} - -static void kbase_job_fault_event_post(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - u32 completion_code) -{ - struct base_job_fault_event *event; - unsigned long flags; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - event = kbase_job_fault_event_queue(&kbdev->job_fault_event_list, katom, completion_code); - INIT_WORK(&event->job_fault_work, kbase_job_fault_resume_worker); - katom->kctx->job_fault_work = &event->job_fault_work; - wake_up_interruptible(&kbdev->job_fault_wq); - queue_work(kbdev->job_fault_resume_workq, &event->job_fault_work); - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - - dev_info(katom->kctx->kbdev->dev, "Job fault happen, start dump: %d_%d", katom->kctx->tgid, - katom->kctx->id); -} - -/* - * This function will process the job fault - * Get the register copy - * Send the failed job dump event - * Create a Wait queue to wait until the job dump finish - */ - -bool kbase_debug_job_fault_process(struct kbase_jd_atom *katom, u32 completion_code) -{ - struct kbase_context *kctx = katom->kctx; - - /* Check if dumping is in the process - * only one atom of each context can be dumped at the same time - * If the atom belongs to different context, it can be dumped - */ - if (atomic_read(&kctx->job_fault_count) > 0) { - kbase_job_fault_event_queue(&kctx->job_fault_resume_event_list, katom, - completion_code); - dev_info(kctx->kbdev->dev, "queue:%d\n", kbase_jd_atom_id(kctx, katom)); - return true; - } - - if (kbase_ctx_flag(kctx, KCTX_DYING)) - return false; - - if (atomic_read(&kctx->kbdev->job_fault_debug) > 0) { - if (completion_code != BASE_JD_EVENT_DONE) { - if (kbase_job_fault_get_reg_snapshot(kctx) == false) { - dev_warn(kctx->kbdev->dev, "get reg dump failed\n"); - return false; - } - - kbase_job_fault_event_post(kctx->kbdev, katom, completion_code); - atomic_inc(&kctx->job_fault_count); - dev_info(kctx->kbdev->dev, "post:%d\n", kbase_jd_atom_id(kctx, katom)); - return true; - } - } - return false; -} - -static int debug_job_fault_show(struct seq_file *m, void *v) -{ - struct kbase_device *kbdev = m->private; - struct base_job_fault_event *event = (struct base_job_fault_event *)v; - struct kbase_context *kctx = event->katom->kctx; - int i; - - dev_info(kbdev->dev, "debug job fault seq show:%d_%d, %d", kctx->tgid, kctx->id, - event->reg_offset); - - if (kctx->reg_dump == NULL) { - dev_warn(kbdev->dev, "reg dump is NULL"); - return -1; - } - - if (kctx->reg_dump[event->reg_offset] == REGISTER_DUMP_TERMINATION_FLAG) { - /* Return the error here to stop the read. And the - * following next() will not be called. The stop can - * get the real event resource and release it - */ - return -1; - } - - if (event->reg_offset == 0) - seq_printf(m, "%d_%d\n", kctx->tgid, kctx->id); - - for (i = 0; i < 50; i++) { - if (kctx->reg_dump[event->reg_offset] == REGISTER_DUMP_TERMINATION_FLAG) { - break; - } - seq_printf(m, "%08x: %08x\n", kctx->reg_dump[event->reg_offset], - kctx->reg_dump[1 + event->reg_offset]); - event->reg_offset += 2; - } - - return 0; -} -static void *debug_job_fault_next(struct seq_file *m, void *v, loff_t *pos) -{ - struct kbase_device *kbdev = m->private; - struct base_job_fault_event *event = (struct base_job_fault_event *)v; - - dev_info(kbdev->dev, "debug job fault seq next:%d, %d", event->reg_offset, (int)*pos); - - return event; -} - -static void *debug_job_fault_start(struct seq_file *m, loff_t *pos) -{ - struct kbase_device *kbdev = m->private; - struct base_job_fault_event *event; - - dev_info(kbdev->dev, "fault job seq start:%d", (int)*pos); - - /* The condition is trick here. It needs make sure the - * fault hasn't happened and the dumping hasn't been started, - * or the dumping has finished - */ - if (*pos == 0) { - event = kmalloc(sizeof(*event), GFP_KERNEL); - if (!event) - return NULL; - event->reg_offset = 0; - if (kbase_job_fault_event_wait(kbdev, event)) { - kfree(event); - return NULL; - } - - /* The cache flush workaround is called in bottom half of - * job done but we delayed it. Now we should clean cache - * earlier. Then the GPU memory dump should be correct. - */ - kbase_backend_cache_clean(kbdev, event->katom); - } else - return NULL; - - return event; -} - -static void debug_job_fault_stop(struct seq_file *m, void *v) -{ - struct kbase_device *kbdev = m->private; - - /* here we wake up the kbase_jd_done_worker after stop, it needs - * get the memory dump before the register dump in debug daemon, - * otherwise, the memory dump may be incorrect. - */ - - if (v != NULL) { - kfree(v); - dev_info(kbdev->dev, "debug job fault seq stop stage 1"); - - } else { - unsigned long flags; - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - if (!list_empty(&kbdev->job_fault_event_list)) { - kbase_job_fault_event_dequeue(kbdev, &kbdev->job_fault_event_list); - wake_up(&kbdev->job_fault_resume_wq); - } - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - dev_info(kbdev->dev, "debug job fault seq stop stage 2"); - } -} - -static const struct seq_operations ops = { - .start = debug_job_fault_start, - .next = debug_job_fault_next, - .stop = debug_job_fault_stop, - .show = debug_job_fault_show, -}; - -static int debug_job_fault_open(struct inode *in, struct file *file) -{ - struct kbase_device *kbdev = in->i_private; - - if (atomic_cmpxchg(&kbdev->job_fault_debug, 0, 1) == 1) { - dev_warn(kbdev->dev, "debug job fault is busy, only a single client is allowed"); - return -EBUSY; - } - - seq_open(file, &ops); - - ((struct seq_file *)file->private_data)->private = kbdev; - dev_info(kbdev->dev, "debug job fault seq open"); - - return 0; -} - -static int debug_job_fault_release(struct inode *in, struct file *file) -{ - struct kbase_device *kbdev = in->i_private; - struct list_head *event_list = &kbdev->job_fault_event_list; - unsigned long flags; - - seq_release(in, file); - - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - - /* Disable job fault dumping. This will let kbase run jobs as normal, - * without blocking waiting for a job_fault client to read failed jobs. - * - * After this a new client may open the file, and may re-enable job - * fault dumping, but the job_fault_event_lock we hold here will block - * that from interfering until after we've completed the cleanup. - */ - atomic_dec(&kbdev->job_fault_debug); - - /* Clean the unprocessed job fault. After that, all the suspended - * contexts could be rescheduled. Remove all the failed atoms that - * belong to different contexts Resume all the contexts that were - * suspend due to failed job. - */ - while (!list_empty(event_list)) { - kbase_job_fault_event_dequeue(kbdev, event_list); - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - wake_up(&kbdev->job_fault_resume_wq); - spin_lock_irqsave(&kbdev->job_fault_event_lock, flags); - } - - spin_unlock_irqrestore(&kbdev->job_fault_event_lock, flags); - - dev_info(kbdev->dev, "debug job fault seq close"); - - return 0; -} - -static const struct file_operations kbasep_debug_job_fault_fops = { - .owner = THIS_MODULE, - .open = debug_job_fault_open, - .read = seq_read, - .llseek = seq_lseek, - .release = debug_job_fault_release, -}; - -/* - * Initialize debugfs entry for job fault dump - */ -void kbase_debug_job_fault_debugfs_init(struct kbase_device *kbdev) -{ - debugfs_create_file("job_fault", 0400, kbdev->mali_debugfs_directory, kbdev, - &kbasep_debug_job_fault_fops); -} - -int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev) -{ - INIT_LIST_HEAD(&kbdev->job_fault_event_list); - - init_waitqueue_head(&(kbdev->job_fault_wq)); - init_waitqueue_head(&(kbdev->job_fault_resume_wq)); - spin_lock_init(&kbdev->job_fault_event_lock); - - kbdev->job_fault_resume_workq = - alloc_workqueue("kbase_job_fault_resume_work_queue", WQ_MEM_RECLAIM, 1); - if (!kbdev->job_fault_resume_workq) - return -ENOMEM; - - return 0; -} - -/* - * Release the relevant resource per device - */ -void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev) -{ - destroy_workqueue(kbdev->job_fault_resume_workq); -} - -/* - * Initialize the relevant data structure per context - */ -int kbase_debug_job_fault_context_init(struct kbase_context *kctx) -{ - /* We need allocate double size register range - * Because this memory will keep the register address and value - */ - kctx->reg_dump = vmalloc(0x4000 * 2); - if (kctx->reg_dump != NULL) { - if (kbase_debug_job_fault_reg_snapshot_init(kctx, 0x4000) == false) { - vfree(kctx->reg_dump); - kctx->reg_dump = NULL; - } - INIT_LIST_HEAD(&kctx->job_fault_resume_event_list); - } - - return 0; -} - -/* - * release the relevant resource per context - */ -void kbase_debug_job_fault_context_term(struct kbase_context *kctx) -{ - vfree(kctx->reg_dump); -} - -void kbase_debug_job_fault_kctx_unblock(struct kbase_context *kctx) -{ - WARN_ON(!kbase_ctx_flag(kctx, KCTX_DYING)); - - /* Return early if the job fault part of the kbase_device is not - * initialized yet. An error can happen during the device probe after - * the privileged Kbase context was created for the HW counter dumping - * but before the job fault part is initialized. - */ - if (!kctx->kbdev->job_fault_resume_workq) - return; - - kbase_ctx_remove_pending_event(kctx); -} - -#else /* CONFIG_DEBUG_FS */ - -int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev) -{ - return 0; -} - -void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev) -{ -} - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.h b/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.h deleted file mode 100644 index ee1228155621..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_debug_job_fault.h +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_DEBUG_JOB_FAULT_H -#define _KBASE_DEBUG_JOB_FAULT_H - -#include - -struct kbase_context; -struct kbase_device; - -#define REGISTER_DUMP_TERMINATION_FLAG 0xFFFFFFFF - -/** - * kbase_debug_job_fault_dev_init - Create the fault event wait queue - * per device and initialize the required lists. - * @kbdev: Device pointer - * - * This function must be called only when a kbase device is initialized. - * - * Return: Zero on success or a negative error code. - */ -int kbase_debug_job_fault_dev_init(struct kbase_device *kbdev); - -/** - * kbase_debug_job_fault_debugfs_init - Initialize job fault debug sysfs - * @kbdev: Device pointer - */ -void kbase_debug_job_fault_debugfs_init(struct kbase_device *kbdev); - -/** - * kbase_debug_job_fault_dev_term - Clean up resources created in - * kbase_debug_job_fault_dev_init. - * @kbdev: Device pointer - */ -void kbase_debug_job_fault_dev_term(struct kbase_device *kbdev); - -/** - * kbase_debug_job_fault_context_init - Initialize the relevant data structure per context - * @kctx: KBase context pointer - * - * This function must be called only when a kbase context is instantiated. - * - * Return: 0 on success - */ -int kbase_debug_job_fault_context_init(struct kbase_context *kctx); - -/** - * kbase_debug_job_fault_context_term - Release the relevant - * resource per context - * @kctx: KBase context pointer - */ -void kbase_debug_job_fault_context_term(struct kbase_context *kctx); - -/** - * kbase_debug_job_fault_kctx_unblock - Unblock the atoms blocked on job fault - * dumping on context termination. - * - * @kctx: KBase context pointer - * - * This function is called during context termination to unblock the atom for - * which the job fault occurred and also the atoms following it. This is needed - * otherwise the wait for zero jobs could timeout (leading to an assertion - * failure, kernel panic in debug builds) in the pathological case where - * although the thread/daemon capturing the job fault events is running, - * but for some reasons has stopped consuming the events. - */ -void kbase_debug_job_fault_kctx_unblock(struct kbase_context *kctx); - -/** - * kbase_debug_job_fault_process - Process the failed job. - * - * @katom: The failed atom pointer - * @completion_code: the job status - * - * It will send a event and wake up the job fault waiting queue - * Then create a work queue to wait for job dump finish - * This function should be called in the interrupt handler and before - * jd_done that make sure the jd_done_worker will be delayed until the - * job dump finish - * - * Return: true if dump is going on - */ -bool kbase_debug_job_fault_process(struct kbase_jd_atom *katom, u32 completion_code); - -/** - * kbase_debug_job_fault_reg_snapshot_init - Set the interested registers - * address during the job fault process, the relevant registers will - * be saved when a job fault happen - * @kctx: KBase context pointer - * @reg_range: Maximum register address space - * - * Return: true if initializing successfully - */ -bool kbase_debug_job_fault_reg_snapshot_init(struct kbase_context *kctx, int reg_range); - -/** - * kbase_job_fault_get_reg_snapshot - Read the interested registers for - * failed job dump - * - * @kctx: KBase context pointer - * - * Return: true if getting registers successfully - */ -bool kbase_job_fault_get_reg_snapshot(struct kbase_context *kctx); - -#endif /*_KBASE_DEBUG_JOB_FAULT_H*/ diff --git a/drivers/gpu/arm/valhall/mali_kbase_debug_mem_zones.c b/drivers/gpu/arm/valhall/mali_kbase_debug_mem_zones.c index 01267b599d89..3964b5505bdd 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_debug_mem_zones.c +++ b/drivers/gpu/arm/valhall/mali_kbase_debug_mem_zones.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2022-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2022-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -63,7 +63,6 @@ static int debug_mem_zones_show(struct seq_file *sfile, void *data) reg_zone->va_size_pages); } } -#if MALI_USE_CSF reg_zone = &kctx->kbdev->csf.mcu_shared_zone; if (reg_zone && reg_zone->base_pfn) { @@ -71,7 +70,6 @@ static int debug_mem_zones_show(struct seq_file *sfile, void *data) kbase_reg_zone_get_name(MCU_SHARED_ZONE), MCU_SHARED_ZONE, reg_zone->base_pfn, reg_zone->va_size_pages); } -#endif kbase_gpu_vm_unlock(kctx); return 0; diff --git a/drivers/gpu/arm/valhall/mali_kbase_defs.h b/drivers/gpu/arm/valhall/mali_kbase_defs.h index 978e76c3fdcf..5edab9b44b9b 100755 --- a/drivers/gpu/arm/valhall/mali_kbase_defs.h +++ b/drivers/gpu/arm/valhall/mali_kbase_defs.h @@ -39,12 +39,7 @@ #include #include -#if MALI_USE_CSF #include -#else -#include -#include -#endif #include "debug/mali_kbase_debug_ktrace_defs.h" @@ -126,7 +121,6 @@ */ #define KBASE_HWCNT_GPU_VIRTUALIZER_DUMP_THRESHOLD_NS (200 * NSEC_PER_USEC) -#if MALI_USE_CSF /* The buffer count of CSF hwcnt backend ring buffer, which is used when CSF * hwcnt backend allocate the ring buffer to communicate with CSF firmware for * HWC dump samples. @@ -134,7 +128,6 @@ * CSF hwcnt backend creation will be failed. */ #define KBASE_HWCNT_BACKEND_CSF_RING_BUFFER_COUNT (128) -#endif /* Maximum number of clock/regulator pairs that may be referenced by * the device node. @@ -150,7 +143,6 @@ struct kbase_context; struct kbase_device; struct kbase_as; struct kbase_mmu_setup; -struct kbase_kinstr_jm; struct kbase_io; #if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) @@ -358,11 +350,7 @@ struct kbase_mmu_table { #endif }; -#if MALI_USE_CSF #include "csf/mali_kbase_csf_defs.h" -#else -#include "jm/mali_kbase_jm_defs.h" -#endif #include "mali_kbase_hwaccess_time.h" @@ -459,6 +447,12 @@ struct kbase_clk_rate_trace_manager { * has already been called from the power_on callback, then * the call to it from runtime_gpu_active callback can be * skipped. + * @runtime_suspend_result: Stores the return value of + * kbase_pm_handle_runtime_suspend() to be passed back + * to the kernel. This is consumed in + * kbase_device_runtime_suspend() once the runtime + * suspend event has been handled by the CSF scheduler + * kthread. * @gpu_lost: Flag indicating gpu lost * This structure contains data for the power management framework. * There is one instance of this structure per device in the system. @@ -466,8 +460,8 @@ struct kbase_clk_rate_trace_manager { * @resume_wait: Wait queue to wait for the System suspend/resume of GPU device. * @debug_core_mask: Bit masks identifying the available shader cores that are * specified via sysfs. One mask per job slot. - * @debug_core_mask_all: Bit masks identifying the available shader cores that - * are specified via sysfs. + * @sysfs_gov_core_mask: Bit masks identifying the available shader cores that are + * specified via sysfs when writing to GOV_CORE_MASK. * @callback_power_runtime_init: Callback for initializing the runtime power * management. Return 0 on success, else error code * @callback_power_runtime_term: Callback for terminating the runtime power @@ -485,20 +479,14 @@ struct kbase_pm_device_data { int active_count; bool suspending; bool resuming; -#if MALI_USE_CSF bool runtime_active; -#endif + int runtime_suspend_result; atomic_t gpu_lost; wait_queue_head_t zero_active_count_wait; wait_queue_head_t resume_wait; -#if MALI_USE_CSF u64 debug_core_mask; -#else - /* One mask per job slot. */ - u64 debug_core_mask[BASE_JM_MAX_NR_SLOTS]; - u64 debug_core_mask_all; -#endif /* MALI_USE_CSF */ + u64 sysfs_gov_core_mask; int (*callback_power_runtime_init)(struct kbase_device *kbdev); void (*callback_power_runtime_term)(struct kbase_device *kbdev); @@ -530,13 +518,12 @@ struct kbase_pm_device_data { * @isolation_in_progress_cnt: Number of pages in pool undergoing page isolation. * This is used to avoid race condition between pool termination * and page isolation for page migration. - * @next_pool: Pointer to next pool where pages can be allocated when this - * pool is empty. Pages will spill over to the next pool when - * this pool is full. Can be NULL if there is no next pool. * @dying: true if the pool is being terminated, and any ongoing * operations should be abandoned - * @dont_reclaim: true if the shrinker is forbidden from reclaiming memory from - * this pool, eg during a grow operation + * @pool_supports_reclaim: Whether this pool supports page reclaiming. + * @reclaim_allowed: true if the shrinker is currently allowed to reclaim from this + * pool. Otherwise, false: the shrinker is forbidden from reclaiming + * memory from it - eg during a grow operation. */ struct kbase_mem_pool { struct kbase_device *kbdev; @@ -549,10 +536,9 @@ struct kbase_mem_pool { DEFINE_KBASE_SHRINKER reclaim; atomic_t isolation_in_progress_cnt; - struct kbase_mem_pool *next_pool; - bool dying; - bool dont_reclaim; + bool pool_supports_reclaim; + bool reclaim_allowed; }; /** @@ -599,6 +585,20 @@ struct kbase_mem_pool_group_config { struct kbase_mem_pool_config large[MEMORY_GROUP_MANAGER_NR_GROUPS]; }; +/** + * struct kbase_fw_mem_pool_group - a set of physical memory pools for fw load. + * + * @small: Object containing the state for pool of small size + * physical pages. + * @large: Object containing the state for pool of large size + * physical pages. + * + */ +struct kbase_fw_mem_pool_group { + struct kbase_mem_pool small; + struct kbase_mem_pool large; +}; + /** * struct kbase_devfreq_opp - Lookup table for converting between nominal OPP * frequency, real frequencies and core mask @@ -702,6 +702,7 @@ struct kbase_devfreq_queue_info { * imported multiple times for the process. */ struct kbase_process { + struct kobject kobj; pid_t tgid; size_t total_gpu_pages; struct list_head kctx_list; @@ -819,12 +820,11 @@ struct kbase_mem_migrate { * framework. * @fw_load_lock: Mutex to protect firmware loading in @ref kbase_open. * @csf: CSF object for the GPU device. - * @js_data: Per device object encapsulating the current context of - * Job Scheduler, which is global to the device and is not - * tied to any particular struct kbase_context running on - * the device - * @mem_pools: Global pools of free physical memory pages which can - * be used by all the contexts. + * @pgd_mem_pool: Global pool of free physical memory pages dedicated to + * allocation of pgd pages that are not associated with + * contexts. + * @fw_mem_pools: Global pools of free physical memory pages which can + * be used by firmware load subroutine. * @memdev: keeps track of the in use physical pages allocated by * the Driver. * @mmu_mode: Pointer to the object containing methods for programming @@ -857,17 +857,6 @@ struct kbase_mem_migrate { * @nr_user_address_spaces: Number of address spaces available to user contexts * @hwcnt_backend_csf_if_fw: Firmware interface to access CSF GPU performance * counters. - * @hwcnt: Structure used for instrumentation and HW counters - * dumping - * @hwcnt.lock: The lock should be used when accessing any of the - * following members - * @hwcnt.kctx: kbase context - * @hwcnt.addr: HW counter address - * @hwcnt.addr_bytes: HW counter size in bytes - * @hwcnt.backend: Kbase instrumentation backend - * @hwcnt_gpu_jm_backend: Job manager GPU backend interface, used as superclass reference - * pointer by hwcnt_gpu_iface, which wraps this implementation in - * order to extend it with periodic dumping functionality. * @hwcnt_gpu_iface: Backend interface for GPU hardware counter access. * @hwcnt_watchdog_timer: Watchdog interface, used by the GPU backend hwcnt_gpu_iface to * perform periodic dumps in order to prevent hardware counter value @@ -955,26 +944,12 @@ struct kbase_mem_migrate { * @previous_frequency: Previous frequency of GPU clock used for * KBASE_HW_ISSUE_GPU2017_1336 workaround, This clock is * restored when L2 is powered on. - * @job_fault_debug: Flag to control the dumping of debug data for job faults, - * set when the 'job_fault' debugfs file is opened. * @mali_debugfs_directory: Root directory for the debugfs files created by the driver * @debugfs_ctx_directory: Directory inside the @mali_debugfs_directory containing * a sub-directory for every context. * @debugfs_instr_directory: Instrumentation debugfs directory * @debugfs_as_read_bitmap: bitmap of address spaces for which the bus or page fault * has occurred. - * @job_fault_wq: Waitqueue to block the job fault dumping daemon till the - * occurrence of a job fault. - * @job_fault_resume_wq: Waitqueue on which every context with a faulty job wait - * for the job fault dumping to complete before they can - * do bottom half of job done for the atoms which followed - * the faulty atom. - * @job_fault_resume_workq: workqueue to process the work items queued for the faulty - * atoms, whereby the work item function waits for the dumping - * to get completed. - * @job_fault_event_list: List of atoms, each belonging to a different context, which - * generated a job fault. - * @job_fault_event_lock: Lock to protect concurrent accesses to @job_fault_event_list * @regs_dump_debugfs_data: Contains the offset of register to be read through debugfs * file "read_register". * @regs_dump_debugfs_data.reg_offset: Contains the offset of register to be @@ -995,8 +970,6 @@ struct kbase_mem_migrate { * power on for GPU is started. * @infinite_cache_active_default: Set to enable using infinite cache for all the * allocations of a new context. - * @mem_pool_defaults: Default configuration for the group of memory pools - * created for a new context. * @current_gpu_coherency_mode: coherency mode in use, which can be different * from @system_coherency, when using protected mode. * @system_coherency: coherency mode as retrieved from the device tree. @@ -1029,10 +1002,6 @@ struct kbase_mem_migrate { * the updates made to Job dispatcher + scheduler states. * @mmu_hw_mutex: Protects access to MMU operations and address space * related state. - * @serialize_jobs: Currently used mode for serialization of jobs, both - * intra & inter slots serialization is supported. - * @js_ctx_scheduling_mode: Context scheduling mode currently being used by - * Job Scheduler * @l2_size_override: Used to set L2 cache size via device tree blob * @l2_hash_override: Used to set L2 cache hash via device tree blob * @l2_hash_values_override: true if @l2_hash_values is valid. @@ -1086,9 +1055,7 @@ struct kbase_device { u32 hw_quirks_tiler; u32 hw_quirks_mmu; u32 hw_quirks_gpu; -#if MALI_USE_CSF u32 hw_quirks_ne; -#endif struct list_head entry; struct device *dev; @@ -1114,6 +1081,7 @@ struct kbase_device { unsigned int nr_regulators; #endif /* CONFIG_REGULATOR */ char devname[DEVNAME_SIZE]; + struct kobject *kprcs_kobj; u32 id; #if !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) @@ -1128,7 +1096,8 @@ struct kbase_device { #endif /* !IS_ENABLED(CONFIG_MALI_VALHALL_REAL_HW) */ struct kbase_pm_device_data pm; - struct kbase_mem_pool_group mem_pools; + struct kbase_mem_pool pgd_mem_pool; + struct kbase_fw_mem_pool_group fw_mem_pools; struct kbasep_mem_device memdev; struct kbase_mmu_mode const *mmu_mode; @@ -1166,21 +1135,7 @@ struct kbase_device { */ u32 mma_wa_id; -#if MALI_USE_CSF struct kbase_hwcnt_backend_csf_if hwcnt_backend_csf_if_fw; -#else - struct kbase_hwcnt { - spinlock_t lock; - - struct kbase_context *kctx; - u64 addr; - u64 addr_bytes; - - struct kbase_instr_backend backend; - } hwcnt; - - struct kbase_hwcnt_backend_interface hwcnt_gpu_jm_backend; -#endif struct kbase_hwcnt_backend_interface hwcnt_gpu_iface; struct kbase_hwcnt_watchdog_interface hwcnt_watchdog_timer; @@ -1253,10 +1208,6 @@ struct kbase_device { #endif /* CONFIG_MALI_VALHALL_DEVFREQ */ unsigned long previous_frequency; -#if !MALI_USE_CSF - atomic_t job_fault_debug; -#endif /* !MALI_USE_CSF */ - struct dentry *mali_debugfs_directory; struct dentry *debugfs_ctx_directory; struct dentry *debugfs_instr_directory; @@ -1265,14 +1216,6 @@ struct kbase_device { u64 debugfs_as_read_bitmap; #endif /* CONFIG_MALI_VALHALL_DEBUG */ -#if !MALI_USE_CSF - wait_queue_head_t job_fault_wq; - wait_queue_head_t job_fault_resume_wq; - struct workqueue_struct *job_fault_resume_workq; - struct list_head job_fault_event_list; - spinlock_t job_fault_event_lock; -#endif /* !MALI_USE_CSF */ - #if !MALI_CUSTOMER_RELEASE struct { u32 reg_offset; @@ -1294,8 +1237,6 @@ struct kbase_device { bool infinite_cache_active_default; - struct kbase_mem_pool_group_config mem_pool_defaults; - u32 current_gpu_coherency_mode; u32 system_coherency; @@ -1335,19 +1276,8 @@ struct kbase_device { u32 sysc_alloc[GPU_SYSC_ALLOC_COUNT]; struct mutex fw_load_lock; -#if MALI_USE_CSF /* CSF object for the GPU device. */ struct kbase_csf_device csf; -#else - struct kbasep_js_device_data js_data; - - /* See KBASE_JS_*_PRIORITY_MODE for details. */ - u32 js_ctx_scheduling_mode; - - /* See KBASE_SERIALIZE_* for details */ - u8 serialize_jobs; - -#endif /* MALI_USE_CSF */ struct rb_root process_root; struct rb_root dma_buf_root; @@ -1370,22 +1300,9 @@ struct kbase_device { struct notifier_block oom_notifier_block; -#if !MALI_USE_CSF - spinlock_t quick_reset_lock; - bool quick_reset_enabled; - /* - * 进入 quck_reset_mode 后 (quick_reset_enabled 为 true), - * 对已经进入 KBASE_JD_ATOM_STATE_HW_COMPLETED 状态的 atom 的计数. - * - * 若 num_of_atoms_hw_completed 达到一定值, 将退出 quck_reset_mode. - * 见 kbase_js_complete_atom() 对 num_of_atoms_hw_completed 的引用. - */ - u32 num_of_atoms_hw_completed; -#endif - struct kbase_mem_migrate mem_migrate; -#if MALI_USE_CSF && IS_ENABLED(CONFIG_SYNC_FILE) +#if IS_ENABLED(CONFIG_SYNC_FILE) atomic_t live_fence_metadata; #endif struct kmem_cache *va_region_slab; @@ -1397,9 +1314,7 @@ struct kbase_device { */ struct kbase_gpu_metrics gpu_metrics; #endif -#if MALI_USE_CSF atomic_t fence_signal_timeout_enabled; -#endif struct notifier_block pcm_prioritized_process_nb; @@ -1652,9 +1567,6 @@ struct kbase_sub_alloc { * events to Userspace. * @event_mutex: Lock to protect the concurrent access to @event_list & * @event_mutex. - * @event_closed: Flag set through POST_TERM ioctl, indicates that Driver - * should stop posting events and also inform event handling - * thread that context termination is in progress. * @event_workq: Workqueue for processing work items corresponding to atoms * that do not return an event to userspace. * @event_count: Count of the posted events to be consumed by Userspace. @@ -1710,8 +1622,6 @@ struct kbase_sub_alloc { * an application becomes foreground or goes to the * background. * @csf: kbase csf context - * @jctx: object encapsulating all the Job dispatcher related state, - * including the array of atoms. * @used_pages: Keeps a track of the number of small physical pages in use * for the context. * @nonmapped_pages: Updated in the same way as @used_pages, except for the case @@ -1719,6 +1629,8 @@ struct kbase_sub_alloc { * is reset to 0. * @permanent_mapped_pages: Usage count of permanently mapped memory * @mem_pools: Context-specific pools of free physical memory pages. + * Note that context-specific PGDs are not allocated from this. + * @pgd_mem_pool: Context-specific pool dedicated to allocation of PGDs. * @reclaim: Shrinker object registered with the kernel containing * the pointer to callback function which is invoked under * low memory conditions. In the callback function Driver @@ -1787,23 +1699,6 @@ struct kbase_sub_alloc { * output of "mem_view" debugfs file. * @job_fault_work: Tracking the latest fault dump work item for assisting the * operation of the job-fault-dump debug process. - * @jsctx_queue: Per slot & priority arrays of object containing the root - * of RB-tree holding currently runnable atoms on the job slot - * and the head item of the linked list of atoms blocked on - * cross-slot dependencies. - * @slot_tracking: Tracking and control of this context's use of all job - * slots - * @atoms_pulled_all_slots: Total number of atoms currently pulled from the - * context, across all slots. - * @slots_pullable: Bitmask of slots, indicating the slots for which the - * context has pullable atoms in the runnable tree. - * @completed_jobs: List containing completed atoms for which base_jd_event is - * to be posted. - * @work_count: Number of work items, corresponding to atoms, currently - * pending on job_done workqueue of @jctx. - * @soft_job_timeout: Timer object used for failing/cancelling the waiting - * soft-jobs which have been blocked for more than the - * timeout value used for the soft-jobs * @jit_alloc: Array of 256 pointers to GPU memory regions, used for * just-in-time memory allocations. * @jit_max_allocations: Maximum allowed number of in-flight @@ -1858,30 +1753,22 @@ struct kbase_sub_alloc { * @ext_res_meta_head: A list of sticky external resources which were requested to * be mapped on GPU side, through a softjob atom of type * EXT_RES_MAP or STICKY_RESOURCE_MAP ioctl. - * @age_count: Counter incremented on every call to jd_submit_atom, - * atom is assigned the snapshot of this counter, which - * is used to determine the atom's age when it is added to - * the runnable RB-tree. * @trim_level: Level of JIT allocation trimming to perform on free (0-100%) * @kprcs: Reference to @struct kbase_process that the current * kbase_context belongs to. * @kprcs_link: List link for the list of kbase context maintained * under kbase_process. - * @priority: Indicates the context priority. Used along with @atoms_count - * for context scheduling, protected by hwaccess_lock. - * @atoms_count: Number of GPU atoms currently in use, per priority * @create_flags: Flags used in context creation. - * @kinstr_jm: Kernel job manager instrumentation context handle * @tl_kctx_list_node: List item into the device timeline's list of * contexts, for timeline summarization. * @limited_core_mask: The mask that is applied to the affinity in case of atoms * marked with BASE_JD_REQ_LIMITED_CORE_MASK. - * @platform_data: Pointer to platform specific per-context data. * @task: Pointer to the task structure of the main thread of the process * that created the Kbase context. It would be set only for the * contexts created by the Userspace and not for the contexts * created internally by the Kbase. * @comm: Record the process name + * @offslot_ts: System time in ns when all CSGs belonged to this kctx become offslot. * * A kernel base context is an entity among which the GPU is scheduled. * Each context has its own GPU address space. @@ -1900,9 +1787,6 @@ struct kbase_context { struct list_head event_list; struct list_head event_coalesce_list; struct mutex event_mutex; -#if !MALI_USE_CSF - atomic_t event_closed; -#endif struct workqueue_struct *event_workq; atomic_t event_count; int event_coalesce_count; @@ -1915,29 +1799,11 @@ struct kbase_context { struct list_head mem_partials; struct mutex reg_lock; -#if MALI_USE_CSF atomic64_t num_fixable_allocs; atomic64_t num_fixed_allocs; -#endif struct kbase_reg_zone reg_zone[CONTEXT_ZONE_MAX]; -#if MALI_USE_CSF struct kbase_csf_context csf; -#else - struct kbase_jd_context jctx; - struct jsctx_queue jsctx_queue[KBASE_JS_ATOM_SCHED_PRIO_COUNT][BASE_JM_MAX_NR_SLOTS]; - struct kbase_jsctx_slot_tracking slot_tracking[BASE_JM_MAX_NR_SLOTS]; - atomic_t atoms_pulled_all_slots; - - struct list_head completed_jobs; - atomic_t work_count; - struct timer_list soft_job_timeout; - - int priority; - s16 atoms_count[KBASE_JS_ATOM_SCHED_PRIO_COUNT]; - u32 slots_pullable; - u32 age_count; -#endif /* MALI_USE_CSF */ DECLARE_BITMAP(cookies, BITS_PER_LONG); struct kbase_va_region *pending_regions[BITS_PER_LONG]; @@ -1951,6 +1817,7 @@ struct kbase_context { atomic_t permanent_mapped_pages; struct kbase_mem_pool_group mem_pools; + struct kbase_mem_pool pgd_mem_pool; DEFINE_KBASE_SHRINKER reclaim; @@ -1966,11 +1833,9 @@ struct kbase_context { struct mm_struct *process_mm; u64 gpu_va_end; -#if MALI_USE_CSF u32 running_total_tiler_heap_nr_chunks; u64 running_total_tiler_heap_memory; u64 peak_total_tiler_heap_memory; -#endif bool jit_va; #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -2011,17 +1876,10 @@ struct kbase_context { base_context_create_flags create_flags; -#if !MALI_USE_CSF - struct kbase_kinstr_jm *kinstr_jm; -#endif struct list_head tl_kctx_list_node; u64 limited_core_mask; -#if !MALI_USE_CSF - void *platform_data; -#endif - struct task_struct *task; #if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) @@ -2033,6 +1891,8 @@ struct kbase_context { #endif char comm[TASK_COMM_LEN]; + + u64 offslot_ts; }; /** diff --git a/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.c b/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.c deleted file mode 100644 index 10bbb64f7def..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.c +++ /dev/null @@ -1,404 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Implementation of the dummy job execution workaround for the GPU hang issue. - */ - -#include -#include -#include -#include - -#include -#include - -#define DUMMY_JOB_WA_BINARY_NAME "valhall-1691526.wa" - -struct wa_header { - u16 signature; - u16 version; - u32 info_offset; -} __packed; - -struct wa_v2_info { - u64 jc; - u32 js; - u32 blob_offset; - u64 flags; -} __packed; - -struct wa_blob { - u64 base; - u32 size; - u32 map_flags; - u32 payload_offset; - u32 blob_offset; -} __packed; - -static bool within_range(const u8 *base, const u8 *end, off_t off, size_t sz) -{ - return !((size_t)(end - base - off) < sz); -} - -static u32 wait_any(struct kbase_device *kbdev, off_t offset, u32 bits) -{ - int loop; - const int timeout = 100; - u32 val; - - for (loop = 0; loop < timeout; loop++) { - val = kbase_reg_read32(kbdev, offset); - if (val & bits) - break; - udelay(10); - } - - if (loop == timeout) { - dev_err(kbdev->dev, - "Timeout reading register 0x%lx, bits 0x%lx, last read was 0x%lx\n", - (unsigned long)offset, (unsigned long)bits, (unsigned long)val); - } - - return (val & bits); -} - -static inline int run_job(struct kbase_device *kbdev, int as, u32 slot, u64 cores, u64 jc) -{ - u32 done; - - /* setup job */ - kbase_reg_write64(kbdev, JOB_SLOT_OFFSET(slot, HEAD_NEXT), jc); - kbase_reg_write64(kbdev, JOB_SLOT_OFFSET(slot, AFFINITY_NEXT), cores); - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(slot, CONFIG_NEXT), - JS_CONFIG_DISABLE_DESCRIPTOR_WR_BK | (unsigned int)as); - - /* go */ - kbase_reg_write32(kbdev, JOB_SLOT_OFFSET(slot, COMMAND_NEXT), JS_COMMAND_START); - - /* wait for the slot to finish (done, error) */ - done = wait_any(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_RAWSTAT), - (1ul << (16 + slot)) | (1ul << slot)); - kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_CLEAR), done); - - if (done != (1ul << slot)) { - dev_err(kbdev->dev, "Failed to run WA job on slot %u cores 0x%llx: done 0x%lx\n", - slot, (unsigned long long)cores, (unsigned long)done); - dev_err(kbdev->dev, "JS_STATUS on failure: 0x%x\n", - kbase_reg_read32(kbdev, JOB_SLOT_OFFSET(slot, STATUS))); - - return -EFAULT; - } else { - return 0; - } -} - -/* To be called after power up & MMU init, but before everything else */ -int kbase_dummy_job_wa_execute(struct kbase_device *kbdev, u64 cores) -{ - int as; - u32 slot; - u64 jc; - int failed = 0; - int runs = 0; - u32 old_gpu_mask; - u32 old_job_mask; - u64 val; - const u32 timeout_us = 10000; - - if (!kbdev) - return -EFAULT; - - if (!kbdev->dummy_job_wa.kctx) - return -EFAULT; - - as = kbdev->dummy_job_wa.kctx->as_nr; - slot = kbdev->dummy_job_wa.slot; - jc = kbdev->dummy_job_wa.jc; - - /* mask off all but MMU IRQs */ - old_gpu_mask = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK)); - old_job_mask = kbase_reg_read32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK)); - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), 0); - kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK), 0); - - /* power up requested cores */ - kbase_reg_write64(kbdev, GPU_CONTROL_ENUM(SHADER_PWRON), cores); - - if (kbdev->dummy_job_wa.flags & KBASE_DUMMY_JOB_WA_FLAG_WAIT_POWERUP) { - /* wait for power-ups */ - kbase_reg_poll64_timeout(kbdev, GPU_CONTROL_ENUM(SHADER_READY), val, - (val & cores) == cores, 10, timeout_us, false); - } - - if (kbdev->dummy_job_wa.flags & KBASE_DUMMY_JOB_WA_FLAG_SERIALIZE) { - size_t i; - - /* do for each requested core */ - for (i = 0; i < sizeof(cores) * 8; i++) { - u64 affinity; - - affinity = 1ull << i; - - if (!(cores & affinity)) - continue; - - if (run_job(kbdev, as, slot, affinity, jc)) - failed++; - runs++; - } - - } else { - if (run_job(kbdev, as, slot, cores, jc)) - failed++; - runs++; - } - - if (kbdev->dummy_job_wa.flags & KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER) { - /* power off shader cores (to reduce any dynamic leakage) */ - kbase_reg_write64(kbdev, GPU_CONTROL_ENUM(SHADER_PWROFF), cores); - - /* wait for power off complete */ - kbase_reg_poll64_timeout(kbdev, GPU_CONTROL_ENUM(SHADER_READY), val, !(val & cores), - 10, timeout_us, false); - kbase_reg_poll64_timeout(kbdev, GPU_CONTROL_ENUM(SHADER_PWRTRANS), val, - !(val & cores), 10, timeout_us, false); - - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_CLEAR), U32_MAX); - } - - /* restore IRQ masks */ - kbase_reg_write32(kbdev, GPU_CONTROL_ENUM(GPU_IRQ_MASK), old_gpu_mask); - kbase_reg_write32(kbdev, JOB_CONTROL_ENUM(JOB_IRQ_MASK), old_job_mask); - - if (failed) - dev_err(kbdev->dev, "WA complete with %d failures out of %d runs\n", failed, runs); - - return failed ? -EFAULT : 0; -} - -static ssize_t dummy_job_wa_info_show(struct device *const dev, struct device_attribute *const attr, - char *const buf) -{ - struct kbase_device *const kbdev = dev_get_drvdata(dev); - int err; - - CSTD_UNUSED(attr); - - if (!kbdev || !kbdev->dummy_job_wa.kctx) - return -ENODEV; - - err = scnprintf(buf, PAGE_SIZE, "slot %u flags %llx\n", kbdev->dummy_job_wa.slot, - kbdev->dummy_job_wa.flags); - - return err; -} - -static DEVICE_ATTR_RO(dummy_job_wa_info); - -static bool wa_blob_load_needed(struct kbase_device *kbdev) -{ - if (kbdev->gpu_props.impl_tech >= THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_FPGA) - return false; - - if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_TTRX_3485)) - return true; - - return false; -} - -int kbase_dummy_job_wa_load(struct kbase_device *kbdev) -{ - const struct firmware *firmware; - static const char wa_name[] = DUMMY_JOB_WA_BINARY_NAME; - const u32 signature = 0x4157; - const u32 version = 2; - const u8 *fw_end; - const u8 *fw; - const struct wa_header *header; - const struct wa_v2_info *v2_info; - u32 blob_offset; - int err; - struct kbase_context *kctx; - - /* Calls to this function are inherently asynchronous, with respect to - * MMU operations. - */ - const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; - - lockdep_assert_held(&kbdev->fw_load_lock); - - if (!wa_blob_load_needed(kbdev)) - return 0; - - /* load the wa */ - err = request_firmware(&firmware, wa_name, kbdev->dev); - - if (err) { - dev_err(kbdev->dev, - "WA blob missing. Please refer to the Arm Mali DDK Valhall Release Notes, " - "Part number DC-06002 or contact support-mali@arm.com - driver probe will be failed"); - return -ENODEV; - } - - kctx = kbase_create_context(kbdev, true, BASE_CONTEXT_CREATE_FLAG_NONE, 0, NULL); - - if (!kctx) { - dev_err(kbdev->dev, "Failed to create WA context\n"); - goto no_ctx; - } - - fw = firmware->data; - fw_end = fw + firmware->size; - - dev_dbg(kbdev->dev, "Loaded firmware of size %zu bytes\n", firmware->size); - - if (!within_range(fw, fw_end, 0, sizeof(*header))) { - dev_err(kbdev->dev, "WA too small\n"); - goto bad_fw; - } - - header = (const struct wa_header *)(fw + 0); - - if (header->signature != signature) { - dev_err(kbdev->dev, "WA signature failure: 0x%lx\n", - (unsigned long)header->signature); - goto bad_fw; - } - - if (header->version != version) { - dev_err(kbdev->dev, "WA version 0x%lx not supported\n", - (unsigned long)header->version); - goto bad_fw; - } - - if (!within_range(fw, fw_end, header->info_offset, sizeof(*v2_info))) { - dev_err(kbdev->dev, "WA info offset out of bounds\n"); - goto bad_fw; - } - - v2_info = (const struct wa_v2_info *)(fw + header->info_offset); - - if (v2_info->flags & ~KBASE_DUMMY_JOB_WA_FLAGS) { - dev_err(kbdev->dev, "Unsupported WA flag(s): 0x%llx\n", - (unsigned long long)v2_info->flags); - goto bad_fw; - } - - kbdev->dummy_job_wa.slot = v2_info->js; - kbdev->dummy_job_wa.jc = v2_info->jc; - kbdev->dummy_job_wa.flags = v2_info->flags; - - blob_offset = v2_info->blob_offset; - - while (blob_offset) { - const struct wa_blob *blob; - size_t nr_pages; - base_mem_alloc_flags flags; - u64 gpu_va; - struct kbase_va_region *va_region; - - if (!within_range(fw, fw_end, blob_offset, sizeof(*blob))) { - dev_err(kbdev->dev, "Blob offset out-of-range: 0x%lx\n", - (unsigned long)blob_offset); - goto bad_fw; - } - - blob = (const struct wa_blob *)(fw + blob_offset); - if (!within_range(fw, fw_end, blob->payload_offset, blob->size)) { - dev_err(kbdev->dev, "Payload out-of-bounds\n"); - goto bad_fw; - } - - gpu_va = blob->base; - if (PAGE_ALIGN(gpu_va) != gpu_va) { - dev_err(kbdev->dev, "blob not page aligned\n"); - goto bad_fw; - } - nr_pages = PFN_UP(blob->size); - flags = blob->map_flags | BASEP_MEM_FLAG_MAP_FIXED; - - va_region = kbase_mem_alloc(kctx, nr_pages, nr_pages, 0, &flags, &gpu_va, - mmu_sync_info); - - if (!va_region) { - dev_err(kbdev->dev, "Failed to allocate for blob\n"); - } else { - struct kbase_vmap_struct vmap = { 0 }; - const u8 *payload; - void *dst; - - /* copy the payload, */ - payload = fw + blob->payload_offset; - - dst = kbase_vmap(kctx, va_region->start_pfn << PAGE_SHIFT, - nr_pages << PAGE_SHIFT, &vmap); - - if (dst) { - memcpy(dst, payload, blob->size); - kbase_vunmap(kctx, &vmap); - } else { - dev_err(kbdev->dev, "Failed to copy payload\n"); - } - } - blob_offset = blob->blob_offset; /* follow chain */ - } - - release_firmware(firmware); - - kbasep_js_schedule_privileged_ctx(kbdev, kctx); - - kbdev->dummy_job_wa.kctx = kctx; - - err = sysfs_create_file(&kbdev->dev->kobj, &dev_attr_dummy_job_wa_info.attr); - if (err) - dev_err(kbdev->dev, "SysFS file creation for dummy job wa failed\n"); - - return 0; - -bad_fw: - kbase_destroy_context(kctx); -no_ctx: - release_firmware(firmware); - return -EFAULT; -} - -void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev) -{ - struct kbase_context *wa_kctx; - - /* return if the dummy job has not been loaded */ - if (kbdev->dummy_job_wa_loaded == false) - return; - - /* Can be safely called even if the file wasn't created on probe */ - sysfs_remove_file(&kbdev->dev->kobj, &dev_attr_dummy_job_wa_info.attr); - - wa_kctx = READ_ONCE(kbdev->dummy_job_wa.kctx); - WRITE_ONCE(kbdev->dummy_job_wa.kctx, NULL); - /* make this write visible before we tear down the ctx */ - smp_mb(); - - if (wa_kctx) { - kbasep_js_release_privileged_ctx(kbdev, wa_kctx); - kbase_destroy_context(wa_kctx); - } -} diff --git a/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.h b/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.h deleted file mode 100644 index b46197aa6df3..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_dummy_job_wa.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _KBASE_DUMMY_JOB_WORKAROUND_ -#define _KBASE_DUMMY_JOB_WORKAROUND_ - -#define KBASE_DUMMY_JOB_WA_FLAG_SERIALIZE (1ull << 0) -#define KBASE_DUMMY_JOB_WA_FLAG_WAIT_POWERUP (1ull << 1) -#define KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER (1ull << 2) - -#define KBASE_DUMMY_JOB_WA_FLAGS \ - (KBASE_DUMMY_JOB_WA_FLAG_SERIALIZE | KBASE_DUMMY_JOB_WA_FLAG_WAIT_POWERUP | \ - KBASE_DUMMY_JOB_WA_FLAG_LOGICAL_SHADER_POWER) - -#if MALI_USE_CSF - -static inline int kbase_dummy_job_wa_load(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - return 0; -} - -static inline void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); -} - -static inline int kbase_dummy_job_wa_execute(struct kbase_device *kbdev, u64 cores) -{ - CSTD_UNUSED(kbdev); - CSTD_UNUSED(cores); - return 0; -} - -static inline bool kbase_dummy_job_wa_enabled(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); - return false; -} - -#else - -int kbase_dummy_job_wa_load(struct kbase_device *kbdev); -void kbase_dummy_job_wa_cleanup(struct kbase_device *kbdev); -int kbase_dummy_job_wa_execute(struct kbase_device *kbdev, u64 cores); - -static inline bool kbase_dummy_job_wa_enabled(struct kbase_device *kbdev) -{ - return (kbdev->dummy_job_wa.kctx != NULL); -} - -#endif /* MALI_USE_CSF */ - -#endif /* _KBASE_DUMMY_JOB_WORKAROUND_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_dvfs_debugfs.c b/drivers/gpu/arm/valhall/mali_kbase_dvfs_debugfs.c index e912178b3324..f33a484a6796 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_dvfs_debugfs.c +++ b/drivers/gpu/arm/valhall/mali_kbase_dvfs_debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -38,16 +38,10 @@ static int kbasep_dvfs_utilization_debugfs_show(struct seq_file *file, void *dat struct kbase_device *kbdev = file->private; CSTD_UNUSED(data); -#if MALI_USE_CSF seq_printf(file, "busy_time: %u idle_time: %u protm_time: %u\n", kbdev->pm.backend.metrics.values.time_busy, kbdev->pm.backend.metrics.values.time_idle, kbdev->pm.backend.metrics.values.time_in_protm); -#else - seq_printf(file, "busy_time: %u idle_time: %u\n", - kbdev->pm.backend.metrics.values.time_busy, - kbdev->pm.backend.metrics.values.time_idle); -#endif return 0; } diff --git a/drivers/gpu/arm/valhall/mali_kbase_event.c b/drivers/gpu/arm/valhall/mali_kbase_event.c deleted file mode 100644 index 3c59b20913f2..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_event.c +++ /dev/null @@ -1,265 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include -#include - -static struct base_jd_udata kbase_event_process(struct kbase_context *kctx, - struct kbase_jd_atom *katom) -{ - struct base_jd_udata data; - struct kbase_device *kbdev; - - lockdep_assert_held(&kctx->jctx.lock); - - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(katom != NULL); - KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); - - kbdev = kctx->kbdev; - data = katom->udata; - - KBASE_TLSTREAM_TL_NRET_ATOM_CTX(kbdev, katom, kctx); - KBASE_TLSTREAM_TL_DEL_ATOM(kbdev, katom); - - katom->status = KBASE_JD_ATOM_STATE_UNUSED; - dev_dbg(kbdev->dev, "Atom %pK status to unused\n", (void *)katom); - wake_up(&katom->completed); - - return data; -} - -int kbase_event_dequeue(struct kbase_context *kctx, struct base_jd_event_v2 *uevent) -{ - struct kbase_jd_atom *atom; - - KBASE_DEBUG_ASSERT(kctx); - - mutex_lock(&kctx->event_mutex); - - if (list_empty(&kctx->event_list)) { - if (!atomic_read(&kctx->event_closed)) { - mutex_unlock(&kctx->event_mutex); - return -1; - } - - /* generate the BASE_JD_EVENT_DRV_TERMINATED message on the fly */ - mutex_unlock(&kctx->event_mutex); - uevent->event_code = BASE_JD_EVENT_DRV_TERMINATED; - memset(&uevent->udata, 0, sizeof(uevent->udata)); - dev_dbg(kctx->kbdev->dev, - "event system closed, returning BASE_JD_EVENT_DRV_TERMINATED(0x%X)\n", - BASE_JD_EVENT_DRV_TERMINATED); - return 0; - } - - /* normal event processing */ - atomic_dec(&kctx->event_count); - atom = list_entry(kctx->event_list.next, struct kbase_jd_atom, dep_item[0]); - list_del(kctx->event_list.next); - - mutex_unlock(&kctx->event_mutex); - - dev_dbg(kctx->kbdev->dev, "event dequeuing %pK\n", (void *)atom); - uevent->event_code = atom->event_code; - - uevent->atom_number = (atom - kctx->jctx.atoms); - - if (atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) - kbase_jd_free_external_resources(atom); - - mutex_lock(&kctx->jctx.lock); - uevent->udata = kbase_event_process(kctx, atom); - mutex_unlock(&kctx->jctx.lock); - - return 0; -} - -KBASE_EXPORT_TEST_API(kbase_event_dequeue); - -/** - * kbase_event_process_noreport_worker - Worker for processing atoms that do not - * return an event but do have external - * resources - * @data: Work structure - */ -static void kbase_event_process_noreport_worker(struct work_struct *data) -{ - struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); - struct kbase_context *kctx = katom->kctx; - - if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) - kbase_jd_free_external_resources(katom); - - mutex_lock(&kctx->jctx.lock); - kbase_event_process(kctx, katom); - mutex_unlock(&kctx->jctx.lock); -} - -/** - * kbase_event_process_noreport - Process atoms that do not return an event - * @kctx: Context pointer - * @katom: Atom to be processed - * - * Atoms that do not have external resources will be processed immediately. - * Atoms that do have external resources will be processed on a workqueue, in - * order to avoid locking issues. - */ -static void kbase_event_process_noreport(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { - INIT_WORK(&katom->work, kbase_event_process_noreport_worker); - queue_work(kctx->event_workq, &katom->work); - } else { - kbase_event_process(kctx, katom); - } -} - -/** - * kbase_event_coalesce - Move pending events to the main event list - * @kctx: Context pointer - * - * kctx->event_list and kctx->event_coalesce_count must be protected - * by a lock unless this is the last thread using them - * (and we're about to terminate the lock). - * - * Return: The number of pending events moved to the main event list - */ -static int kbase_event_coalesce(struct kbase_context *kctx) -{ - const int event_count = kctx->event_coalesce_count; - - /* Join the list of pending events onto the tail of the main list - * and reset it - */ - list_splice_tail_init(&kctx->event_coalesce_list, &kctx->event_list); - kctx->event_coalesce_count = 0; - - /* Return the number of events moved */ - return event_count; -} - -void kbase_event_post(struct kbase_context *kctx, struct kbase_jd_atom *atom) -{ - struct kbase_device *kbdev = kctx->kbdev; - - dev_dbg(kbdev->dev, "Posting event for atom %pK\n", (void *)atom); - - if (WARN_ON(atom->status != KBASE_JD_ATOM_STATE_COMPLETED)) { - dev_warn(kbdev->dev, "%s: Atom %d (%pK) not completed (status %d)\n", __func__, - kbase_jd_atom_id(atom->kctx, atom), atom->kctx, atom->status); - return; - } - - if (atom->core_req & BASE_JD_REQ_EVENT_ONLY_ON_FAILURE) { - if (atom->event_code == BASE_JD_EVENT_DONE) { - dev_dbg(kbdev->dev, "Suppressing event (atom done)\n"); - kbase_event_process_noreport(kctx, atom); - return; - } - } - - if (atom->core_req & BASEP_JD_REQ_EVENT_NEVER) { - dev_dbg(kbdev->dev, "Suppressing event (never)\n"); - kbase_event_process_noreport(kctx, atom); - return; - } - KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, atom, TL_ATOM_STATE_POSTED); - if (atom->core_req & BASE_JD_REQ_EVENT_COALESCE) { - /* Don't report the event until other event(s) have completed */ - dev_dbg(kbdev->dev, "Deferring event (coalesced)\n"); - mutex_lock(&kctx->event_mutex); - list_add_tail(&atom->dep_item[0], &kctx->event_coalesce_list); - ++kctx->event_coalesce_count; - mutex_unlock(&kctx->event_mutex); - } else { - /* Report the event and any pending events now */ - int event_count = 1; - - mutex_lock(&kctx->event_mutex); - event_count += kbase_event_coalesce(kctx); - list_add_tail(&atom->dep_item[0], &kctx->event_list); - atomic_add(event_count, &kctx->event_count); - mutex_unlock(&kctx->event_mutex); - dev_dbg(kbdev->dev, "Reporting %d events\n", event_count); - - kbase_event_wakeup(kctx); - - /* Post-completion latency */ - trace_sysgraph(SGR_POST, kctx->id, kbase_jd_atom_id(kctx, atom)); - } -} -KBASE_EXPORT_TEST_API(kbase_event_post); - -void kbase_event_close(struct kbase_context *kctx) -{ - mutex_lock(&kctx->event_mutex); - atomic_set(&kctx->event_closed, true); - mutex_unlock(&kctx->event_mutex); - kbase_event_wakeup(kctx); -} - -int kbase_event_init(struct kbase_context *kctx) -{ - KBASE_DEBUG_ASSERT(kctx); - - INIT_LIST_HEAD(&kctx->event_list); - INIT_LIST_HEAD(&kctx->event_coalesce_list); - mutex_init(&kctx->event_mutex); - kctx->event_workq = alloc_workqueue("kbase_event", WQ_MEM_RECLAIM, 1); - - if (kctx->event_workq == NULL) - return -EINVAL; - - return 0; -} - -KBASE_EXPORT_TEST_API(kbase_event_init); - -void kbase_event_cleanup(struct kbase_context *kctx) -{ - int event_count; - - KBASE_DEBUG_ASSERT(kctx); - KBASE_DEBUG_ASSERT(kctx->event_workq); - - flush_workqueue(kctx->event_workq); - destroy_workqueue(kctx->event_workq); - - /* We use kbase_event_dequeue to remove the remaining events as that - * deals with all the cleanup needed for the atoms. - * - * Note: use of kctx->event_list without a lock is safe because this must be the last - * thread using it (because we're about to terminate the lock) - */ - event_count = kbase_event_coalesce(kctx); - atomic_add(event_count, &kctx->event_count); - - while (!list_empty(&kctx->event_list)) { - struct base_jd_event_v2 event; - - kbase_event_dequeue(kctx, &event); - } -} - -KBASE_EXPORT_TEST_API(kbase_event_cleanup); diff --git a/drivers/gpu/arm/valhall/mali_kbase_fence.c b/drivers/gpu/arm/valhall/mali_kbase_fence.c deleted file mode 100644 index 8b0505a800a4..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_fence.c +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include -#include -#include - -#include - -/* Spin lock protecting all Mali fences as fence->lock. */ -static DEFINE_SPINLOCK(kbase_fence_lock); - -struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom) -{ - struct dma_fence *fence; - - WARN_ON(katom->dma_fence.fence); - - fence = kzalloc(sizeof(*fence), GFP_KERNEL); - if (!fence) - return NULL; - - dma_fence_init(fence, &kbase_fence_ops, &kbase_fence_lock, katom->dma_fence.context, - (u64)atomic_inc_return(&katom->dma_fence.seqno)); - - katom->dma_fence.fence = fence; - - return fence; -} diff --git a/drivers/gpu/arm/valhall/mali_kbase_fence.h b/drivers/gpu/arm/valhall/mali_kbase_fence.h index 9fe6c67b464c..f15f4048e922 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_fence.h +++ b/drivers/gpu/arm/valhall/mali_kbase_fence.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2010-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -34,7 +34,6 @@ #include #include -#if MALI_USE_CSF /* Number of digits needed to express the max value of given unsigned type. * * Details: The number of digits needed to express the max value of given type is log10(t_max) + 1 @@ -91,12 +90,13 @@ struct kbase_kcpu_dma_fence_meta { * * @base: Fence object itself. * @metadata: Pointer to metadata structure. + * @module: Pointer to the mali_kbase kernel module. */ struct kbase_kcpu_dma_fence { struct dma_fence base; struct kbase_kcpu_dma_fence_meta *metadata; + struct module *module; }; -#endif extern const struct dma_fence_ops kbase_fence_ops; @@ -123,86 +123,6 @@ struct dma_fence *kbase_fence_out_new(struct kbase_jd_atom *katom); } while (0) #endif -#if !MALI_USE_CSF -/** - * kbase_fence_out_remove() - Removes the output fence from atom - * @katom: Atom to remove output fence for - * - * This will also release the reference to this fence which the atom keeps - */ -static inline void kbase_fence_out_remove(struct kbase_jd_atom *katom) -{ - if (katom->dma_fence.fence) { - dma_fence_put(katom->dma_fence.fence); - katom->dma_fence.fence = NULL; - } -} - -#if IS_ENABLED(CONFIG_SYNC_FILE) -/** - * kbase_fence_in_remove() - Removes the input fence from atom - * @katom: Atom to remove input fence for - * - * This will also release the reference to this fence which the atom keeps - */ -static inline void kbase_fence_in_remove(struct kbase_jd_atom *katom) -{ - if (katom->dma_fence.fence_in) { - dma_fence_put(katom->dma_fence.fence_in); - katom->dma_fence.fence_in = NULL; - } -} -#endif - -/** - * kbase_fence_out_is_ours() - Check if atom has a valid fence created by us - * @katom: Atom to check output fence for - * - * Return: true if fence exists and is valid, otherwise false - */ -static inline bool kbase_fence_out_is_ours(struct kbase_jd_atom *katom) -{ - return katom->dma_fence.fence && katom->dma_fence.fence->ops == &kbase_fence_ops; -} - -/** - * kbase_fence_out_signal() - Signal output fence of atom - * @katom: Atom to signal output fence for - * @status: Status to signal with (0 for success, < 0 for error) - * - * Return: 0 on success, < 0 on error - */ -static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom, int status) -{ - if (status) - dma_fence_set_error_helper(katom->dma_fence.fence, status); - return dma_fence_signal(katom->dma_fence.fence); -} - -#if IS_ENABLED(CONFIG_SYNC_FILE) -/** - * kbase_fence_in_get() - Retrieve input fence for atom. - * @katom: Atom to get input fence from - * - * A ref will be taken for the fence, so use @kbase_fence_put() to release it - * - * Return: The fence, or NULL if there is no input fence for atom - */ -#define kbase_fence_in_get(katom) dma_fence_get((katom)->dma_fence.fence_in) -#endif - -/** - * kbase_fence_out_get() - Retrieve output fence for atom. - * @katom: Atom to get output fence from - * - * A ref will be taken for the fence, so use @kbase_fence_put() to release it - * - * Return: The fence, or NULL if there is no output fence for atom - */ -#define kbase_fence_out_get(katom) dma_fence_get((katom)->dma_fence.fence) - -#endif /* !MALI_USE_CSF */ - /** * kbase_fence_get() - Retrieve fence for a KCPUQ fence command. * @fence_info: KCPUQ fence command @@ -213,7 +133,6 @@ static inline int kbase_fence_out_signal(struct kbase_jd_atom *katom, int status */ #define kbase_fence_get(fence_info) dma_fence_get((fence_info)->fence) -#if MALI_USE_CSF static inline struct kbase_kcpu_dma_fence *kbase_kcpu_dma_fence_get(struct dma_fence *fence) { if (fence->ops == &kbase_fence_ops) @@ -237,7 +156,6 @@ static inline void kbase_kcpu_dma_fence_put(struct dma_fence *fence) if (kcpu_fence) kbase_kcpu_dma_fence_meta_put(kcpu_fence->metadata); } -#endif /* MALI_USE_CSF */ /** * kbase_fence_put() - Releases a reference to a fence diff --git a/drivers/gpu/arm/valhall/mali_kbase_fence_ops.c b/drivers/gpu/arm/valhall/mali_kbase_fence_ops.c index b10e69cea565..faaf4f1a82dc 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_fence_ops.c +++ b/drivers/gpu/arm/valhall/mali_kbase_fence_ops.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2020-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -31,21 +31,12 @@ static const char *kbase_fence_get_driver_name(struct dma_fence *fence) return KBASE_DRV_NAME; } -#if MALI_USE_CSF static const char *kbase_fence_get_timeline_name(struct dma_fence *fence) { struct kbase_kcpu_dma_fence *kcpu_fence = (struct kbase_kcpu_dma_fence *)fence; return kcpu_fence->metadata->timeline_name; } -#else -static const char *kbase_fence_get_timeline_name(struct dma_fence *fence) -{ - CSTD_UNUSED(fence); - - return KBASE_TIMELINE_NAME; -} -#endif /* MALI_USE_CSF */ static bool kbase_fence_enable_signaling(struct dma_fence *fence) { @@ -67,12 +58,13 @@ static void kbase_fence_fence_value_str(struct dma_fence *fence, char *str, int pr_err("Fail to encode fence seqno to string"); } -#if MALI_USE_CSF static void kbase_fence_release(struct dma_fence *fence) { struct kbase_kcpu_dma_fence *kcpu_fence = (struct kbase_kcpu_dma_fence *)fence; kbase_kcpu_dma_fence_meta_put(kcpu_fence->metadata); + if (likely(kcpu_fence->module)) + module_put(kcpu_fence->module); kfree(kcpu_fence); } @@ -83,13 +75,5 @@ const struct dma_fence_ops kbase_fence_ops = { .wait = dma_fence_default_wait, .enable_signaling = kbase_fence_enable_signaling, .fence_value_str = kbase_fence_fence_value_str, .release = kbase_fence_release }; -#else -extern const struct dma_fence_ops kbase_fence_ops; /* silence checker warning */ -const struct dma_fence_ops kbase_fence_ops = { .wait = dma_fence_default_wait, - .get_driver_name = kbase_fence_get_driver_name, - .get_timeline_name = kbase_fence_get_timeline_name, - .enable_signaling = kbase_fence_enable_signaling, - .fence_value_str = kbase_fence_fence_value_str }; -#endif /* MALI_USE_CSF */ KBASE_EXPORT_TEST_API(kbase_fence_ops); diff --git a/drivers/gpu/arm/valhall/mali_kbase_gpuprops.c b/drivers/gpu/arm/valhall/mali_kbase_gpuprops.c index 55a7a796c58a..fd73c86e35a6 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_gpuprops.c +++ b/drivers/gpu/arm/valhall/mali_kbase_gpuprops.c @@ -239,11 +239,7 @@ static int kbase_gpuprops_get_props(struct kbase_device *kbdev) else gpu_props->max_threads = regdump->thread_max_threads; -#if MALI_USE_CSF gpu_props->impl_tech = KBASE_UBFX32(regdump->thread_features, 22U, 2); -#else /* MALI_USE_CSF */ - gpu_props->impl_tech = KBASE_UBFX32(regdump->thread_features, 30U, 2); -#endif /* MALI_USE_CSF */ if (IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI)) gpu_props->impl_tech = THREAD_FEATURES_IMPLEMENTATION_TECHNOLOGY_NO_MALI; @@ -678,9 +674,6 @@ static void kbase_populate_user_data(struct kbase_device *kbdev, struct gpu_prop * GPUs like tTIx have additional fields like LSC_SIZE that are * otherwise reserved/RAZ on older GPUs. */ -#if !MALI_USE_CSF - data->core_props.num_exec_engines = KBASE_UBFX64(regdump->core_features, 0, 4); -#endif data->l2_props.log2_cache_size = KBASE_UBFX64(regdump->l2_features, 16U, 8); data->coherency_info.coherency = regdump->mem_features; @@ -707,15 +700,9 @@ static void kbase_populate_user_data(struct kbase_device *kbdev, struct gpu_prop else data->thread_props.tls_alloc = regdump->thread_tls_alloc; -#if MALI_USE_CSF data->thread_props.max_registers = KBASE_UBFX32(regdump->thread_features, 0U, 22); data->thread_props.max_task_queue = KBASE_UBFX32(regdump->thread_features, 24U, 8); data->thread_props.max_thread_group_split = 0; -#else - data->thread_props.max_registers = KBASE_UBFX32(regdump->thread_features, 0U, 16); - data->thread_props.max_task_queue = KBASE_UBFX32(regdump->thread_features, 16U, 8); - data->thread_props.max_thread_group_split = KBASE_UBFX32(regdump->thread_features, 24U, 6); -#endif if (data->thread_props.max_registers == 0) { data->thread_props.max_registers = THREAD_MR_DEFAULT; diff --git a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_defs.h b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_defs.h index 96aeb6188a05..fba612771e33 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_defs.h +++ b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_defs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -40,10 +40,6 @@ * @backend: GPU backend specific data for HW access layer */ struct kbase_hwaccess_data { -#if !MALI_USE_CSF - struct kbase_context *active_kctx[BASE_JM_MAX_NR_SLOTS]; -#endif - struct kbase_backend_data backend; }; diff --git a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_jm.h b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_jm.h deleted file mode 100644 index ed91019ff74c..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_jm.h +++ /dev/null @@ -1,308 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * HW access job manager common APIs - */ - -#ifndef _KBASE_HWACCESS_JM_H_ -#define _KBASE_HWACCESS_JM_H_ - -/** - * kbase_backend_run_atom() - Run an atom on the GPU - * @kbdev: Device pointer - * @katom: Atom to run - * - * Caller must hold the HW access lock - */ -void kbase_backend_run_atom(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -/** - * kbase_backend_slot_update - Update state based on slot ringbuffers - * - * @kbdev: Device pointer - * - * Inspect the jobs in the slot ringbuffers and update state. - * - * This will cause jobs to be submitted to hardware if they are unblocked - */ -void kbase_backend_slot_update(struct kbase_device *kbdev); - -/** - * kbase_backend_find_and_release_free_address_space() - Release a free AS - * @kbdev: Device pointer - * @kctx: Context pointer - * - * This function can evict an idle context from the runpool, freeing up the - * address space it was using. - * - * The address space is marked as in use. The caller must either assign a - * context using kbase_gpu_use_ctx(), or release it using - * kbase_ctx_sched_release() - * - * Return: Number of free address space, or KBASEP_AS_NR_INVALID if none - * available - */ -int kbase_backend_find_and_release_free_address_space(struct kbase_device *kbdev, - struct kbase_context *kctx); - -/** - * kbase_backend_use_ctx() - Activate a currently unscheduled context, using the - * provided address space. - * @kbdev: Device pointer - * @kctx: Context pointer. May be NULL - * @as_nr: Free address space to use - * - * kbase_gpu_next_job() will pull atoms from the active context. - * - * Return: true if successful, false if ASID not assigned. - */ -bool kbase_backend_use_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, int as_nr); - -/** - * kbase_backend_use_ctx_sched() - Activate a context. - * @kbdev: Device pointer - * @kctx: Context pointer - * @js: Job slot to activate context on - * - * kbase_gpu_next_job() will pull atoms from the active context. - * - * The context must already be scheduled and assigned to an address space. If - * the context is not scheduled, then kbase_gpu_use_ctx() should be used - * instead. - * - * Caller must hold hwaccess_lock - * - * Return: true if context is now active, false otherwise (ie if context does - * not have an address space assigned) - */ -bool kbase_backend_use_ctx_sched(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js); - -/** - * kbase_backend_release_ctx_irq - Release a context from the GPU. This will - * de-assign the assigned address space. - * @kbdev: Device pointer - * @kctx: Context pointer - * - * Caller must hold kbase_device->mmu_hw_mutex and hwaccess_lock - */ -void kbase_backend_release_ctx_irq(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbase_backend_release_ctx_noirq - Release a context from the GPU. This will - * de-assign the assigned address space. - * @kbdev: Device pointer - * @kctx: Context pointer - * - * Caller must hold kbase_device->mmu_hw_mutex - * - * This function must perform any operations that could not be performed in IRQ - * context by kbase_backend_release_ctx_irq(). - */ -void kbase_backend_release_ctx_noirq(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbase_backend_cache_clean - Perform a cache clean if the given atom requires - * one - * @kbdev: Device pointer - * @katom: Pointer to the failed atom - * - * On some GPUs, the GPU cache must be cleaned following a failed atom. This - * function performs a clean if it is required by @katom. - */ -void kbase_backend_cache_clean(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -/** - * kbase_backend_complete_wq() - Perform backend-specific actions required on - * completing an atom. - * @kbdev: Device pointer - * @katom: Pointer to the atom to complete - * - * This function should only be called from kbase_jd_done_worker() or - * js_return_worker(). - * - * Return: true if atom has completed, false if atom should be re-submitted - */ -void kbase_backend_complete_wq(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -#if !MALI_USE_CSF -/** - * kbase_backend_complete_wq_post_sched - Perform backend-specific actions - * required on completing an atom, after - * any scheduling has taken place. - * @kbdev: Device pointer - * @core_req: Core requirements of atom - * - * This function should only be called from kbase_jd_done_worker() or - * js_return_worker(). - */ -void kbase_backend_complete_wq_post_sched(struct kbase_device *kbdev, base_jd_core_req core_req); -#endif /* !MALI_USE_CSF */ - -/** - * kbase_backend_reset() - The GPU is being reset. Cancel all jobs on the GPU - * and remove any others from the ringbuffers. - * @kbdev: Device pointer - * @end_timestamp: Timestamp of reset - */ -void kbase_backend_reset(struct kbase_device *kbdev, ktime_t *end_timestamp); - -/** - * kbase_backend_inspect_tail - Return the atom currently at the tail of slot - * @js - * @kbdev: Device pointer - * @js: Job slot to inspect - * - * Return: Atom currently at the head of slot @js, or NULL - */ -struct kbase_jd_atom *kbase_backend_inspect_tail(struct kbase_device *kbdev, unsigned int js); - -/** - * kbase_backend_nr_atoms_on_slot() - Return the number of atoms currently on a - * slot. - * @kbdev: Device pointer - * @js: Job slot to inspect - * - * Return: Number of atoms currently on slot - */ -int kbase_backend_nr_atoms_on_slot(struct kbase_device *kbdev, unsigned int js); - -/** - * kbase_backend_nr_atoms_submitted() - Return the number of atoms on a slot - * that are currently on the GPU. - * @kbdev: Device pointer - * @js: Job slot to inspect - * - * Return: Number of atoms currently on slot @js that are currently on the GPU. - */ -u32 kbase_backend_nr_atoms_submitted(struct kbase_device *kbdev, unsigned int js); - -/** - * kbase_backend_ctx_count_changed() - Number of contexts ready to submit jobs - * has changed. - * @kbdev: Device pointer - * - * Perform any required backend-specific actions (eg starting/stopping - * scheduling timers). - */ -void kbase_backend_ctx_count_changed(struct kbase_device *kbdev); - -/** - * kbase_backend_timeouts_changed() - Job Scheduler timeouts have changed. - * @kbdev: Device pointer - * - * Perform any required backend-specific actions (eg updating timeouts of - * currently running atoms). - */ -void kbase_backend_timeouts_changed(struct kbase_device *kbdev); - -/** - * kbase_backend_slot_free() - Return the number of jobs that can be currently - * submitted to slot @js. - * @kbdev: Device pointer - * @js: Job slot to inspect - * - * Return: Number of jobs that can be submitted. - */ -int kbase_backend_slot_free(struct kbase_device *kbdev, unsigned int js); - -/** - * kbase_job_check_leave_disjoint - potentially leave disjoint state - * @kbdev: kbase device - * @target_katom: atom which is finishing - * - * Work out whether to leave disjoint state when finishing an atom that was - * originated by kbase_job_check_enter_disjoint(). - */ -void kbase_job_check_leave_disjoint(struct kbase_device *kbdev, struct kbase_jd_atom *target_katom); - -/** - * kbase_backend_jm_kill_running_jobs_from_kctx - Kill all jobs that are - * currently running on GPU from a context - * @kctx: Context pointer - * - * This is used in response to a page fault to remove all jobs from the faulting - * context from the hardware. - * - * Caller must hold hwaccess_lock. - */ -void kbase_backend_jm_kill_running_jobs_from_kctx(struct kbase_context *kctx); - -/** - * kbase_jm_wait_for_zero_jobs - Wait for context to have zero jobs running, and - * to be descheduled. - * @kctx: Context pointer - * - * This should be called following kbase_js_zap_context(), to ensure the context - * can be safely destroyed. - */ -void kbase_jm_wait_for_zero_jobs(struct kbase_context *kctx); - -/** - * kbase_backend_get_current_flush_id - Return the current flush ID - * - * @kbdev: Device pointer - * - * Return: the current flush ID to be recorded for each job chain - */ -u32 kbase_backend_get_current_flush_id(struct kbase_device *kbdev); - -/** - * kbase_job_slot_hardstop - Hard-stop the specified job slot - * @kctx: The kbase context that contains the job(s) that should - * be hard-stopped - * @js: The job slot to hard-stop - * @target_katom: The job that should be hard-stopped (or NULL for all - * jobs from the context) - * Context: - * The job slot lock must be held when calling this function. - */ -void kbase_job_slot_hardstop(struct kbase_context *kctx, unsigned int js, - struct kbase_jd_atom *target_katom); - -/** - * kbase_gpu_atoms_submitted_any() - Inspect whether there are any atoms - * currently on the GPU - * @kbdev: Device pointer - * - * Return: true if there are any atoms on the GPU, false otherwise - */ -bool kbase_gpu_atoms_submitted_any(struct kbase_device *kbdev); - -/** - * kbase_backend_slot_kctx_purge_locked - Perform a purge on the slot_rb tracked - * kctx - * - * @kbdev: Device pointer - * @kctx: The kbase context that needs to be purged from slot_rb[] - * - * For JM GPUs, the L1 read only caches may need a start_flush invalidation, - * potentially on all slots (even if the kctx was only using a single slot), - * following a context termination or address-space ID recycle. This function - * performs a clean-up purge on the given kctx which if it has been tracked by - * slot_rb[] objects. - * - * Caller must hold kbase_device->hwaccess_lock. - */ -void kbase_backend_slot_kctx_purge_locked(struct kbase_device *kbdev, struct kbase_context *kctx); - -#endif /* _KBASE_HWACCESS_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_pm.h b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_pm.h index 982547d16022..a396f02b59ed 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_pm.h +++ b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_pm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -114,7 +114,6 @@ void kbase_hwaccess_pm_gpu_active(struct kbase_device *kbdev); */ void kbase_hwaccess_pm_gpu_idle(struct kbase_device *kbdev); -#if MALI_USE_CSF /** * kbase_pm_set_debug_core_mask - Set the debug core mask. * @@ -124,20 +123,6 @@ void kbase_hwaccess_pm_gpu_idle(struct kbase_device *kbdev); * This determines which cores the power manager is allowed to use. */ void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, u64 new_core_mask); -#else -/** - * kbase_pm_set_debug_core_mask - Set the debug core mask. - * - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * @new_core_mask: The core mask to use, as an array where each element refers - * to a job slot. - * @new_core_mask_size: Number of elements in the core mask array. - * - * This determines which cores the power manager is allowed to use. - */ -void kbase_pm_set_debug_core_mask(struct kbase_device *kbdev, u64 *new_core_mask, - size_t new_core_mask_size); -#endif /* MALI_USE_CSF */ /** * kbase_pm_ca_get_policy - Get the current policy. diff --git a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_time.h b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_time.h index 222ff2001e56..2df4cad514f8 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_hwaccess_time.h +++ b/drivers/gpu/arm/valhall/mali_kbase_hwaccess_time.h @@ -53,15 +53,12 @@ * */ struct kbase_backend_time { -#if MALI_USE_CSF u64 multiplier; u64 divisor; s64 gpu_timestamp_offset; -#endif unsigned int device_scaled_timeouts[KBASE_TIMEOUT_SELECTOR_COUNT]; }; -#if MALI_USE_CSF /** * kbase_backend_time_convert_gpu_to_cpu() - Convert GPU timestamp to CPU timestamp. * @@ -105,7 +102,6 @@ void kbase_backend_invalidate_gpu_timestamp_offset(struct kbase_device *kbdev); */ u64 kbase_backend_read_gpu_timestamp_offset_reg(struct kbase_device *kbdev); #endif -#endif /** * kbase_backend_get_gpu_time() - Get current GPU time @@ -205,4 +201,11 @@ u64 kbase_arch_timer_get_cntfrq(struct kbase_device *kbdev); */ int kbase_backend_time_init(struct kbase_device *kbdev); +/** + * kbase_gpu_timestamp_offset_debugfs_init - Define debugfs entry to read the GPU timestamp offset. + * + * @kbdev: kbase device pointer + * + */ +void kbase_gpu_timestamp_offset_debugfs_init(struct kbase_device *kbdev); #endif /* _KBASE_BACKEND_TIME_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_io.c b/drivers/gpu/arm/valhall/mali_kbase_io.c index 33acab795f75..49e1ea5175d6 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_io.c +++ b/drivers/gpu/arm/valhall/mali_kbase_io.c @@ -36,25 +36,6 @@ struct kbase_io { struct kbase_device *kbdev; }; -/** - * kbase_io_is_gpu_removed() - Has the GPU been removed. - * @kbdev: Kbase device pointer - * - * When Kbase takes too long to give up the GPU, the Arbiter - * can remove it. This will then be followed by a GPU lost event. - * This function will return true if the GPU has been removed. - * When this happens register reads will be zero. A zero GPU_ID is - * invalid so this is used to detect when GPU is removed. - * - * Return: True if GPU removed - */ -static bool kbase_io_is_gpu_removed(struct kbase_device *kbdev) -{ - if (!kbase_has_arbiter(kbdev)) - return false; - return (KBASE_REG_READ(kbdev, GPU_CONTROL_ENUM(GPU_ID)) == 0); -} - void kbase_io_set_status(struct kbase_io *io, enum kbase_io_status_bits status_bit) { set_bit(status_bit, io->status); @@ -81,21 +62,13 @@ KBASE_EXPORT_TEST_API(kbase_io_is_gpu_powered); bool kbase_io_is_aw_removed(struct kbase_device *kbdev) { - return (kbdev->arb.arb_if && test_bit(KBASE_IO_STATUS_AW_REMOVED, kbdev->io->status)); + return test_bit(KBASE_IO_STATUS_AW_REMOVED, kbdev->io->status); } KBASE_EXPORT_TEST_API(kbase_io_is_aw_removed); bool kbase_io_has_gpu(struct kbase_device *kbdev) { - if (kbase_io_test_status(kbdev, KBASE_IO_STATUS_AW_REMOVED)) - return false; - - if (kbase_io_is_gpu_removed(kbdev)) { - kbase_io_set_status(kbdev->io, KBASE_IO_STATUS_AW_REMOVED); - return false; - } - - return true; + return kbase_io_is_gpu_powered(kbdev) && !kbase_io_is_aw_removed(kbdev); } KBASE_EXPORT_TEST_API(kbase_io_has_gpu); diff --git a/drivers/gpu/arm/valhall/mali_kbase_io.h b/drivers/gpu/arm/valhall/mali_kbase_io.h index 3a352fcb92b4..0f1cf8a6264b 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_io.h +++ b/drivers/gpu/arm/valhall/mali_kbase_io.h @@ -32,14 +32,12 @@ struct kbase_io; /** * enum kbase_io_status_bits - Status bits for kbase I/O interface. * - * @KBASE_IO_STATUS_GPU_SUSPENDED: The GPU is suspended. * @KBASE_IO_STATUS_GPU_OFF: The GPU is OFF. * @KBASE_IO_STATUS_AW_REMOVED: The GPU access window has been removed. * @KBASE_IO_STATUS_NUM_BITS: Number of bits used to encode the status. */ enum kbase_io_status_bits { - KBASE_IO_STATUS_GPU_SUSPENDED = 0, - KBASE_IO_STATUS_GPU_OFF, + KBASE_IO_STATUS_GPU_OFF = 0, KBASE_IO_STATUS_AW_REMOVED, KBASE_IO_STATUS_NUM_BITS, }; diff --git a/drivers/gpu/arm/valhall/mali_kbase_ioctl_helpers.h b/drivers/gpu/arm/valhall/mali_kbase_ioctl_helpers.h index d8d144c46f16..cfecc2de6b92 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_ioctl_helpers.h +++ b/drivers/gpu/arm/valhall/mali_kbase_ioctl_helpers.h @@ -286,8 +286,6 @@ check_padding_KBASE_IOCTL_KINSTR_PRFCNT_SETUP(union kbase_ioctl_kinstr_prfcnt_se #if MALI_UNIT_TEST #endif /* MALI_UNIT_TEST */ -#if MALI_USE_CSF - static inline int check_padding_KBASE_IOCTL_CS_QUEUE_REGISTER(struct kbase_ioctl_cs_queue_register *p) { @@ -518,31 +516,4 @@ check_padding_KBASE_IOCTL_CS_TILER_HEAP_SIZE(union kbase_ioctl_cs_tiler_heap_siz return 0; } -#else /* MALI_USE_CSF */ - -static inline int check_padding_KBASE_IOCTL_JOB_SUBMIT(struct kbase_ioctl_job_submit *p) -{ - return 0; -} - -static inline int -check_padding_KBASE_IOCTL_SOFT_EVENT_UPDATE(struct kbase_ioctl_soft_event_update *p) -{ - return 0; -} - -static inline int check_padding_KBASE_IOCTL_KINSTR_JM_FD(union kbase_kinstr_jm_fd *p) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) { - if (p->in.padding[i]) - return -1; - } - - return 0; -} - -#endif /* !MALI_USE_CSF */ - #endif /* _KBASE_IOCTL_HELPERS_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_jd.c b/drivers/gpu/arm/valhall/mali_kbase_jd.c deleted file mode 100644 index e56bc60ed8c3..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_jd.c +++ /dev/null @@ -1,1492 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#if IS_ENABLED(CONFIG_COMPAT) -#include -#endif -#include -#include -#include -#include -#include -#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include - -/* Return whether katom will run on the GPU or not. Currently only soft jobs and - * dependency-only atoms do not run on the GPU - */ -#define IS_GPU_ATOM(katom) \ - (!((katom->core_req & BASE_JD_REQ_SOFT_JOB) || \ - ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP))) - -/* - * This is the kernel side of the API. Only entry points are: - * - kbase_jd_submit(): Called from userspace to submit a single bag - * - kbase_jd_done(): Called from interrupt context to track the - * completion of a job. - * Callouts: - * - to the job manager (enqueue a job) - * - to the event subsystem (signals the completion/failure of bag/job-chains). - */ - -static void __user *get_compat_pointer(struct kbase_context *kctx, const u64 p) -{ -#if IS_ENABLED(CONFIG_COMPAT) - if (kbase_ctx_flag(kctx, KCTX_COMPAT)) - return compat_ptr(p); -#endif - return u64_to_user_ptr(p); -} - -/* Mark an atom as complete, and trace it in kinstr_jm */ -static void jd_mark_atom_complete(struct kbase_jd_atom *katom) -{ - katom->status = KBASE_JD_ATOM_STATE_COMPLETED; - kbase_kinstr_jm_atom_complete(katom); - dev_dbg(katom->kctx->kbdev->dev, "Atom %pK status to completed\n", (void *)katom); - KBASE_TLSTREAM_TL_JD_ATOM_COMPLETE(katom->kctx->kbdev, katom); -} - -/* Runs an atom, either by handing to the JS or by immediately running it in the case of soft-jobs - * - * Returns whether the JS needs a reschedule. - * - * Note that the caller must also check the atom status and - * if it is KBASE_JD_ATOM_STATE_COMPLETED must call kbase_jd_done_nolock - */ -static bool jd_run_atom(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - - dev_dbg(kctx->kbdev->dev, "JD run atom %pK in kctx %pK\n", (void *)katom, (void *)kctx); - - KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); - - if ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) { - /* Dependency only atom */ - trace_sysgraph(SGR_SUBMIT, kctx->id, kbase_jd_atom_id(katom->kctx, katom)); - jd_mark_atom_complete(katom); - return false; - } else if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { - /* Soft-job */ - if (katom->will_fail_event_code) { - kbase_finish_soft_job(katom); - jd_mark_atom_complete(katom); - return false; - } - if (kbase_process_soft_job(katom) == 0) { - kbase_finish_soft_job(katom); - jd_mark_atom_complete(katom); - } - return false; - } - - katom->status = KBASE_JD_ATOM_STATE_IN_JS; - dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n", (void *)katom); - /* Queue an action about whether we should try scheduling a context */ - return kbasep_js_add_job(kctx, katom); -} - -void kbase_jd_dep_clear_locked(struct kbase_jd_atom *katom) -{ - struct kbase_device *kbdev; - - KBASE_DEBUG_ASSERT(katom); - kbdev = katom->kctx->kbdev; - KBASE_DEBUG_ASSERT(kbdev); - - /* Check whether the atom's other dependencies were already met. If - * katom is a GPU atom then the job scheduler may be able to represent - * the dependencies, hence we may attempt to submit it before they are - * met. Other atoms must have had both dependencies resolved. - */ - if (IS_GPU_ATOM(katom) || (!kbase_jd_katom_dep_atom(&katom->dep[0]) && - !kbase_jd_katom_dep_atom(&katom->dep[1]))) { - /* katom dep complete, attempt to run it */ - bool resched = false; - - KBASE_TLSTREAM_TL_RUN_ATOM_START(katom->kctx->kbdev, katom, - kbase_jd_atom_id(katom->kctx, katom)); - resched = jd_run_atom(katom); - KBASE_TLSTREAM_TL_RUN_ATOM_END(katom->kctx->kbdev, katom, - kbase_jd_atom_id(katom->kctx, katom)); - - if (katom->status == KBASE_JD_ATOM_STATE_COMPLETED) { - /* The atom has already finished */ - resched |= kbase_jd_done_nolock(katom, true); - } - - if (resched) - kbase_js_sched_all(kbdev); - } -} - -void kbase_jd_free_external_resources(struct kbase_jd_atom *katom) -{ - CSTD_UNUSED(katom); -} - -static void kbase_jd_post_external_resources(struct kbase_jd_atom *katom) -{ - KBASE_DEBUG_ASSERT(katom); - KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); - - kbase_gpu_vm_lock(katom->kctx); - /* only roll back if extres is non-NULL */ - if (katom->extres) { - u32 res_no; - - res_no = katom->nr_extres; - while (res_no-- > 0) { - kbase_unmap_external_resource(katom->kctx, katom->extres[res_no]); - } - kfree(katom->extres); - katom->extres = NULL; - } - kbase_gpu_vm_unlock(katom->kctx); -} - -/* - * Set up external resources needed by this job. - * - * jctx.lock must be held when this is called. - */ - -static int kbase_jd_pre_external_resources(struct kbase_jd_atom *katom, - const struct base_jd_atom *user_atom) -{ - int err = -EINVAL; - u32 res_no; - struct base_external_resource *input_extres; - size_t copy_size; - - KBASE_DEBUG_ASSERT(katom); - KBASE_DEBUG_ASSERT(katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES); - - /* no resources encoded, early out */ - if (!katom->nr_extres) - return -EINVAL; - - katom->extres = kmalloc_array(katom->nr_extres, sizeof(*katom->extres), GFP_KERNEL); - if (!katom->extres) - return -ENOMEM; - - input_extres = kmalloc_array(katom->nr_extres, sizeof(*input_extres), GFP_KERNEL); - if (!input_extres) { - err = -ENOMEM; - goto failed_input_alloc; - } - - if (check_mul_overflow(sizeof(*input_extres), (size_t)katom->nr_extres, ©_size)) { - err = -EINVAL; - goto failed_input_copy; - } - - if (copy_from_user(input_extres, get_compat_pointer(katom->kctx, user_atom->extres_list), - copy_size) != 0) { - err = -EINVAL; - goto failed_input_copy; - } - - /* Take the processes mmap lock */ - down_read(kbase_mem_get_process_mmap_lock()); - - /* need to keep the GPU VM locked while we set up UMM buffers */ - kbase_gpu_vm_lock(katom->kctx); - for (res_no = 0; res_no < katom->nr_extres; res_no++) { - struct base_external_resource *user_res = &input_extres[res_no]; - struct kbase_va_region *reg; - - reg = kbase_region_tracker_find_region_enclosing_address( - katom->kctx, - user_res->ext_resource & ~(__u64)BASE_EXT_RES_ACCESS_EXCLUSIVE); - /* did we find a matching region object? */ - if (unlikely(kbase_is_region_invalid_or_free(reg))) { - /* roll back */ - goto failed_loop; - } - - if (!(katom->core_req & BASE_JD_REQ_SOFT_JOB) && - (reg->flags & KBASE_REG_PROTECTED)) { - katom->atom_flags |= KBASE_KATOM_FLAG_PROTECTED; - } - - err = kbase_map_external_resource(katom->kctx, reg, current->mm); - if (err) - goto failed_loop; - - katom->extres[res_no] = reg; - } - /* successfully parsed the extres array */ - /* drop the vm lock now */ - kbase_gpu_vm_unlock(katom->kctx); - - /* Release the processes mmap lock */ - up_read(kbase_mem_get_process_mmap_lock()); - - /* Free the buffer holding data from userspace */ - kfree(input_extres); - - /* all done OK */ - return 0; - -/* error handling section */ -failed_loop: - /* undo the loop work. We are guaranteed to have access to the VA region - * as we hold a reference to it until it's unmapped - */ - while (res_no-- > 0) { - struct kbase_va_region *reg = katom->extres[res_no]; - - kbase_unmap_external_resource(katom->kctx, reg); - } - kbase_gpu_vm_unlock(katom->kctx); - - /* Release the processes mmap lock */ - up_read(kbase_mem_get_process_mmap_lock()); - -failed_input_copy: - kfree(input_extres); -failed_input_alloc: - kfree(katom->extres); - katom->extres = NULL; - return err; -} - -static inline void jd_resolve_dep(struct list_head *out_list, struct kbase_jd_atom *katom, u8 d, - bool ctx_is_dying) -{ - u8 other_d = !d; - - while (!list_empty(&katom->dep_head[d])) { - struct kbase_jd_atom *dep_atom; - struct kbase_jd_atom *other_dep_atom; - u8 dep_type; - - dep_atom = list_entry(katom->dep_head[d].next, struct kbase_jd_atom, dep_item[d]); - list_del(katom->dep_head[d].next); - - dep_type = kbase_jd_katom_dep_type(&dep_atom->dep[d]); - kbase_jd_katom_dep_clear(&dep_atom->dep[d]); - - if (katom->event_code != BASE_JD_EVENT_DONE && - (dep_type != BASE_JD_DEP_TYPE_ORDER)) { - dep_atom->event_code = katom->event_code; - KBASE_DEBUG_ASSERT(dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED); - - dep_atom->will_fail_event_code = dep_atom->event_code; - } - other_dep_atom = - (struct kbase_jd_atom *)kbase_jd_katom_dep_atom(&dep_atom->dep[other_d]); - - if (!dep_atom->in_jd_list && - (!other_dep_atom || - (IS_GPU_ATOM(dep_atom) && !ctx_is_dying && !dep_atom->will_fail_event_code && - !other_dep_atom->will_fail_event_code))) { - dep_atom->in_jd_list = true; - list_add_tail(&dep_atom->jd_item, out_list); - } - } -} - -/** - * is_dep_valid - Validate that a dependency is valid for early dependency - * submission - * @katom: Dependency atom to validate - * - * A dependency is valid if any of the following are true : - * - It does not exist (a non-existent dependency does not block submission) - * - It is in the job scheduler - * - It has completed, does not have a failure event code, and has not been - * marked to fail in the future - * - * Return: true if valid, false otherwise - */ -static bool is_dep_valid(struct kbase_jd_atom *katom) -{ - /* If there's no dependency then this is 'valid' from the perspective of - * early dependency submission - */ - if (!katom) - return true; - - /* Dependency must have reached the job scheduler */ - if (katom->status < KBASE_JD_ATOM_STATE_IN_JS) - return false; - - /* If dependency has completed and has failed or will fail then it is - * not valid - */ - if (katom->status >= KBASE_JD_ATOM_STATE_HW_COMPLETED && - (katom->event_code != BASE_JD_EVENT_DONE || katom->will_fail_event_code)) - return false; - - return true; -} - -static void jd_try_submitting_deps(struct list_head *out_list, struct kbase_jd_atom *node) -{ - int i; - - for (i = 0; i < 2; i++) { - struct list_head *pos; - - list_for_each(pos, &node->dep_head[i]) { - struct kbase_jd_atom *dep_atom = - list_entry(pos, struct kbase_jd_atom, dep_item[i]); - - if (IS_GPU_ATOM(dep_atom) && !dep_atom->in_jd_list) { - /*Check if atom deps look sane*/ - bool dep0_valid = is_dep_valid(dep_atom->dep[0].atom); - bool dep1_valid = is_dep_valid(dep_atom->dep[1].atom); - - if (dep0_valid && dep1_valid) { - dep_atom->in_jd_list = true; - list_add(&dep_atom->jd_item, out_list); - } - } - } - } -} - -#if MALI_JIT_PRESSURE_LIMIT_BASE -/** - * jd_update_jit_usage - Update just-in-time physical memory usage for an atom. - * - * @katom: An atom that has just finished. - * - * Read back actual just-in-time memory region usage from atoms that provide - * this information, and update the current physical page pressure. - * - * The caller must hold the kbase_jd_context.lock. - */ -static void jd_update_jit_usage(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct kbase_va_region *reg; - struct kbase_vmap_struct mapping; - u64 *ptr; - u64 used_pages; - unsigned int idx; - - lockdep_assert_held(&kctx->jctx.lock); - - /* If this atom wrote to JIT memory, find out how much it has written - * and update the usage information in the region. - */ - for (idx = 0; idx < ARRAY_SIZE(katom->jit_ids) && katom->jit_ids[idx]; idx++) { - enum heap_pointer { LOW = 0, HIGH, COUNT }; - size_t size_to_read; - u64 read_val; - - reg = kctx->jit_alloc[katom->jit_ids[idx]]; - - if (!reg) { - dev_warn(kctx->kbdev->dev, "%s: JIT id[%u]=%u has no region\n", __func__, - idx, katom->jit_ids[idx]); - continue; - } - - if (reg == KBASE_RESERVED_REG_JIT_ALLOC) { - dev_warn(kctx->kbdev->dev, - "%s: JIT id[%u]=%u has failed to allocate a region\n", __func__, - idx, katom->jit_ids[idx]); - continue; - } - - if (!reg->heap_info_gpu_addr) - continue; - - size_to_read = sizeof(*ptr); - if (reg->flags & KBASE_REG_HEAP_INFO_IS_SIZE) - size_to_read = sizeof(u32); - else if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) - size_to_read = sizeof(u64[COUNT]); - - ptr = kbase_vmap_prot(kctx, reg->heap_info_gpu_addr, size_to_read, KBASE_REG_CPU_RD, - &mapping); - - if (!ptr) { - dev_warn(kctx->kbdev->dev, - "%s: JIT id[%u]=%u start=0x%llx unable to map end marker %llx\n", - __func__, idx, katom->jit_ids[idx], reg->start_pfn << PAGE_SHIFT, - reg->heap_info_gpu_addr); - continue; - } - - if (reg->flags & KBASE_REG_HEAP_INFO_IS_SIZE) { - read_val = READ_ONCE(*(u32 *)ptr); - used_pages = PFN_UP(read_val); - } else { - u64 addr_end; - - if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) { - const unsigned long extension_bytes = reg->extension << PAGE_SHIFT; - const u64 low_ptr = ptr[LOW]; - const u64 high_ptr = ptr[HIGH]; - - /* As either the low or high pointer could - * consume their partition and move onto the - * next chunk, we need to account for both. - * In the case where nothing has been allocated - * from the high pointer the whole chunk could - * be backed unnecessarily - but the granularity - * is the chunk size anyway and any non-zero - * offset of low pointer from the start of the - * chunk would result in the whole chunk being - * backed. - */ - read_val = max(high_ptr, low_ptr); - - /* kbase_check_alloc_sizes() already satisfies - * this, but here to avoid future maintenance - * hazards - */ - WARN_ON(!is_power_of_2(extension_bytes)); - addr_end = ALIGN(read_val, extension_bytes); - } else { - addr_end = read_val = READ_ONCE(*ptr); - } - - if (addr_end >= (reg->start_pfn << PAGE_SHIFT)) - used_pages = PFN_UP(addr_end) - reg->start_pfn; - else - used_pages = reg->used_pages; - } - - trace_mali_jit_report(katom, reg, idx, read_val, used_pages); - kbase_trace_jit_report_gpu_mem(kctx, reg, 0u); - - /* We can never have used more pages than the VA size of the - * region - */ - if (used_pages > reg->nr_pages) { - dev_warn( - kctx->kbdev->dev, - "%s: JIT id[%u]=%u start=0x%llx used_pages %llx > %zx (read 0x%llx as %s%s)\n", - __func__, idx, katom->jit_ids[idx], reg->start_pfn << PAGE_SHIFT, - used_pages, reg->nr_pages, read_val, - (reg->flags & KBASE_REG_HEAP_INFO_IS_SIZE) ? "size" : "addr", - (reg->flags & KBASE_REG_TILER_ALIGN_TOP) ? " with align" : ""); - used_pages = reg->nr_pages; - } - /* Note: one real use case has an atom correctly reporting 0 - * pages in use. This happens in normal use-cases but may only - * happen for a few of the application's frames. - */ - - kbase_vunmap(kctx, &mapping); - - kbase_jit_report_update_pressure(kctx, reg, used_pages, 0u); - } - - kbase_jit_retry_pending_alloc(kctx); -} -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - -bool kbase_jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) -{ - struct kbase_context *kctx = katom->kctx; - struct list_head completed_jobs; - struct list_head runnable_jobs; - bool need_to_try_schedule_context = false; - int i; - - lockdep_assert_held(&kctx->jctx.lock); - - KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_START(kctx->kbdev, katom); - - INIT_LIST_HEAD(&completed_jobs); - INIT_LIST_HEAD(&runnable_jobs); - - KBASE_DEBUG_ASSERT(katom->status != KBASE_JD_ATOM_STATE_UNUSED); - -#if MALI_JIT_PRESSURE_LIMIT_BASE - if (kbase_ctx_flag(kctx, KCTX_JPL_ENABLED)) - jd_update_jit_usage(katom); -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - - /* This is needed in case an atom is failed due to being invalid, this - * can happen *before* the jobs that the atom depends on have completed - */ - for (i = 0; i < 2; i++) { - if (kbase_jd_katom_dep_atom(&katom->dep[i])) { - list_del(&katom->dep_item[i]); - kbase_jd_katom_dep_clear(&katom->dep[i]); - } - } - - jd_mark_atom_complete(katom); - - list_add_tail(&katom->jd_item, &completed_jobs); - - while (!list_empty(&completed_jobs)) { - katom = list_entry(completed_jobs.prev, struct kbase_jd_atom, jd_item); - list_del(completed_jobs.prev); - KBASE_DEBUG_ASSERT(katom->status == KBASE_JD_ATOM_STATE_COMPLETED); - - for (i = 0; i < 2; i++) - jd_resolve_dep(&runnable_jobs, katom, i, kbase_ctx_flag(kctx, KCTX_DYING)); - - if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) - kbase_jd_post_external_resources(katom); - - while (!list_empty(&runnable_jobs)) { - struct kbase_jd_atom *node; - - node = list_entry(runnable_jobs.next, struct kbase_jd_atom, jd_item); - list_del(runnable_jobs.next); - node->in_jd_list = false; - - dev_dbg(kctx->kbdev->dev, "List node %pK has status %d\n", node, - node->status); - - KBASE_DEBUG_ASSERT(node->status != KBASE_JD_ATOM_STATE_UNUSED); - if (node->status == KBASE_JD_ATOM_STATE_IN_JS) - continue; - - if (node->status != KBASE_JD_ATOM_STATE_COMPLETED && - !kbase_ctx_flag(kctx, KCTX_DYING)) { - KBASE_TLSTREAM_TL_RUN_ATOM_START(kctx->kbdev, node, - kbase_jd_atom_id(kctx, node)); - need_to_try_schedule_context |= jd_run_atom(node); - KBASE_TLSTREAM_TL_RUN_ATOM_END(kctx->kbdev, node, - kbase_jd_atom_id(kctx, node)); - } else { - node->event_code = katom->event_code; - - if (node->core_req & BASE_JD_REQ_SOFT_JOB) { - WARN_ON(!list_empty(&node->queue)); - kbase_finish_soft_job(node); - } - node->status = KBASE_JD_ATOM_STATE_COMPLETED; - } - - if (node->status == KBASE_JD_ATOM_STATE_COMPLETED) { - list_add_tail(&node->jd_item, &completed_jobs); - } else if (node->status == KBASE_JD_ATOM_STATE_IN_JS && - !node->will_fail_event_code) { - /* Node successfully submitted, try submitting - * dependencies as they may now be representable - * in JS - */ - jd_try_submitting_deps(&runnable_jobs, node); - } - } - - /* Register a completed job as a disjoint event when the GPU - * is in a disjoint state (ie. being reset). - */ - kbase_disjoint_event_potential(kctx->kbdev); - if (post_immediately && list_empty(&kctx->completed_jobs)) - kbase_event_post(kctx, katom); - else - list_add_tail(&katom->jd_item, &kctx->completed_jobs); - - /* Decrement and check the TOTAL number of jobs. This includes - * those not tracked by the scheduler: 'not ready to run' and - * 'dependency-only' jobs. - */ - if (--kctx->jctx.job_nr == 0) - /* All events are safely queued now, and we can signal - * any waiter that we've got no more jobs (so we can be - * safely terminated) - */ - wake_up(&kctx->jctx.zero_jobs_wait); - } - KBASE_TLSTREAM_TL_JD_DONE_NO_LOCK_END(kctx->kbdev, katom); - return need_to_try_schedule_context; -} -KBASE_EXPORT_TEST_API(kbase_jd_done_nolock); - -/* Trace an atom submission. */ -static void jd_trace_atom_submit(struct kbase_context *const kctx, - struct kbase_jd_atom *const katom, int *priority) -{ - struct kbase_device *const kbdev = kctx->kbdev; - - KBASE_TLSTREAM_TL_NEW_ATOM(kbdev, katom, (u32)kbase_jd_atom_id(kctx, katom)); - KBASE_TLSTREAM_TL_RET_ATOM_CTX(kbdev, katom, kctx); - if (priority) - KBASE_TLSTREAM_TL_ATTRIB_ATOM_PRIORITY(kbdev, katom, (u32)*priority); - KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom, TL_ATOM_STATE_IDLE); - kbase_kinstr_jm_atom_queue(katom); -} - -static bool jd_submit_atom(struct kbase_context *const kctx, - const struct base_jd_atom *const user_atom, - struct kbase_jd_atom *const katom) -{ - struct kbase_device *kbdev = kctx->kbdev; - struct kbase_jd_context *jctx = &kctx->jctx; - int queued = 0; - int i; - int sched_prio; - bool will_fail = false; - unsigned long flags; - enum kbase_jd_atom_state status; - - dev_dbg(kbdev->dev, "User did JD submit atom %pK\n", (void *)katom); - - /* Update the TOTAL number of jobs. This includes those not tracked by - * the scheduler: 'not ready to run' and 'dependency-only' jobs. - */ - jctx->job_nr++; - -#if KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE - katom->start_timestamp.tv64 = 0; -#else - katom->start_timestamp = 0; -#endif - katom->udata = user_atom->udata; - katom->kctx = kctx; - katom->nr_extres = user_atom->nr_extres; - katom->extres = NULL; - katom->device_nr = user_atom->device_nr; - katom->jc = user_atom->jc; - katom->core_req = user_atom->core_req; - katom->jobslot = user_atom->jobslot; - katom->seq_nr = user_atom->seq_nr; - katom->atom_flags = 0; - katom->need_cache_flush_cores_retained = 0; - katom->pre_dep = NULL; - katom->post_dep = NULL; - katom->x_pre_dep = NULL; - katom->x_post_dep = NULL; - katom->will_fail_event_code = BASE_JD_EVENT_NOT_STARTED; - katom->softjob_data = NULL; - - trace_sysgraph(SGR_ARRIVE, kctx->id, user_atom->atom_number); - -#if MALI_JIT_PRESSURE_LIMIT_BASE - /* Older API version atoms might have random values where jit_id now - * lives, but we must maintain backwards compatibility - handle the - * issue. - */ - if (!mali_kbase_supports_jit_pressure_limit(kctx->api_version)) { - katom->jit_ids[0] = 0; - katom->jit_ids[1] = 0; - } else { - katom->jit_ids[0] = user_atom->jit_id[0]; - katom->jit_ids[1] = user_atom->jit_id[1]; - } -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - - /* Implicitly sets katom->protected_state.enter as well. */ - katom->protected_state.exit = KBASE_ATOM_EXIT_PROTECTED_CHECK; - - katom->age = kctx->age_count++; - - INIT_LIST_HEAD(&katom->queue); - INIT_LIST_HEAD(&katom->jd_item); - - /* Don't do anything if there is a mess up with dependencies. - * This is done in a separate cycle to check both the dependencies at ones, otherwise - * it will be extra complexity to deal with 1st dependency ( just added to the list ) - * if only the 2nd one has invalid config. - */ - for (i = 0; i < 2; i++) { - int dep_atom_number = user_atom->pre_dep[i].atom_id; - base_jd_dep_type dep_atom_type = user_atom->pre_dep[i].dependency_type; - - if (dep_atom_number) { - if (dep_atom_type != BASE_JD_DEP_TYPE_ORDER && - dep_atom_type != BASE_JD_DEP_TYPE_DATA) { - katom->event_code = BASE_JD_EVENT_JOB_CONFIG_FAULT; - katom->status = KBASE_JD_ATOM_STATE_COMPLETED; - dev_dbg(kbdev->dev, "Atom %pK status to completed\n", - (void *)katom); - - /* Wrong dependency setup. Atom will be sent - * back to user space. Do not record any - * dependencies. - */ - jd_trace_atom_submit(kctx, katom, NULL); - return kbase_jd_done_nolock(katom, true); - } - } - } - - /* Add dependencies */ - for (i = 0; i < 2; i++) { - int dep_atom_number = user_atom->pre_dep[i].atom_id; - base_jd_dep_type dep_atom_type; - struct kbase_jd_atom *dep_atom = &jctx->atoms[dep_atom_number]; - - dep_atom_type = user_atom->pre_dep[i].dependency_type; - kbase_jd_katom_dep_clear(&katom->dep[i]); - - if (!dep_atom_number) - continue; - - if (dep_atom->status == KBASE_JD_ATOM_STATE_UNUSED || - dep_atom->status == KBASE_JD_ATOM_STATE_COMPLETED) { - if (dep_atom->event_code == BASE_JD_EVENT_DONE) - continue; - /* don't stop this atom if it has an order dependency - * only to the failed one, try to submit it through - * the normal path - */ - if (dep_atom_type == BASE_JD_DEP_TYPE_ORDER && - dep_atom->event_code > BASE_JD_EVENT_ACTIVE) { - continue; - } - - /* Atom has completed, propagate the error code if any */ - katom->event_code = dep_atom->event_code; - katom->status = KBASE_JD_ATOM_STATE_QUEUED; - dev_dbg(kbdev->dev, "Atom %pK status to queued\n", (void *)katom); - - /* This atom will be sent back to user space. - * Do not record any dependencies. - */ - jd_trace_atom_submit(kctx, katom, NULL); - - will_fail = true; - - } else { - /* Atom is in progress, add this atom to the list */ - list_add_tail(&katom->dep_item[i], &dep_atom->dep_head[i]); - kbase_jd_katom_dep_set(&katom->dep[i], dep_atom, dep_atom_type); - queued = 1; - } - } - - if (will_fail) { - if (!queued) { - if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { - /* This softjob has failed due to a previous - * dependency, however we should still run the - * prepare & finish functions - */ - int err = kbase_prepare_soft_job(katom); - - if (err >= 0) - kbase_finish_soft_job(katom); - } - return kbase_jd_done_nolock(katom, true); - } - - katom->will_fail_event_code = katom->event_code; - } - - /* These must occur after the above loop to ensure that an atom - * that depends on a previous atom with the same number behaves - * as expected - */ - katom->event_code = BASE_JD_EVENT_DONE; - katom->status = KBASE_JD_ATOM_STATE_QUEUED; - dev_dbg(kbdev->dev, "Atom %pK status to queued\n", (void *)katom); - - /* For invalid priority, be most lenient and choose the default */ - sched_prio = kbasep_js_atom_prio_to_sched_prio(user_atom->prio); - if (sched_prio == KBASE_JS_ATOM_SCHED_PRIO_INVALID) - sched_prio = KBASE_JS_ATOM_SCHED_PRIO_DEFAULT; - - /* Cap the priority to jctx.max_priority */ - katom->sched_priority = (sched_prio < kctx->jctx.max_priority) ? kctx->jctx.max_priority : - sched_prio; - - /* Create a new atom. */ - jd_trace_atom_submit(kctx, katom, &katom->sched_priority); - - if (!katom->jc && (katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { - /* Reject atoms with job chain = NULL, as these cause issues - * with soft-stop - */ - dev_err(kctx->kbdev->dev, "Rejecting atom with jc = NULL\n"); - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - - /* Reject atoms with an invalid device_nr */ - if ((katom->core_req & BASE_JD_REQ_SPECIFIC_COHERENT_GROUP) && - (katom->device_nr >= kctx->kbdev->gpu_props.num_core_groups)) { - dev_err(kctx->kbdev->dev, "Rejecting atom with invalid device_nr %d\n", - katom->device_nr); - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - - /* Reject atoms with invalid core requirements */ - if ((katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) && - (katom->core_req & BASE_JD_REQ_EVENT_COALESCE)) { - dev_err(kctx->kbdev->dev, "Rejecting atom with invalid core requirements\n"); - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - katom->core_req &= ~BASE_JD_REQ_EVENT_COALESCE; - return kbase_jd_done_nolock(katom, true); - } - - /* Reject soft-job atom of certain types from accessing external resources */ - if ((katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) && - (((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == BASE_JD_REQ_SOFT_FENCE_WAIT) || - ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == BASE_JD_REQ_SOFT_JIT_ALLOC) || - ((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == BASE_JD_REQ_SOFT_JIT_FREE))) { - dev_err(kctx->kbdev->dev, "Rejecting soft-job atom accessing external resources\n"); - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - - if (katom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) { - /* handle what we need to do to access the external resources */ - if (kbase_jd_pre_external_resources(katom, user_atom) != 0) { - /* setup failed (no access, bad resource, unknown resource types, etc.) */ - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - } - -#if !MALI_JIT_PRESSURE_LIMIT_BASE - if (mali_kbase_supports_jit_pressure_limit(kctx->api_version) && - (user_atom->jit_id[0] || user_atom->jit_id[1])) { - /* JIT pressure limit is disabled, but we are receiving non-0 - * JIT IDs - atom is invalid. - */ - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - - /* Validate the atom. Function will return error if the atom is - * malformed. - * - * Soft-jobs never enter the job scheduler but have their own initialize method. - * - * If either fail then we immediately complete the atom with an error. - */ - if ((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0) { - if (!kbase_js_is_atom_valid(kctx->kbdev, katom)) { - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - } else { - /* Soft-job */ - if (kbase_prepare_soft_job(katom) != 0) { - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return kbase_jd_done_nolock(katom, true); - } - } - - if (queued && !IS_GPU_ATOM(katom)) - return false; - - if (katom->core_req & BASE_JD_REQ_SOFT_JOB) { - if (kbase_process_soft_job(katom) == 0) { - kbase_finish_soft_job(katom); - return kbase_jd_done_nolock(katom, true); - } - return false; - } - - if ((katom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_DEP) { - bool need_to_try_schedule_context; - - katom->status = KBASE_JD_ATOM_STATE_IN_JS; - dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n", (void *)katom); - - need_to_try_schedule_context = kbasep_js_add_job(kctx, katom); - /* If job was cancelled then resolve immediately */ - if (katom->event_code != BASE_JD_EVENT_JOB_CANCELLED) - return need_to_try_schedule_context; - - /* Synchronize with backend reset */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - status = katom->status; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - if (status == KBASE_JD_ATOM_STATE_HW_COMPLETED) { - dev_dbg(kctx->kbdev->dev, "Atom %d cancelled on HW\n", - kbase_jd_atom_id(katom->kctx, katom)); - return need_to_try_schedule_context; - } - } - - /* This is a pure dependency. Resolve it immediately */ - return kbase_jd_done_nolock(katom, true); -} - -int kbase_jd_submit(struct kbase_context *kctx, void __user *user_addr, u32 nr_atoms, u32 stride, - bool uk6_atom) -{ - struct kbase_jd_context *jctx = &kctx->jctx; - int err = 0; - u32 i; - bool need_to_try_schedule_context = false; - struct kbase_device *kbdev; - u32 latest_flush; - - bool jd_atom_is_v2 = (stride == sizeof(struct base_jd_atom_v2)); - - CSTD_UNUSED(uk6_atom); - - /* - * kbase_jd_submit isn't expected to fail and so all errors with the - * jobs are reported by immediately failing them (through event system) - */ - kbdev = kctx->kbdev; - - if (kbase_ctx_flag(kctx, KCTX_SUBMIT_DISABLED)) { - dev_err(kbdev->dev, - "Attempt to submit to a context that has SUBMIT_DISABLED set on it\n"); - return -EINVAL; - } - - if (stride != sizeof(struct base_jd_atom_v2) && stride != sizeof(struct base_jd_atom)) { - dev_err(kbdev->dev, - "Stride %u passed to job_submit isn't supported by the kernel\n", stride); - return -EINVAL; - } - - if (nr_atoms > BASE_JD_ATOM_COUNT) { - dev_dbg(kbdev->dev, "Invalid attempt to submit %u atoms at once for kctx %d_%d", - nr_atoms, kctx->tgid, kctx->id); - return -EINVAL; - } - - /* All atoms submitted in this call have the same flush ID */ - latest_flush = kbase_backend_get_current_flush_id(kbdev); - - for (i = 0; i < nr_atoms; i++) { - struct base_jd_atom user_atom = { - .seq_nr = 0, - }; - struct kbase_jd_atom *katom; - - if (unlikely(jd_atom_is_v2)) { - if (copy_from_user(&user_atom.jc, user_addr, - sizeof(struct base_jd_atom_v2)) != 0) { - dev_dbg(kbdev->dev, - "Invalid atom address %pK passed to job_submit\n", - user_addr); - err = -EFAULT; - break; - } - - /* no seq_nr in v2 */ - user_atom.seq_nr = 0; - } else { - if (copy_from_user(&user_atom, user_addr, stride) != 0) { - dev_dbg(kbdev->dev, - "Invalid atom address %pK passed to job_submit\n", - user_addr); - err = -EFAULT; - break; - } - } - - user_addr = (void __user *)((uintptr_t)user_addr + stride); - - mutex_lock(&jctx->lock); -#ifndef compiletime_assert -#define compiletime_assert_defined -#define compiletime_assert(x, msg) \ - do { \ - switch (0) { \ - case 0: \ - case (x):; \ - } \ - } while (false) -#endif - compiletime_assert((1 << (8 * sizeof(user_atom.atom_number))) == BASE_JD_ATOM_COUNT, - "BASE_JD_ATOM_COUNT and base_atom_id type out of sync"); - compiletime_assert(sizeof(user_atom.pre_dep[0].atom_id) == - sizeof(user_atom.atom_number), - "BASE_JD_ATOM_COUNT and base_atom_id type out of sync"); -#ifdef compiletime_assert_defined -#undef compiletime_assert -#undef compiletime_assert_defined -#endif - katom = &jctx->atoms[user_atom.atom_number]; - - /* Record the flush ID for the cache flush optimisation */ - katom->flush_id = latest_flush; - - while (katom->status != KBASE_JD_ATOM_STATE_UNUSED) { - /* Atom number is already in use, wait for the atom to - * complete - */ - mutex_unlock(&jctx->lock); - - /* This thread will wait for the atom to complete. Due - * to thread scheduling we are not sure that the other - * thread that owns the atom will also schedule the - * context, so we force the scheduler to be active and - * hence eventually schedule this context at some point - * later. - */ - kbase_js_sched_all(kbdev); - - if (wait_event_killable(katom->completed, - katom->status == KBASE_JD_ATOM_STATE_UNUSED) != 0) { - /* We're being killed so the result code - * doesn't really matter - */ - return 0; - } - mutex_lock(&jctx->lock); - } - KBASE_TLSTREAM_TL_JD_SUBMIT_ATOM_START(kbdev, katom); - need_to_try_schedule_context |= jd_submit_atom(kctx, &user_atom, katom); - KBASE_TLSTREAM_TL_JD_SUBMIT_ATOM_END(kbdev, katom); - /* Register a completed job as a disjoint event when the GPU is in a disjoint state - * (ie. being reset). - */ - kbase_disjoint_event_potential(kbdev); - - mutex_unlock(&jctx->lock); - if (fatal_signal_pending(current)) { - dev_dbg(kbdev->dev, "Fatal signal pending for kctx %d_%d", kctx->tgid, - kctx->id); - /* We're being killed so the result code doesn't really matter */ - return 0; - } - } - - if (need_to_try_schedule_context) - kbase_js_sched_all(kbdev); - - return err; -} - -KBASE_EXPORT_TEST_API(kbase_jd_submit); - -void kbase_jd_done_worker(struct work_struct *data) -{ - struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); - struct kbase_jd_context *jctx; - struct kbase_context *kctx; - struct kbasep_js_kctx_info *js_kctx_info; - struct kbase_device *kbdev; - struct kbasep_js_device_data *js_devdata; - u64 cache_jc = katom->jc; - struct kbasep_js_atom_retained_state katom_retained_state; - bool context_idle; - base_jd_core_req core_req = katom->core_req; - - /* Soft jobs should never reach this function */ - KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); - - kctx = katom->kctx; - jctx = &kctx->jctx; - kbdev = kctx->kbdev; - js_kctx_info = &kctx->jctx.sched_info; - js_devdata = &kbdev->js_data; - - dev_dbg(kbdev->dev, "Enter atom %pK done worker for kctx %pK\n", (void *)katom, - (void *)kctx); - - KBASE_KTRACE_ADD_JM(kbdev, JD_DONE_WORKER, kctx, katom, katom->jc, 0); - - kbase_backend_complete_wq(kbdev, katom); - - /* - * Begin transaction on JD context and JS context - */ - mutex_lock(&jctx->lock); - KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom, TL_ATOM_STATE_DONE); - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - - /* This worker only gets called on contexts that are scheduled *in*. This is - * because it only happens in response to an IRQ from a job that was - * running. - */ - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - if (katom->event_code == BASE_JD_EVENT_STOPPED) { - unsigned long flags; - - dev_dbg(kbdev->dev, "Atom %pK has been promoted to stopped\n", (void *)katom); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - katom->status = KBASE_JD_ATOM_STATE_IN_JS; - dev_dbg(kctx->kbdev->dev, "Atom %pK status to in JS\n", (void *)katom); - kbase_js_unpull(kctx, katom); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&jctx->lock); - - return; - } - - if ((katom->event_code != BASE_JD_EVENT_DONE) && !kbase_ctx_flag(katom->kctx, KCTX_DYING) && - !kbase_ctx_flag(katom->kctx, KCTX_PAGE_FAULT_REPORT_SKIP)) - if (!kbase_is_quick_reset_enabled(kbdev)) - dev_err(kbdev->dev, "t6xx: GPU fault 0x%02lx from job slot %d\n", - (unsigned long)katom->event_code, katom->slot_nr); - - /* Retain state before the katom disappears */ - kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); - - context_idle = kbase_js_complete_atom_wq(kctx, katom); - - KBASE_DEBUG_ASSERT(kbasep_js_has_atom_finished(&katom_retained_state)); - - kbasep_js_remove_job(kbdev, kctx, katom); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - /* kbase_jd_done_nolock() requires the jsctx_mutex lock to be dropped */ - kbase_jd_done_nolock(katom, false); - - /* katom may have been freed now, do not use! */ - - if (context_idle) { - unsigned long flags; - - context_idle = false; - mutex_lock(&js_devdata->queue_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* If kbase_sched() has scheduled this context back in then - * KCTX_ACTIVE will have been set after we marked it as - * inactive, and another pm reference will have been taken, so - * drop our reference. But do not call kbase_jm_idle_ctx(), as - * the context is active and fast-starting is allowed. - * - * If an atom has been fast-started then - * kbase_jsctx_atoms_pulled(kctx) will return non-zero but - * KCTX_ACTIVE will still be false (as the previous pm - * reference has been inherited). Do NOT drop our reference, as - * it has been re-used, and leave the context as active. - * - * If no new atoms have been started then KCTX_ACTIVE will - * still be false and kbase_jsctx_atoms_pulled(kctx) will - * return zero, so drop the reference and call - * kbase_jm_idle_ctx(). - * - * As the checks are done under both the queue_mutex and - * hwaccess_lock is should be impossible for this to race - * with the scheduler code. - */ - if (kbase_ctx_flag(kctx, KCTX_ACTIVE) || !kbase_jsctx_atoms_pulled(kctx)) { - /* Calling kbase_jm_idle_ctx() here will ensure that - * atoms are not fast-started when we drop the - * hwaccess_lock. This is not performed if - * KCTX_ACTIVE is set as in that case another pm - * reference has been taken and a fast-start would be - * valid. - */ - if (!kbase_ctx_flag(kctx, KCTX_ACTIVE)) - kbase_jm_idle_ctx(kbdev, kctx); - context_idle = true; - } else { - kbase_ctx_flag_set(kctx, KCTX_ACTIVE); - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_devdata->queue_mutex); - } - - /* - * Transaction complete - */ - mutex_unlock(&jctx->lock); - - /* Job is now no longer running, so can now safely release the context - * reference, and handle any actions that were logged against the - * atom's retained state - */ - - kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); - - kbase_js_sched_all(kbdev); - - if (!atomic_dec_return(&kctx->work_count)) { - /* If worker now idle then post all events that kbase_jd_done_nolock() - * has queued - */ - mutex_lock(&jctx->lock); - while (!list_empty(&kctx->completed_jobs)) { - struct kbase_jd_atom *atom = list_entry(kctx->completed_jobs.next, - struct kbase_jd_atom, jd_item); - list_del(kctx->completed_jobs.next); - - kbase_event_post(kctx, atom); - } - mutex_unlock(&jctx->lock); - } - - kbase_backend_complete_wq_post_sched(kbdev, core_req); - - if (context_idle) - kbase_pm_context_idle(kbdev); - - KBASE_KTRACE_ADD_JM(kbdev, JD_DONE_WORKER_END, kctx, NULL, cache_jc, 0); - - dev_dbg(kbdev->dev, "Leave atom %pK done worker for kctx %pK\n", (void *)katom, - (void *)kctx); -} - -/** - * jd_cancel_worker - Work queue job cancel function. - * @data: a &struct work_struct - * - * Only called as part of 'Zapping' a context (which occurs on termination). - * Operates serially with the kbase_jd_done_worker() on the work queue. - * - * This can only be called on contexts that aren't scheduled. - * - * We don't need to release most of the resources that would occur on - * kbase_jd_done() or kbase_jd_done_worker(), because the atoms here must not be - * running (by virtue of only being called on contexts that aren't - * scheduled). - */ -static void jd_cancel_worker(struct work_struct *data) -{ - struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); - struct kbase_jd_context *jctx; - struct kbase_context *kctx; - struct kbasep_js_kctx_info *js_kctx_info; - bool need_to_try_schedule_context; - bool attr_state_changed; - struct kbase_device *kbdev; - CSTD_UNUSED(need_to_try_schedule_context); - - /* Soft jobs should never reach this function */ - KBASE_DEBUG_ASSERT((katom->core_req & BASE_JD_REQ_SOFT_JOB) == 0); - - kctx = katom->kctx; - kbdev = kctx->kbdev; - jctx = &kctx->jctx; - js_kctx_info = &kctx->jctx.sched_info; - - KBASE_KTRACE_ADD_JM(kbdev, JD_CANCEL_WORKER, kctx, katom, katom->jc, 0); - - /* This only gets called on contexts that are scheduled out. Hence, we must - * make sure we don't de-ref the number of running jobs (there aren't - * any), nor must we try to schedule out the context (it's already - * scheduled out). - */ - KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - /* Scheduler: Remove the job from the system */ - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - attr_state_changed = kbasep_js_remove_cancelled_job(kbdev, kctx, katom); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - mutex_lock(&jctx->lock); - - need_to_try_schedule_context = kbase_jd_done_nolock(katom, true); - /* Because we're zapping, we're not adding any more jobs to this ctx, so no need to - * schedule the context. There's also no need for the jsctx_mutex to have been taken - * around this too. - */ - KBASE_DEBUG_ASSERT(!need_to_try_schedule_context); - - /* katom may have been freed now, do not use! */ - mutex_unlock(&jctx->lock); - - if (attr_state_changed) - kbase_js_sched_all(kbdev); -} - -/** - * kbase_jd_done - Complete a job that has been removed from the Hardware - * @katom: atom which has been completed - * @slot_nr: slot the atom was on - * @end_timestamp: completion time - * @done_code: completion code - * - * This must be used whenever a job has been removed from the Hardware, e.g.: - * An IRQ indicates that the job finished (for both error and 'done' codes), or - * the job was evicted from the JS_HEAD_NEXT registers during a Soft/Hard stop. - * - * Some work is carried out immediately, and the rest is deferred onto a - * workqueue - * - * Context: - * This can be called safely from atomic context. - * The caller must hold kbdev->hwaccess_lock - */ -void kbase_jd_done(struct kbase_jd_atom *katom, unsigned int slot_nr, ktime_t *end_timestamp, - kbasep_js_atom_done_code done_code) -{ - struct kbase_context *kctx; - struct kbase_device *kbdev; - - CSTD_UNUSED(end_timestamp); - - KBASE_DEBUG_ASSERT(katom); - kctx = katom->kctx; - KBASE_DEBUG_ASSERT(kctx); - kbdev = kctx->kbdev; - KBASE_DEBUG_ASSERT(kbdev); - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (done_code & KBASE_JS_ATOM_DONE_EVICTED_FROM_NEXT) - katom->event_code = BASE_JD_EVENT_REMOVED_FROM_NEXT; - - KBASE_KTRACE_ADD_JM(kbdev, JD_DONE, kctx, katom, katom->jc, 0); - - kbase_job_check_leave_disjoint(kbdev, katom); - - katom->slot_nr = slot_nr; - - atomic_inc(&kctx->work_count); - -#if IS_ENABLED(CONFIG_DEBUG_FS) - /* a failed job happened and is waiting for dumping*/ - if (!katom->will_fail_event_code && kbase_debug_job_fault_process(katom, katom->event_code)) - return; -#endif - - WARN_ON(work_pending(&katom->work)); - INIT_WORK(&katom->work, kbase_jd_done_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); -} - -KBASE_EXPORT_TEST_API(kbase_jd_done); - -void kbase_jd_cancel(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(katom != NULL); - kctx = katom->kctx; - KBASE_DEBUG_ASSERT(kctx != NULL); - - dev_dbg(kbdev->dev, "JD: cancelling atom %pK\n", (void *)katom); - KBASE_KTRACE_ADD_JM(kbdev, JD_CANCEL, kctx, katom, katom->jc, 0); - - /* This should only be done from a context that is not scheduled */ - KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - WARN_ON(work_pending(&katom->work)); - - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - INIT_WORK(&katom->work, jd_cancel_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); -} - -void kbase_jd_zap_context(struct kbase_context *kctx) -{ - struct kbase_jd_atom *katom; - struct list_head *entry, *tmp; - struct kbase_device *kbdev; - - KBASE_DEBUG_ASSERT(kctx); - - kbdev = kctx->kbdev; - - KBASE_KTRACE_ADD_JM(kbdev, JD_ZAP_CONTEXT, kctx, NULL, 0u, 0u); - - kbase_js_zap_context(kctx); - - mutex_lock(&kctx->jctx.lock); - - /* - * While holding the struct kbase_jd_context lock clean up jobs which are known to kbase but are - * queued outside the job scheduler. - */ - - del_timer_sync(&kctx->soft_job_timeout); - list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { - katom = list_entry(entry, struct kbase_jd_atom, queue); - kbase_cancel_soft_job(katom); - } - - mutex_unlock(&kctx->jctx.lock); - -#if IS_ENABLED(CONFIG_DEBUG_FS) - kbase_debug_job_fault_kctx_unblock(kctx); -#endif - - kbase_jm_wait_for_zero_jobs(kctx); -} - -KBASE_EXPORT_TEST_API(kbase_jd_zap_context); - -int kbase_jd_init(struct kbase_context *kctx) -{ - int i; - int mali_err = 0; - struct priority_control_manager_device *pcm_device = NULL; - - KBASE_DEBUG_ASSERT(kctx); - pcm_device = kctx->kbdev->pcm_dev; - kctx->jctx.max_priority = KBASE_JS_ATOM_SCHED_PRIO_REALTIME; - - kctx->jctx.job_done_wq = alloc_workqueue("mali_jd", WQ_HIGHPRI | WQ_UNBOUND, 1); - if (kctx->jctx.job_done_wq == NULL) { - mali_err = -ENOMEM; - goto out1; - } - - for (i = 0; i < BASE_JD_ATOM_COUNT; i++) { - init_waitqueue_head(&kctx->jctx.atoms[i].completed); - - INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[0]); - INIT_LIST_HEAD(&kctx->jctx.atoms[i].dep_head[1]); - - /* Catch userspace attempting to use an atom which doesn't exist as a pre-dependency */ - kctx->jctx.atoms[i].event_code = BASE_JD_EVENT_JOB_INVALID; - kctx->jctx.atoms[i].status = KBASE_JD_ATOM_STATE_UNUSED; - -#if IS_ENABLED(CONFIG_SYNC_FILE) - kctx->jctx.atoms[i].dma_fence.context = dma_fence_context_alloc(1); -#endif - } - - mutex_init(&kctx->jctx.lock); - - init_waitqueue_head(&kctx->jctx.zero_jobs_wait); - - spin_lock_init(&kctx->jctx.tb_lock); - - INIT_LIST_HEAD(&kctx->completed_jobs); - - /* Check if there are platform rules for maximum priority */ - if (pcm_device) - kctx->jctx.max_priority = pcm_device->ops.pcm_scheduler_priority_check( - pcm_device, current, KBASE_JS_ATOM_SCHED_PRIO_REALTIME); - - return 0; - -out1: - return mali_err; -} - -KBASE_EXPORT_TEST_API(kbase_jd_init); - -void kbase_jd_exit(struct kbase_context *kctx) -{ - KBASE_DEBUG_ASSERT(kctx); - - /* Work queue is emptied by this */ - destroy_workqueue(kctx->jctx.job_done_wq); -} - -KBASE_EXPORT_TEST_API(kbase_jd_exit); diff --git a/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.c b/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.c deleted file mode 100644 index c3b6a63afc3f..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.c +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#if IS_ENABLED(CONFIG_DEBUG_FS) - -#include -#include -#include -#if IS_ENABLED(CONFIG_SYNC_FILE) -#include -#endif -#include - -struct kbase_jd_debugfs_depinfo { - u8 id; - char type; -}; - -static void kbase_jd_debugfs_fence_info(struct kbase_jd_atom *atom, struct seq_file *sfile) -{ -#if IS_ENABLED(CONFIG_SYNC_FILE) - struct kbase_sync_fence_info info; - int res; - - switch (atom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_FENCE_TRIGGER: - res = kbase_sync_fence_out_info_get(atom, &info); - if (res == 0) - seq_printf(sfile, "Sa([%pK]%d) ", info.fence, info.status); - break; - case BASE_JD_REQ_SOFT_FENCE_WAIT: - res = kbase_sync_fence_in_info_get(atom, &info); - if (res == 0) - seq_printf(sfile, "Wa([%pK]%d) ", info.fence, info.status); - break; - default: - break; - } -#endif /* CONFIG_SYNC_FILE */ -} - -static void kbasep_jd_debugfs_atom_deps(struct kbase_jd_debugfs_depinfo *deps, - struct kbase_jd_atom *atom) -{ - struct kbase_context *kctx = atom->kctx; - int i; - - for (i = 0; i < 2; i++) { - deps[i].id = (unsigned int)(atom->dep[i].atom ? - kbase_jd_atom_id(kctx, atom->dep[i].atom) : - 0); - - switch (atom->dep[i].dep_type) { - case BASE_JD_DEP_TYPE_INVALID: - deps[i].type = ' '; - break; - case BASE_JD_DEP_TYPE_DATA: - deps[i].type = 'D'; - break; - case BASE_JD_DEP_TYPE_ORDER: - deps[i].type = '>'; - break; - default: - deps[i].type = '?'; - break; - } - } -} -/** - * kbasep_jd_debugfs_atoms_show - Show callback for the JD atoms debugfs file. - * @sfile: The debugfs entry - * @data: Data associated with the entry - * - * This function is called to get the contents of the JD atoms debugfs file. - * This is a report of all atoms managed by kbase_jd_context.atoms - * - * Return: 0 if successfully prints data in debugfs entry file, failure - * otherwise - */ -static int kbasep_jd_debugfs_atoms_show(struct seq_file *sfile, void *data) -{ - struct kbase_context *kctx = sfile->private; - struct kbase_jd_atom *atoms; - unsigned long irq_flags; - int i; - - CSTD_UNUSED(data); - - KBASE_DEBUG_ASSERT(kctx != NULL); - - /* Print version */ - seq_printf(sfile, "v%u\n", MALI_JD_DEBUGFS_VERSION); - - /* Print U/K API version */ - seq_printf(sfile, "ukv%u.%u\n", BASE_UK_VERSION_MAJOR, BASE_UK_VERSION_MINOR); - - /* Print table heading */ - seq_puts(sfile, " ID, Core req, St, Predeps, Start time, Additional info...\n"); - - atoms = kctx->jctx.atoms; - /* General atom states */ - mutex_lock(&kctx->jctx.lock); - /* JS-related states */ - spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, irq_flags); - for (i = 0; i != BASE_JD_ATOM_COUNT; ++i) { - struct kbase_jd_atom *atom = &atoms[i]; - s64 start_timestamp = 0; - struct kbase_jd_debugfs_depinfo deps[2]; - - if (atom->status == KBASE_JD_ATOM_STATE_UNUSED) - continue; - - /* start_timestamp is cleared as soon as the atom leaves UNUSED state - * and set before a job is submitted to the h/w, a non-zero value means - * it is valid - */ - if (ktime_to_ns(atom->start_timestamp)) - start_timestamp = - ktime_to_ns(ktime_sub(ktime_get_raw(), atom->start_timestamp)); - - kbasep_jd_debugfs_atom_deps(deps, atom); - - seq_printf(sfile, "%3u, %8x, %2u, %c%3u %c%3u, %20lld, ", i, atom->core_req, - atom->status, deps[0].type, deps[0].id, deps[1].type, deps[1].id, - start_timestamp); - - kbase_jd_debugfs_fence_info(atom, sfile); - - seq_puts(sfile, "\n"); - } - spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, irq_flags); - mutex_unlock(&kctx->jctx.lock); - - return 0; -} - -/** - * kbasep_jd_debugfs_atoms_open - open operation for atom debugfs file - * @in: &struct inode pointer - * @file: &struct file pointer - * - * Return: file descriptor - */ -static int kbasep_jd_debugfs_atoms_open(struct inode *in, struct file *file) -{ - return single_open(file, kbasep_jd_debugfs_atoms_show, in->i_private); -} - -static const struct file_operations kbasep_jd_debugfs_atoms_fops = { - .owner = THIS_MODULE, - .open = kbasep_jd_debugfs_atoms_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx) -{ - const mode_t mode = 0444; - - /* Caller already ensures this, but we keep the pattern for - * maintenance safety. - */ - if (WARN_ON(!kctx) || WARN_ON(IS_ERR_OR_NULL(kctx->kctx_dentry))) - return; - - /* Expose all atoms */ - debugfs_create_file("atoms", mode, kctx->kctx_dentry, kctx, &kbasep_jd_debugfs_atoms_fops); -} - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.h b/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.h deleted file mode 100644 index 8ea18b36d0d8..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_jd_debugfs.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Header file for job dispatcher-related entries in debugfs - */ - -#ifndef _KBASE_JD_DEBUGFS_H -#define _KBASE_JD_DEBUGFS_H - -#include - -#define MALI_JD_DEBUGFS_VERSION 3 - -/* Forward declarations */ -struct kbase_context; - -/** - * kbasep_jd_debugfs_ctx_init() - Add debugfs entries for JD system - * - * @kctx: Pointer to kbase_context - */ -void kbasep_jd_debugfs_ctx_init(struct kbase_context *kctx); - -#endif /*_KBASE_JD_DEBUGFS_H*/ diff --git a/drivers/gpu/arm/valhall/mali_kbase_jm.c b/drivers/gpu/arm/valhall/mali_kbase_jm.c deleted file mode 100644 index cac12df225a0..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_jm.c +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2013-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * HW access job manager common APIs - */ - -#include -#include "mali_kbase_hwaccess_jm.h" -#include "mali_kbase_jm.h" - -#if !MALI_USE_CSF -/** - * kbase_jm_next_job() - Attempt to run the next @nr_jobs_to_submit jobs on slot - * @js on the active context. - * @kbdev: Device pointer - * @js: Job slot to run on - * @nr_jobs_to_submit: Number of jobs to attempt to submit - * - * Return: true if slot can still be submitted on, false if slot is now full. - */ -static bool kbase_jm_next_job(struct kbase_device *kbdev, unsigned int js, int nr_jobs_to_submit) -{ - struct kbase_context *kctx; - int i; - - kctx = kbdev->hwaccess.active_kctx[js]; - dev_dbg(kbdev->dev, "Trying to run the next %d jobs in kctx %pK (s:%u)\n", - nr_jobs_to_submit, (void *)kctx, js); - - if (!kctx) - return true; - - for (i = 0; i < nr_jobs_to_submit; i++) { - struct kbase_jd_atom *katom = kbase_js_pull(kctx, js); - - if (!katom) - return true; /* Context has no jobs on this slot */ - - kbase_backend_run_atom(kbdev, katom); - } - - dev_dbg(kbdev->dev, "Slot ringbuffer should now be full (s:%u)\n", js); - return false; -} - -u32 kbase_jm_kick(struct kbase_device *kbdev, u32 js_mask) -{ - u32 ret_mask = 0; - - lockdep_assert_held(&kbdev->hwaccess_lock); - dev_dbg(kbdev->dev, "JM kick slot mask 0x%x\n", js_mask); - - while (js_mask) { - unsigned int js = (unsigned int)ffs((int)js_mask) - 1U; - int nr_jobs_to_submit = kbase_backend_slot_free(kbdev, js); - - if (kbase_jm_next_job(kbdev, js, nr_jobs_to_submit)) - ret_mask |= (1U << js); - - js_mask &= ~(1U << js); - } - - dev_dbg(kbdev->dev, "Can still submit to mask 0x%x\n", ret_mask); - return ret_mask; -} - -void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask) -{ - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (!down_trylock(&js_devdata->schedule_sem)) { - kbase_jm_kick(kbdev, js_mask); - up(&js_devdata->schedule_sem); - } -} - -void kbase_jm_try_kick_all(struct kbase_device *kbdev) -{ - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (!down_trylock(&js_devdata->schedule_sem)) { - kbase_jm_kick_all(kbdev); - up(&js_devdata->schedule_sem); - } -} - -void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - unsigned int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { - if (kbdev->hwaccess.active_kctx[js] == kctx) { - dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%u)\n", (void *)kctx, - js); - kbdev->hwaccess.active_kctx[js] = NULL; - } - } -} - -struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev, - struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - dev_dbg(kbdev->dev, "Atom %pK is returning with event code 0x%x\n", (void *)katom, - katom->event_code); - - KBASE_KTRACE_ADD_JM(kbdev, JM_RETURN_ATOM_TO_JS, katom->kctx, katom, katom->jc, - katom->event_code); - - if (katom->event_code != BASE_JD_EVENT_STOPPED && - katom->event_code != BASE_JD_EVENT_REMOVED_FROM_NEXT) { - return kbase_js_complete_atom(katom, NULL); - } - - kbase_js_unpull(katom->kctx, katom); - - return NULL; -} - -struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - ktime_t *end_timestamp) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - return kbase_js_complete_atom(katom, end_timestamp); -} -#endif /* !MALI_USE_CSF */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_jm.h b/drivers/gpu/arm/valhall/mali_kbase_jm.h deleted file mode 100644 index fb0e69a0aee3..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_jm.h +++ /dev/null @@ -1,117 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2013-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Job manager common APIs - */ - -#ifndef _KBASE_JM_H_ -#define _KBASE_JM_H_ - -#if !MALI_USE_CSF -/** - * kbase_jm_kick() - Indicate that there are jobs ready to run. - * @kbdev: Device pointer - * @js_mask: Mask of the job slots that can be pulled from. - * - * Caller must hold the hwaccess_lock and schedule_sem semaphore - * - * Return: Mask of the job slots that can still be submitted to. - */ -u32 kbase_jm_kick(struct kbase_device *kbdev, u32 js_mask); - -/** - * kbase_jm_kick_all() - Indicate that there are jobs ready to run on all job - * slots. - * @kbdev: Device pointer - * - * Caller must hold the hwaccess_lock and schedule_sem semaphore - * - * Return: Mask of the job slots that can still be submitted to. - */ -static inline u32 kbase_jm_kick_all(struct kbase_device *kbdev) -{ - return kbase_jm_kick(kbdev, (1U << kbdev->gpu_props.num_job_slots) - 1U); -} - -/** - * kbase_jm_try_kick - Attempt to call kbase_jm_kick - * @kbdev: Device pointer - * @js_mask: Mask of the job slots that can be pulled from - * Context: Caller must hold hwaccess_lock - * - * If schedule_sem can be immediately obtained then this function will call - * kbase_jm_kick() otherwise it will do nothing. - */ -void kbase_jm_try_kick(struct kbase_device *kbdev, u32 js_mask); - -/** - * kbase_jm_try_kick_all() - Attempt to call kbase_jm_kick_all - * @kbdev: Device pointer - * Context: Caller must hold hwaccess_lock - * - * If schedule_sem can be immediately obtained then this function will call - * kbase_jm_kick_all() otherwise it will do nothing. - */ -void kbase_jm_try_kick_all(struct kbase_device *kbdev); -#endif /* !MALI_USE_CSF */ - -#if !MALI_USE_CSF -/** - * kbase_jm_idle_ctx() - Mark a context as idle. - * @kbdev: Device pointer - * @kctx: Context to mark as idle - * - * No more atoms will be pulled from this context until it is marked as active - * by kbase_js_use_ctx(). - * - * The context should have no atoms currently pulled from it - * (kbase_jsctx_atoms_pulled(kctx) == 0). - * - * Caller must hold the hwaccess_lock - */ -void kbase_jm_idle_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbase_jm_return_atom_to_js() - Return an atom to the job scheduler that has - * been soft-stopped or will fail due to a - * dependency - * @kbdev: Device pointer - * @katom: Atom that has been stopped or will be failed - * - * Return: Atom that has now been unblocked and can now be run, or NULL if none - */ -struct kbase_jd_atom *kbase_jm_return_atom_to_js(struct kbase_device *kbdev, - struct kbase_jd_atom *katom); - -/** - * kbase_jm_complete() - Complete an atom - * @kbdev: Device pointer - * @katom: Atom that has completed - * @end_timestamp: Timestamp of atom completion - * - * Return: Atom that has now been unblocked and can now be run, or NULL if none - */ -struct kbase_jd_atom *kbase_jm_complete(struct kbase_device *kbdev, struct kbase_jd_atom *katom, - ktime_t *end_timestamp); -#endif /* !MALI_USE_CSF */ - -#endif /* _KBASE_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_js.c b/drivers/gpu/arm/valhall/mali_kbase_js.c deleted file mode 100644 index 8e3dd7023373..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_js.c +++ /dev/null @@ -1,3271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * Job Scheduler Implementation - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mali_kbase_jm.h" -#include "mali_kbase_hwaccess_jm.h" -#include -#include -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) -#include -#endif - -/* - * Private types - */ - -/* Bitpattern indicating the result of releasing a context */ -enum { - /* The context was descheduled - caller should try scheduling in a new - * one to keep the runpool full - */ - KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED = (1u << 0), - /* Ctx attributes were changed - caller should try scheduling all - * contexts - */ - KBASEP_JS_RELEASE_RESULT_SCHED_ALL = (1u << 1) -}; - -typedef u32 kbasep_js_release_result; - -const int kbasep_js_atom_priority_to_relative[BASE_JD_NR_PRIO_LEVELS] = { - KBASE_JS_ATOM_SCHED_PRIO_MED, /* BASE_JD_PRIO_MEDIUM */ - KBASE_JS_ATOM_SCHED_PRIO_HIGH, /* BASE_JD_PRIO_HIGH */ - KBASE_JS_ATOM_SCHED_PRIO_LOW, /* BASE_JD_PRIO_LOW */ - KBASE_JS_ATOM_SCHED_PRIO_REALTIME /* BASE_JD_PRIO_REALTIME */ -}; - -const base_jd_prio kbasep_js_relative_priority_to_atom[KBASE_JS_ATOM_SCHED_PRIO_COUNT] = { - BASE_JD_PRIO_REALTIME, /* KBASE_JS_ATOM_SCHED_PRIO_REALTIME */ - BASE_JD_PRIO_HIGH, /* KBASE_JS_ATOM_SCHED_PRIO_HIGH */ - BASE_JD_PRIO_MEDIUM, /* KBASE_JS_ATOM_SCHED_PRIO_MED */ - BASE_JD_PRIO_LOW /* KBASE_JS_ATOM_SCHED_PRIO_LOW */ -}; - -/* - * Private function prototypes - */ -static kbasep_js_release_result -kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state); - -static unsigned int kbase_js_get_slot(struct kbase_device *kbdev, struct kbase_jd_atom *katom); - -static void kbase_js_foreach_ctx_job(struct kbase_context *kctx, kbasep_js_ctx_job_cb *callback); - -/* Helper for ktrace */ -#if KBASE_KTRACE_ENABLE -static int kbase_ktrace_get_ctx_refcnt(struct kbase_context *kctx) -{ - return atomic_read(&kctx->refcount); -} -#else /* KBASE_KTRACE_ENABLE */ -static int kbase_ktrace_get_ctx_refcnt(struct kbase_context *kctx) -{ - CSTD_UNUSED(kctx); - return 0; -} -#endif /* KBASE_KTRACE_ENABLE */ - -/* - * Private functions - */ - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) -/** - * gpu_metrics_timer_callback() - Callback function for the GPU metrics hrtimer - * - * @timer: Pointer to the GPU metrics hrtimer - * - * This function will emit power/gpu_work_period tracepoint for all the active - * GPU metrics contexts. The timer will be restarted if needed. - * - * Return: enum value to indicate that timer should not be restarted. - */ -static enum hrtimer_restart gpu_metrics_timer_callback(struct hrtimer *timer) -{ - struct kbasep_js_device_data *js_devdata = - container_of(timer, struct kbasep_js_device_data, gpu_metrics_timer); - struct kbase_device *kbdev = container_of(js_devdata, struct kbase_device, js_data); - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_gpu_metrics_emit_tracepoint(kbdev, ktime_get_raw_ns()); - WARN_ON_ONCE(!js_devdata->gpu_metrics_timer_running); - if (js_devdata->gpu_metrics_timer_needed) { - hrtimer_start(&js_devdata->gpu_metrics_timer, - HR_TIMER_DELAY_NSEC(kbase_gpu_metrics_get_tp_emit_interval()), - HRTIMER_MODE_REL); - } else - js_devdata->gpu_metrics_timer_running = false; - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return HRTIMER_NORESTART; -} - -/** - * gpu_metrics_ctx_init() - Take a reference on GPU metrics context if it exists, - * otherwise allocate and initialise one. - * - * @kctx: Pointer to the Kbase context. - * - * The GPU metrics context represents an "Application" for the purposes of GPU metrics - * reporting. There may be multiple kbase_contexts contributing data to a single GPU - * metrics context. - * This function takes a reference on GPU metrics context if it already exists - * corresponding to the Application that is creating the Kbase context, otherwise - * memory is allocated for it and initialised. - * - * Return: 0 on success, or negative on failure. - */ -static inline int gpu_metrics_ctx_init(struct kbase_context *kctx) -{ - struct kbase_gpu_metrics_ctx *gpu_metrics_ctx; - struct kbase_device *kbdev = kctx->kbdev; - unsigned long flags; - int ret = 0; - - const struct cred *cred = get_current_cred(); - const unsigned int aid = cred->euid.val; - - put_cred(cred); - - /* Return early if this is not a Userspace created context */ - if (unlikely(!kctx->filp)) - return 0; - - /* Serialize against the other threads trying to create/destroy Kbase contexts. */ - mutex_lock(&kbdev->kctx_list_lock); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - gpu_metrics_ctx = kbase_gpu_metrics_ctx_get(kbdev, aid); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (!gpu_metrics_ctx) { - gpu_metrics_ctx = kmalloc(sizeof(*gpu_metrics_ctx), GFP_KERNEL); - - if (gpu_metrics_ctx) { - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_gpu_metrics_ctx_init(kbdev, gpu_metrics_ctx, aid); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } else { - dev_err(kbdev->dev, "Allocation for gpu_metrics_ctx failed"); - ret = -ENOMEM; - } - } - - kctx->gpu_metrics_ctx = gpu_metrics_ctx; - mutex_unlock(&kbdev->kctx_list_lock); - - return ret; -} - -/** - * gpu_metrics_ctx_term() - Drop a reference on a GPU metrics context and free it - * if the refcount becomes 0. - * - * @kctx: Pointer to the Kbase context. - */ -static inline void gpu_metrics_ctx_term(struct kbase_context *kctx) -{ - unsigned long flags; - - /* Return early if this is not a Userspace created context */ - if (unlikely(!kctx->filp)) - return; - - /* Serialize against the other threads trying to create/destroy Kbase contexts. */ - mutex_lock(&kctx->kbdev->kctx_list_lock); - spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags); - kbase_gpu_metrics_ctx_put(kctx->kbdev, kctx->gpu_metrics_ctx); - spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); - mutex_unlock(&kctx->kbdev->kctx_list_lock); -} -#endif - -/** - * core_reqs_from_jsn_features - Convert JSn_FEATURES to core requirements - * @features: parsed JSn_FEATURE register value - * - * Given a JSn_FEATURE register value returns the core requirements that match - * - * Return: Core requirement bit mask - */ -static base_jd_core_req core_reqs_from_jsn_features(struct kbase_js_features_props *features) -{ - base_jd_core_req core_req = 0u; - - if (features->write_value) - core_req |= BASE_JD_REQ_V; - - if (features->cache_flush) - core_req |= BASE_JD_REQ_CF; - - if (features->compute_shader) - core_req |= BASE_JD_REQ_CS; - - if (features->tiler) - core_req |= BASE_JD_REQ_T; - - if (features->fragment_shader) - core_req |= BASE_JD_REQ_FS; - - return core_req; -} - -static void kbase_js_sync_timers(struct kbase_device *kbdev) -{ - mutex_lock(&kbdev->js_data.runpool_mutex); - kbase_backend_ctx_count_changed(kbdev); - mutex_unlock(&kbdev->js_data.runpool_mutex); -} - -/** - * jsctx_rb_none_to_pull_prio(): - Check if there are no pullable atoms - * @kctx: Pointer to kbase context with ring buffer. - * @js: Job slot id to check. - * @prio: Priority to check. - * - * Return true if there are no atoms to pull. There may be running atoms in the - * ring buffer even if there are no atoms to pull. It is also possible for the - * ring buffer to be full (with running atoms) when this functions returns - * true. - * - * Return: true if there are no atoms to pull, false otherwise. - */ -static inline bool jsctx_rb_none_to_pull_prio(struct kbase_context *kctx, unsigned int js, int prio) -{ - bool none_to_pull; - struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - none_to_pull = RB_EMPTY_ROOT(&rb->runnable_tree); - - dev_dbg(kctx->kbdev->dev, "Slot %u (prio %d) is %spullable in kctx %pK\n", js, prio, - none_to_pull ? "not " : "", kctx); - - return none_to_pull; -} - -/** - * jsctx_rb_none_to_pull(): - Check if all priority ring buffers have no - * pullable atoms - * @kctx: Pointer to kbase context with ring buffer. - * @js: Job slot id to check. - * - * Caller must hold hwaccess_lock - * - * Return: true if the ring buffers for all priorities have no pullable atoms, - * false otherwise. - */ -static inline bool jsctx_rb_none_to_pull(struct kbase_context *kctx, unsigned int js) -{ - int prio; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) { - if (!jsctx_rb_none_to_pull_prio(kctx, js, prio)) - return false; - } - - return true; -} - -/** - * jsctx_queue_foreach_prio(): - Execute callback for each entry in the queue. - * @kctx: Pointer to kbase context with the queue. - * @js: Job slot id to iterate. - * @prio: Priority id to iterate. - * @callback: Function pointer to callback. - * - * Iterate over a queue and invoke @callback for each entry in the queue, and - * remove the entry from the queue. - * - * If entries are added to the queue while this is running those entries may, or - * may not be covered. To ensure that all entries in the buffer have been - * enumerated when this function returns jsctx->lock must be held when calling - * this function. - * - * The HW access lock must always be held when calling this function. - */ -static void jsctx_queue_foreach_prio(struct kbase_context *kctx, unsigned int js, int prio, - kbasep_js_ctx_job_cb *callback) -{ - struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - while (!RB_EMPTY_ROOT(&queue->runnable_tree)) { - struct rb_node *node = rb_first(&queue->runnable_tree); - struct kbase_jd_atom *entry = - rb_entry(node, struct kbase_jd_atom, runnable_tree_node); - - rb_erase(node, &queue->runnable_tree); - callback(kctx->kbdev, entry); - } - - while (!list_empty(&queue->x_dep_head)) { - struct kbase_jd_atom *entry = - list_entry(queue->x_dep_head.next, struct kbase_jd_atom, queue); - - WARN_ON(!(entry->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST)); - dev_dbg(kctx->kbdev->dev, "Del blocked atom %pK from X_DEP list\n", (void *)entry); - - list_del(queue->x_dep_head.next); - entry->atom_flags &= ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST; - - callback(kctx->kbdev, entry); - } -} - -/** - * jsctx_queue_foreach(): - Execute callback for each entry in every queue - * @kctx: Pointer to kbase context with queue. - * @js: Job slot id to iterate. - * @callback: Function pointer to callback. - * - * Iterate over all the different priorities, and for each call - * jsctx_queue_foreach_prio() to iterate over the queue and invoke @callback - * for each entry, and remove the entry from the queue. - */ -static inline void jsctx_queue_foreach(struct kbase_context *kctx, unsigned int js, - kbasep_js_ctx_job_cb *callback) -{ - int prio; - - for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) - jsctx_queue_foreach_prio(kctx, js, prio, callback); -} - -/** - * jsctx_rb_peek_prio(): - Check buffer and get next atom - * @kctx: Pointer to kbase context with ring buffer. - * @js: Job slot id to check. - * @prio: Priority id to check. - * - * Check the ring buffer for the specified @js and @prio and return a pointer to - * the next atom, unless the ring buffer is empty. - * - * Return: Pointer to next atom in buffer, or NULL if there is no atom. - */ -static inline struct kbase_jd_atom *jsctx_rb_peek_prio(struct kbase_context *kctx, unsigned int js, - int prio) -{ - struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; - struct rb_node *node; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - dev_dbg(kctx->kbdev->dev, "Peeking runnable tree of kctx %pK for prio %d (s:%u)\n", - (void *)kctx, prio, js); - - node = rb_first(&rb->runnable_tree); - if (!node) { - dev_dbg(kctx->kbdev->dev, "Tree is empty\n"); - return NULL; - } - - return rb_entry(node, struct kbase_jd_atom, runnable_tree_node); -} - -/** - * jsctx_rb_peek(): - Check all priority buffers and get next atom - * @kctx: Pointer to kbase context with ring buffer. - * @js: Job slot id to check. - * - * Check the ring buffers for all priorities, starting from - * KBASE_JS_ATOM_SCHED_PRIO_REALTIME, for the specified @js and @prio and return a - * pointer to the next atom, unless all the priority's ring buffers are empty. - * - * Caller must hold the hwaccess_lock. - * - * Return: Pointer to next atom in buffer, or NULL if there is no atom. - */ -static inline struct kbase_jd_atom *jsctx_rb_peek(struct kbase_context *kctx, unsigned int js) -{ - int prio; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; prio++) { - struct kbase_jd_atom *katom; - - katom = jsctx_rb_peek_prio(kctx, js, prio); - if (katom) - return katom; - } - - return NULL; -} - -/** - * jsctx_rb_pull(): - Mark atom in list as running - * @kctx: Pointer to kbase context with ring buffer. - * @katom: Pointer to katom to pull. - * - * Mark an atom previously obtained from jsctx_rb_peek() as running. - * - * @katom must currently be at the head of the ring buffer. - */ -static inline void jsctx_rb_pull(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - int prio = katom->sched_priority; - unsigned int js = katom->slot_nr; - struct jsctx_queue *rb = &kctx->jsctx_queue[prio][js]; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - dev_dbg(kctx->kbdev->dev, "Erasing atom %pK from runnable tree of kctx %pK\n", - (void *)katom, (void *)kctx); - - /* Atoms must be pulled in the correct order. */ - WARN_ON(katom != jsctx_rb_peek_prio(kctx, js, prio)); - - rb_erase(&katom->runnable_tree_node, &rb->runnable_tree); -} - -static void jsctx_tree_add(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - struct kbase_device *kbdev = kctx->kbdev; - int prio = katom->sched_priority; - unsigned int js = katom->slot_nr; - struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; - struct rb_node **new = &(queue->runnable_tree.rb_node), *parent = NULL; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - dev_dbg(kbdev->dev, "Adding atom %pK to runnable tree of kctx %pK (s:%u)\n", (void *)katom, - (void *)kctx, js); - - while (*new) { - struct kbase_jd_atom *entry = - container_of(*new, struct kbase_jd_atom, runnable_tree_node); - - parent = *new; - if (kbase_jd_atom_is_younger(katom, entry)) - new = &((*new)->rb_left); - else - new = &((*new)->rb_right); - } - - /* Add new node and rebalance tree. */ - rb_link_node(&katom->runnable_tree_node, parent, new); - rb_insert_color(&katom->runnable_tree_node, &queue->runnable_tree); - - KBASE_TLSTREAM_TL_ATTRIB_ATOM_STATE(kbdev, katom, TL_ATOM_STATE_READY); -} - -/** - * jsctx_rb_unpull(): - Undo marking of atom in list as running - * @kctx: Pointer to kbase context with ring buffer. - * @katom: Pointer to katom to unpull. - * - * Undo jsctx_rb_pull() and put @katom back in the queue. - * - * jsctx_rb_unpull() must be called on atoms in the same order the atoms were - * pulled. - */ -static inline void jsctx_rb_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - KBASE_KTRACE_ADD_JM(kctx->kbdev, JS_UNPULL_JOB, kctx, katom, katom->jc, 0u); - - jsctx_tree_add(kctx, katom); -} - -static bool kbase_js_ctx_pullable(struct kbase_context *kctx, unsigned int js, bool is_scheduled); -static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js); -static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js); - -typedef bool(katom_ordering_func)(const struct kbase_jd_atom *, const struct kbase_jd_atom *); - -bool kbase_js_atom_runs_before(struct kbase_device *kbdev, const struct kbase_jd_atom *katom_a, - const struct kbase_jd_atom *katom_b, - const kbase_atom_ordering_flag_t order_flags) -{ - struct kbase_context *kctx_a = katom_a->kctx; - struct kbase_context *kctx_b = katom_b->kctx; - katom_ordering_func *samectxatomprio_ordering_func = kbase_jd_atom_is_younger; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (order_flags & KBASE_ATOM_ORDERING_FLAG_SEQNR) - samectxatomprio_ordering_func = kbase_jd_atom_is_earlier; - - /* It only makes sense to make this test for atoms on the same slot */ - WARN_ON(katom_a->slot_nr != katom_b->slot_nr); - - if (kbdev->js_ctx_scheduling_mode == KBASE_JS_PROCESS_LOCAL_PRIORITY_MODE) { - /* In local priority mode, querying either way around for "a - * should run before b" and "b should run before a" should - * always be false when they're from different contexts - */ - if (kctx_a != kctx_b) - return false; - } else { - /* In system priority mode, ordering is done first strictly by - * context priority, even when katom_b might be lower priority - * than katom_a. This is due to scheduling of contexts in order - * of highest priority first, regardless of whether the atoms - * for a particular slot from such contexts have the highest - * priority or not. - */ - if (kctx_a != kctx_b) { - if (kctx_a->priority < kctx_b->priority) - return true; - if (kctx_a->priority > kctx_b->priority) - return false; - } - } - - /* For same contexts/contexts with the same context priority (in system - * priority mode), ordering is next done by atom priority - */ - if (katom_a->sched_priority < katom_b->sched_priority) - return true; - if (katom_a->sched_priority > katom_b->sched_priority) - return false; - /* For atoms of same priority on the same kctx, they are - * ordered by seq_nr/age (dependent on caller) - */ - if (kctx_a == kctx_b && samectxatomprio_ordering_func(katom_a, katom_b)) - return true; - - return false; -} - -/* - * Functions private to KBase ('Protected' functions) - */ -int kbasep_js_devdata_init(struct kbase_device *const kbdev) -{ - struct kbasep_js_device_data *jsdd; - int i, j; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - - jsdd = &kbdev->js_data; - - INIT_LIST_HEAD(&jsdd->suspended_soft_jobs_list); - - /* Config attributes */ - jsdd->scheduling_period_ns = DEFAULT_JS_SCHEDULING_PERIOD_NS; - jsdd->soft_stop_ticks = DEFAULT_JS_SOFT_STOP_TICKS; - jsdd->soft_stop_ticks_cl = DEFAULT_JS_SOFT_STOP_TICKS_CL; - jsdd->hard_stop_ticks_ss = DEFAULT_JS_HARD_STOP_TICKS_SS; - jsdd->hard_stop_ticks_cl = DEFAULT_JS_HARD_STOP_TICKS_CL; - jsdd->hard_stop_ticks_dumping = DEFAULT_JS_HARD_STOP_TICKS_DUMPING; - jsdd->gpu_reset_ticks_ss = DEFAULT_JS_RESET_TICKS_SS; - jsdd->gpu_reset_ticks_cl = DEFAULT_JS_RESET_TICKS_CL; - - jsdd->gpu_reset_ticks_dumping = DEFAULT_JS_RESET_TICKS_DUMPING; - jsdd->ctx_timeslice_ns = DEFAULT_JS_CTX_TIMESLICE_NS; - atomic_set(&jsdd->soft_job_timeout_ms, DEFAULT_JS_SOFT_JOB_TIMEOUT); - jsdd->js_free_wait_time_ms = kbase_get_timeout_ms(kbdev, JM_DEFAULT_JS_FREE_TIMEOUT); - - dev_dbg(kbdev->dev, "JS Config Attribs: "); - dev_dbg(kbdev->dev, "\tscheduling_period_ns:%u", jsdd->scheduling_period_ns); - dev_dbg(kbdev->dev, "\tsoft_stop_ticks:%u", jsdd->soft_stop_ticks); - dev_dbg(kbdev->dev, "\tsoft_stop_ticks_cl:%u", jsdd->soft_stop_ticks_cl); - dev_dbg(kbdev->dev, "\thard_stop_ticks_ss:%u", jsdd->hard_stop_ticks_ss); - dev_dbg(kbdev->dev, "\thard_stop_ticks_cl:%u", jsdd->hard_stop_ticks_cl); - dev_dbg(kbdev->dev, "\thard_stop_ticks_dumping:%u", jsdd->hard_stop_ticks_dumping); - dev_dbg(kbdev->dev, "\tgpu_reset_ticks_ss:%u", jsdd->gpu_reset_ticks_ss); - dev_dbg(kbdev->dev, "\tgpu_reset_ticks_cl:%u", jsdd->gpu_reset_ticks_cl); - dev_dbg(kbdev->dev, "\tgpu_reset_ticks_dumping:%u", jsdd->gpu_reset_ticks_dumping); - dev_dbg(kbdev->dev, "\tctx_timeslice_ns:%u", jsdd->ctx_timeslice_ns); - dev_dbg(kbdev->dev, "\tsoft_job_timeout:%i", atomic_read(&jsdd->soft_job_timeout_ms)); - dev_dbg(kbdev->dev, "\tjs_free_wait_time_ms:%u", jsdd->js_free_wait_time_ms); - - if (!(jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_ss && - jsdd->hard_stop_ticks_ss < jsdd->gpu_reset_ticks_ss && - jsdd->soft_stop_ticks < jsdd->hard_stop_ticks_dumping && - jsdd->hard_stop_ticks_dumping < jsdd->gpu_reset_ticks_dumping)) { - dev_err(kbdev->dev, - "Job scheduler timeouts invalid; soft/hard/reset tick counts should be in increasing order\n"); - return -EINVAL; - } - -#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS - dev_dbg(kbdev->dev, - "Job Scheduling Soft-stops disabled, ignoring value for soft_stop_ticks==%u at %uns per tick. Other soft-stops may still occur.", - jsdd->soft_stop_ticks, jsdd->scheduling_period_ns); -#endif -#if KBASE_DISABLE_SCHEDULING_HARD_STOPS - dev_dbg(kbdev->dev, - "Job Scheduling Hard-stops disabled, ignoring values for hard_stop_ticks_ss==%d and hard_stop_ticks_dumping==%u at %uns per tick. Other hard-stops may still occur.", - jsdd->hard_stop_ticks_ss, jsdd->hard_stop_ticks_dumping, - jsdd->scheduling_period_ns); -#endif -#if KBASE_DISABLE_SCHEDULING_SOFT_STOPS && KBASE_DISABLE_SCHEDULING_HARD_STOPS - dev_dbg(kbdev->dev, - "Note: The JS tick timer (if coded) will still be run, but do nothing."); -#endif - - for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) - jsdd->js_reqs[i] = core_reqs_from_jsn_features(&kbdev->gpu_props.js_features[i]); - - /* On error, we could continue on: providing none of the below resources - * rely on the ones above - */ - - mutex_init(&jsdd->runpool_mutex); - mutex_init(&jsdd->queue_mutex); - sema_init(&jsdd->schedule_sem, 1); - - for (i = 0; i < kbdev->gpu_props.num_job_slots; ++i) { - for (j = KBASE_JS_ATOM_SCHED_PRIO_FIRST; j < KBASE_JS_ATOM_SCHED_PRIO_COUNT; ++j) { - INIT_LIST_HEAD(&jsdd->ctx_list_pullable[i][j]); - INIT_LIST_HEAD(&jsdd->ctx_list_unpullable[i][j]); - } - } - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - hrtimer_init(&jsdd->gpu_metrics_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - jsdd->gpu_metrics_timer.function = gpu_metrics_timer_callback; - jsdd->gpu_metrics_timer_needed = false; - jsdd->gpu_metrics_timer_running = false; -#endif - - return 0; -} - -void kbasep_js_devdata_halt(struct kbase_device *kbdev) -{ - CSTD_UNUSED(kbdev); -} - -void kbasep_js_devdata_term(struct kbase_device *kbdev) -{ - struct kbasep_js_device_data *js_devdata; - s8 zero_ctx_attr_ref_count[KBASEP_JS_CTX_ATTR_COUNT] = { - 0, - }; - CSTD_UNUSED(js_devdata); - - KBASE_DEBUG_ASSERT(kbdev != NULL); - - js_devdata = &kbdev->js_data; - - /* The caller must de-register all contexts before calling this - */ - KBASE_DEBUG_ASSERT(js_devdata->nr_all_contexts_running == 0); - KBASE_DEBUG_ASSERT(memcmp(js_devdata->runpool_irq.ctx_attr_ref_count, - zero_ctx_attr_ref_count, sizeof(zero_ctx_attr_ref_count)) == 0); - CSTD_UNUSED(zero_ctx_attr_ref_count); - -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - js_devdata->gpu_metrics_timer_needed = false; - hrtimer_cancel(&js_devdata->gpu_metrics_timer); -#endif -} - -int kbasep_js_kctx_init(struct kbase_context *const kctx) -{ - struct kbasep_js_kctx_info *js_kctx_info; - int i, j; - int ret; - CSTD_UNUSED(js_kctx_info); - - KBASE_DEBUG_ASSERT(kctx != NULL); - - CSTD_UNUSED(ret); -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - ret = gpu_metrics_ctx_init(kctx); - if (ret) - return ret; -#endif - - for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i) - INIT_LIST_HEAD(&kctx->jctx.sched_info.ctx.ctx_list_entry[i]); - - js_kctx_info = &kctx->jctx.sched_info; - - kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); - kbase_ctx_flag_clear(kctx, KCTX_DYING); - - /* Initially, the context is disabled from submission until the create - * flags are set - */ - kbase_ctx_flag_set(kctx, KCTX_SUBMIT_DISABLED); - - /* On error, we could continue on: providing none of the below resources - * rely on the ones above - */ - mutex_init(&js_kctx_info->ctx.jsctx_mutex); - - init_waitqueue_head(&js_kctx_info->ctx.is_scheduled_wait); - - for (i = KBASE_JS_ATOM_SCHED_PRIO_FIRST; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) { - for (j = 0; j < BASE_JM_MAX_NR_SLOTS; j++) { - INIT_LIST_HEAD(&kctx->jsctx_queue[i][j].x_dep_head); - kctx->jsctx_queue[i][j].runnable_tree = RB_ROOT; - } - } - - return 0; -} - -void kbasep_js_kctx_term(struct kbase_context *kctx) -{ - struct kbase_device *kbdev; - struct kbasep_js_kctx_info *js_kctx_info; - unsigned int js; - bool update_ctx_count = false; - unsigned long flags; - CSTD_UNUSED(js_kctx_info); - - KBASE_DEBUG_ASSERT(kctx != NULL); - - kbdev = kctx->kbdev; - KBASE_DEBUG_ASSERT(kbdev != NULL); - - js_kctx_info = &kctx->jctx.sched_info; - - /* The caller must de-register all jobs before calling this */ - KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs == 0); - - mutex_lock(&kbdev->js_data.queue_mutex); - mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)) { - WARN_ON(atomic_read(&kbdev->js_data.nr_contexts_runnable) <= 0); - atomic_dec(&kbdev->js_data.nr_contexts_runnable); - update_ctx_count = true; - kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); - } - - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - mutex_unlock(&kbdev->js_data.queue_mutex); - - if (update_ctx_count) { - mutex_lock(&kbdev->js_data.runpool_mutex); - kbase_backend_ctx_count_changed(kbdev); - mutex_unlock(&kbdev->js_data.runpool_mutex); - } - - kbase_ctx_sched_remove_ctx(kctx); -#if IS_ENABLED(CONFIG_MALI_VALHALL_TRACE_POWER_GPU_WORK_PERIOD) - gpu_metrics_ctx_term(kctx); -#endif -} - -/* - * Priority blocking management functions - */ - -/* Should not normally use directly - use kbase_jsctx_slot_atom_pulled_dec() instead */ -static void kbase_jsctx_slot_prio_blocked_clear(struct kbase_context *kctx, unsigned int js, - int sched_prio) -{ - struct kbase_jsctx_slot_tracking *slot_tracking = &kctx->slot_tracking[js]; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - slot_tracking->blocked &= ~(((kbase_js_prio_bitmap_t)1) << sched_prio); - KBASE_KTRACE_ADD_JM_SLOT_INFO(kctx->kbdev, JS_SLOT_PRIO_UNBLOCKED, kctx, NULL, 0, js, - (unsigned int)sched_prio); -} - -static int kbase_jsctx_slot_atoms_pulled(struct kbase_context *kctx, unsigned int js) -{ - return atomic_read(&kctx->slot_tracking[js].atoms_pulled); -} - -/* - * A priority level on a slot is blocked when: - * - that priority level is blocked - * - or, any higher priority level is blocked - */ -static bool kbase_jsctx_slot_prio_is_blocked(struct kbase_context *kctx, unsigned int js, - int sched_prio) -{ - struct kbase_jsctx_slot_tracking *slot_tracking = &kctx->slot_tracking[js]; - kbase_js_prio_bitmap_t prio_bit, higher_prios_mask; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - /* done in two separate shifts to prevent future undefined behavior - * should the number of priority levels == (bit width of the type) - */ - prio_bit = (((kbase_js_prio_bitmap_t)1) << sched_prio); - /* all bits of sched_prio or higher, with sched_prio = 0 being the - * highest priority - */ - higher_prios_mask = (prio_bit << 1u) - 1u; - return (slot_tracking->blocked & higher_prios_mask) != 0u; -} - -/** - * kbase_jsctx_slot_atom_pulled_inc - Increase counts of atoms that have being - * pulled for a slot from a ctx, based on - * this atom - * @kctx: kbase context - * @katom: atom pulled - * - * Manages counts of atoms pulled (including per-priority-level counts), for - * later determining when a ctx can become unblocked on a slot. - * - * Once a slot has been blocked at @katom's priority level, it should not be - * pulled from, hence this function should not be called in that case. - * - * The return value is to aid tracking of when @kctx becomes runnable. - * - * Return: new total count of atoms pulled from all slots on @kctx - */ -static int kbase_jsctx_slot_atom_pulled_inc(struct kbase_context *kctx, - const struct kbase_jd_atom *katom) -{ - unsigned int js = katom->slot_nr; - int sched_prio = katom->sched_priority; - struct kbase_jsctx_slot_tracking *slot_tracking = &kctx->slot_tracking[js]; - int nr_atoms_pulled; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - WARN(kbase_jsctx_slot_prio_is_blocked(kctx, js, sched_prio), - "Should not have pulled atoms for slot %u from a context that is blocked at priority %d or higher", - js, sched_prio); - - nr_atoms_pulled = atomic_inc_return(&kctx->atoms_pulled_all_slots); - atomic_inc(&slot_tracking->atoms_pulled); - slot_tracking->atoms_pulled_pri[sched_prio]++; - - return nr_atoms_pulled; -} - -/** - * kbase_jsctx_slot_atom_pulled_dec- Decrease counts of atoms that have being - * pulled for a slot from a ctx, and - * re-evaluate whether a context is blocked - * on this slot - * @kctx: kbase context - * @katom: atom that has just been removed from a job slot - * - * @kctx can become unblocked on a slot for a priority level when it no longer - * has any pulled atoms at that priority level on that slot, and all higher - * (numerically lower) priority levels are also unblocked @kctx on that - * slot. The latter condition is to retain priority ordering within @kctx. - * - * Return: true if the slot was previously blocked but has now become unblocked - * at @katom's priority level, false otherwise. - */ -static bool kbase_jsctx_slot_atom_pulled_dec(struct kbase_context *kctx, - const struct kbase_jd_atom *katom) -{ - unsigned int js = katom->slot_nr; - int sched_prio = katom->sched_priority; - int atoms_pulled_pri; - struct kbase_jsctx_slot_tracking *slot_tracking = &kctx->slot_tracking[js]; - bool slot_prio_became_unblocked = false; - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - atomic_dec(&kctx->atoms_pulled_all_slots); - atomic_dec(&slot_tracking->atoms_pulled); - - atoms_pulled_pri = --(slot_tracking->atoms_pulled_pri[sched_prio]); - - /* We can safely clear this priority level's blocked status even if - * higher priority levels are still blocked: a subsequent query to - * kbase_jsctx_slot_prio_is_blocked() will still return true - */ - if (!atoms_pulled_pri && kbase_jsctx_slot_prio_is_blocked(kctx, js, sched_prio)) { - kbase_jsctx_slot_prio_blocked_clear(kctx, js, sched_prio); - - if (!kbase_jsctx_slot_prio_is_blocked(kctx, js, sched_prio)) - slot_prio_became_unblocked = true; - } - - if (slot_prio_became_unblocked) - KBASE_KTRACE_ADD_JM_SLOT_INFO(kctx->kbdev, JS_SLOT_PRIO_AND_HIGHER_UNBLOCKED, kctx, - katom, katom->jc, js, (unsigned int)sched_prio); - - return slot_prio_became_unblocked; -} - -/** - * kbase_js_ctx_list_add_pullable_nolock - Variant of - * kbase_jd_ctx_list_add_pullable() - * where the caller must hold - * hwaccess_lock - * @kbdev: Device pointer - * @kctx: Context to add to queue - * @js: Job slot to use - * - * Caller must hold hwaccess_lock - * - * Return: true if caller should call kbase_backend_ctx_count_changed() - */ -static bool kbase_js_ctx_list_add_pullable_nolock(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js) -{ - bool ret = false; - - lockdep_assert_held(&kbdev->hwaccess_lock); - dev_dbg(kbdev->dev, "Add pullable tail kctx %pK (s:%u)\n", (void *)kctx, js); - - if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])) - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - - list_add_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], - &kbdev->js_data.ctx_list_pullable[js][kctx->priority]); - - if (!kctx->slots_pullable) { - kbdev->js_data.nr_contexts_pullable++; - ret = true; - if (!kbase_jsctx_atoms_pulled(kctx)) { - WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); - atomic_inc(&kbdev->js_data.nr_contexts_runnable); - } - } - kctx->slots_pullable |= (1UL << js); - - return ret; -} - -/** - * kbase_js_ctx_list_add_pullable_head_nolock - Variant of - * kbase_js_ctx_list_add_pullable_head() - * where the caller must hold - * hwaccess_lock - * @kbdev: Device pointer - * @kctx: Context to add to queue - * @js: Job slot to use - * - * Caller must hold hwaccess_lock - * - * Return: true if caller should call kbase_backend_ctx_count_changed() - */ -static bool kbase_js_ctx_list_add_pullable_head_nolock(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js) -{ - bool ret = false; - - lockdep_assert_held(&kbdev->hwaccess_lock); - dev_dbg(kbdev->dev, "Add pullable head kctx %pK (s:%u)\n", (void *)kctx, js); - - if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])) - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - - list_add(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], - &kbdev->js_data.ctx_list_pullable[js][kctx->priority]); - - if (!kctx->slots_pullable) { - kbdev->js_data.nr_contexts_pullable++; - ret = true; - if (!kbase_jsctx_atoms_pulled(kctx)) { - WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); - atomic_inc(&kbdev->js_data.nr_contexts_runnable); - } - } - kctx->slots_pullable |= (1UL << js); - - return ret; -} - -/** - * kbase_js_ctx_list_add_pullable_head - Add context to the head of the - * per-slot pullable context queue - * @kbdev: Device pointer - * @kctx: Context to add to queue - * @js: Job slot to use - * - * If the context is on either the pullable or unpullable queues, then it is - * removed before being added to the head. - * - * This function should be used when a context has been scheduled, but no jobs - * can currently be pulled from it. - * - * Return: true if caller should call kbase_backend_ctx_count_changed() - */ -static bool kbase_js_ctx_list_add_pullable_head(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js) -{ - bool ret; - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - ret = kbase_js_ctx_list_add_pullable_head_nolock(kbdev, kctx, js); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return ret; -} - -/** - * kbase_js_ctx_list_add_unpullable_nolock - Add context to the tail of the - * per-slot unpullable context queue - * @kbdev: Device pointer - * @kctx: Context to add to queue - * @js: Job slot to use - * - * The context must already be on the per-slot pullable queue. It will be - * removed from the pullable queue before being added to the unpullable queue. - * - * This function should be used when a context has been pulled from, and there - * are no jobs remaining on the specified slot. - * - * Caller must hold hwaccess_lock - * - * Return: true if caller should call kbase_backend_ctx_count_changed() - */ -static bool kbase_js_ctx_list_add_unpullable_nolock(struct kbase_device *kbdev, - struct kbase_context *kctx, unsigned int js) -{ - bool ret = false; - - lockdep_assert_held(&kbdev->hwaccess_lock); - dev_dbg(kbdev->dev, "Add unpullable tail kctx %pK (s:%u)\n", (void *)kctx, js); - - list_move_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], - &kbdev->js_data.ctx_list_unpullable[js][kctx->priority]); - - if (kctx->slots_pullable == (1UL << js)) { - kbdev->js_data.nr_contexts_pullable--; - ret = true; - if (!kbase_jsctx_atoms_pulled(kctx)) { - WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); - atomic_dec(&kbdev->js_data.nr_contexts_runnable); - } - } - kctx->slots_pullable &= ~(1UL << js); - - return ret; -} - -/** - * kbase_js_ctx_list_remove_nolock - Remove context from the per-slot pullable - * or unpullable context queues - * @kbdev: Device pointer - * @kctx: Context to remove from queue - * @js: Job slot to use - * - * The context must already be on one of the queues. - * - * This function should be used when a context has no jobs on the GPU, and no - * jobs remaining for the specified slot. - * - * Caller must hold hwaccess_lock - * - * Return: true if caller should call kbase_backend_ctx_count_changed() - */ -static bool kbase_js_ctx_list_remove_nolock(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js) -{ - bool ret = false; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - WARN_ON(list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])); - - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - - if (kctx->slots_pullable == (1UL << js)) { - kbdev->js_data.nr_contexts_pullable--; - ret = true; - if (!kbase_jsctx_atoms_pulled(kctx)) { - WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); - atomic_dec(&kbdev->js_data.nr_contexts_runnable); - } - } - kctx->slots_pullable &= ~(1UL << js); - - return ret; -} - -/** - * kbase_js_ctx_list_pop_head_nolock - Variant of kbase_js_ctx_list_pop_head() - * where the caller must hold - * hwaccess_lock - * @kbdev: Device pointer - * @js: Job slot to use - * - * Caller must hold hwaccess_lock - * - * Return: Context to use for specified slot. - * NULL if no contexts present for specified slot - */ -static struct kbase_context *kbase_js_ctx_list_pop_head_nolock(struct kbase_device *kbdev, - unsigned int js) -{ - struct kbase_context *kctx; - int i; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - for (i = KBASE_JS_ATOM_SCHED_PRIO_FIRST; i < KBASE_JS_ATOM_SCHED_PRIO_COUNT; i++) { - if (list_empty(&kbdev->js_data.ctx_list_pullable[js][i])) - continue; - - kctx = list_entry(kbdev->js_data.ctx_list_pullable[js][i].next, - struct kbase_context, jctx.sched_info.ctx.ctx_list_entry[js]); - - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - dev_dbg(kbdev->dev, "Popped %pK from the pullable queue (s:%u)\n", (void *)kctx, - js); - return kctx; - } - return NULL; -} - -/** - * kbase_js_ctx_list_pop_head - Pop the head context off the per-slot pullable - * queue. - * @kbdev: Device pointer - * @js: Job slot to use - * - * Return: Context to use for specified slot. - * NULL if no contexts present for specified slot - */ -static struct kbase_context *kbase_js_ctx_list_pop_head(struct kbase_device *kbdev, unsigned int js) -{ - struct kbase_context *kctx; - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kctx = kbase_js_ctx_list_pop_head_nolock(kbdev, js); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return kctx; -} - -/** - * kbase_js_ctx_pullable - Return if a context can be pulled from on the - * specified slot - * @kctx: Context pointer - * @js: Job slot to use - * @is_scheduled: true if the context is currently scheduled - * - * Caller must hold hwaccess_lock - * - * Return: true if context can be pulled from on specified slot - * false otherwise - */ -static bool kbase_js_ctx_pullable(struct kbase_context *kctx, unsigned int js, bool is_scheduled) -{ - struct kbasep_js_device_data *js_devdata; - struct kbase_jd_atom *katom; - struct kbase_device *kbdev = kctx->kbdev; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - js_devdata = &kbdev->js_data; - - if (is_scheduled) { - if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) { - dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %pK\n", (void *)kctx); - return false; - } - } - katom = jsctx_rb_peek(kctx, js); - if (!katom) { - dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %pK (s:%u)\n", (void *)kctx, js); - return false; /* No pullable atoms */ - } - if (kbase_jsctx_slot_prio_is_blocked(kctx, js, katom->sched_priority)) { - KBASE_KTRACE_ADD_JM_SLOT_INFO(kctx->kbdev, JS_SLOT_PRIO_IS_BLOCKED, kctx, katom, - katom->jc, js, (unsigned int)katom->sched_priority); - dev_dbg(kbdev->dev, - "JS: kctx %pK is blocked from submitting atoms at priority %d and lower (s:%u)\n", - (void *)kctx, katom->sched_priority, js); - return false; - } - if (atomic_read(&katom->blocked)) { - dev_dbg(kbdev->dev, "JS: Atom %pK is blocked in js_ctx_pullable\n", (void *)katom); - return false; /* next atom blocked */ - } - if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) { - if (katom->x_pre_dep->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB || - katom->x_pre_dep->will_fail_event_code) { - dev_dbg(kbdev->dev, - "JS: X pre-dep %pK is not present in slot FIFO or will fail\n", - (void *)katom->x_pre_dep); - return false; - } - if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) && - kbase_backend_nr_atoms_on_slot(kctx->kbdev, js)) { - dev_dbg(kbdev->dev, - "JS: Atom %pK has cross-slot fail dependency and atoms on slot (s:%u)\n", - (void *)katom, js); - return false; - } - } - - dev_dbg(kbdev->dev, "JS: Atom %pK is pullable in kctx %pK (s:%u)\n", (void *)katom, - (void *)kctx, js); - - return true; -} - -static bool kbase_js_dep_validate(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - struct kbase_device *kbdev = kctx->kbdev; - bool ret = true; - bool has_dep = false, has_x_dep = false; - unsigned int js = kbase_js_get_slot(kbdev, katom); - int prio = katom->sched_priority; - int i; - - for (i = 0; i < 2; i++) { - struct kbase_jd_atom *dep_atom = katom->dep[i].atom; - - if (dep_atom) { - unsigned int dep_js = kbase_js_get_slot(kbdev, dep_atom); - int dep_prio = dep_atom->sched_priority; - - dev_dbg(kbdev->dev, "Checking dep %d of atom %pK (s:%d) on %pK (s:%d)\n", i, - (void *)katom, js, (void *)dep_atom, dep_js); - - /* Dependent atom must already have been submitted */ - if (!(dep_atom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE)) { - dev_dbg(kbdev->dev, "Blocker not submitted yet\n"); - ret = false; - break; - } - - /* Dependencies with different priorities can't - * be represented in the ringbuffer - */ - if (prio != dep_prio) { - dev_dbg(kbdev->dev, "Different atom priorities\n"); - ret = false; - break; - } - - if (js == dep_js) { - /* Only one same-slot dependency can be - * represented in the ringbuffer - */ - if (has_dep) { - dev_dbg(kbdev->dev, "Too many same-slot deps\n"); - ret = false; - break; - } - /* Each dependee atom can only have one - * same-slot dependency - */ - if (dep_atom->post_dep) { - dev_dbg(kbdev->dev, "Too many same-slot successors\n"); - ret = false; - break; - } - has_dep = true; - } else { - /* Only one cross-slot dependency can be - * represented in the ringbuffer - */ - if (has_x_dep) { - dev_dbg(kbdev->dev, "Too many cross-slot deps\n"); - ret = false; - break; - } - /* Each dependee atom can only have one - * cross-slot dependency - */ - if (dep_atom->x_post_dep) { - dev_dbg(kbdev->dev, "Too many cross-slot successors\n"); - ret = false; - break; - } - /* The dependee atom can not already be in the - * HW access ringbuffer - */ - if (dep_atom->gpu_rb_state != KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB) { - dev_dbg(kbdev->dev, - "Blocker already in ringbuffer (state:%d)\n", - dep_atom->gpu_rb_state); - ret = false; - break; - } - /* The dependee atom can not already have - * completed - */ - if (dep_atom->status != KBASE_JD_ATOM_STATE_IN_JS) { - dev_dbg(kbdev->dev, - "Blocker already completed (status:%d)\n", - dep_atom->status); - ret = false; - break; - } - - has_x_dep = true; - } - - /* Dependency can be represented in ringbuffers */ - } - } - - /* If dependencies can be represented by ringbuffer then clear them from - * atom structure - */ - if (ret) { - for (i = 0; i < 2; i++) { - struct kbase_jd_atom *dep_atom = katom->dep[i].atom; - - if (dep_atom) { - unsigned int dep_js = kbase_js_get_slot(kbdev, dep_atom); - - dev_dbg(kbdev->dev, - "Clearing dep %d of atom %pK (s:%d) on %pK (s:%d)\n", i, - (void *)katom, js, (void *)dep_atom, dep_js); - - if ((js != dep_js) && - (dep_atom->status != KBASE_JD_ATOM_STATE_COMPLETED) && - (dep_atom->status != KBASE_JD_ATOM_STATE_HW_COMPLETED) && - (dep_atom->status != KBASE_JD_ATOM_STATE_UNUSED)) { - katom->atom_flags |= KBASE_KATOM_FLAG_X_DEP_BLOCKED; - - katom->x_pre_dep = dep_atom; - dep_atom->x_post_dep = katom; - if (kbase_jd_katom_dep_type(&katom->dep[i]) == - BASE_JD_DEP_TYPE_DATA) - katom->atom_flags |= KBASE_KATOM_FLAG_FAIL_BLOCKER; - } - if ((kbase_jd_katom_dep_type(&katom->dep[i]) == - BASE_JD_DEP_TYPE_DATA) && - (js == dep_js)) { - katom->pre_dep = dep_atom; - dep_atom->post_dep = katom; - } - - list_del(&katom->dep_item[i]); - kbase_jd_katom_dep_clear(&katom->dep[i]); - } - } - } else { - dev_dbg(kbdev->dev, "Deps of atom %pK (s:%d) could not be represented\n", - (void *)katom, js); - } - - return ret; -} - -void kbase_js_set_ctx_priority(struct kbase_context *kctx, int new_priority) -{ - struct kbase_device *kbdev = kctx->kbdev; - unsigned int js; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - /* Move kctx to the pullable/upullable list as per the new priority */ - if (new_priority != kctx->priority) { - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - if (kctx->slots_pullable & (1UL << js)) - list_move_tail(&kctx->jctx.sched_info.ctx.ctx_list_entry[js], - &kbdev->js_data.ctx_list_pullable[js][new_priority]); - else - list_move_tail( - &kctx->jctx.sched_info.ctx.ctx_list_entry[js], - &kbdev->js_data.ctx_list_unpullable[js][new_priority]); - } - - kctx->priority = new_priority; - } -} - -void kbase_js_update_ctx_priority(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - int new_priority = KBASE_JS_ATOM_SCHED_PRIO_LOW; - int prio; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (kbdev->js_ctx_scheduling_mode == KBASE_JS_SYSTEM_PRIORITY_MODE) { - /* Determine the new priority for context, as per the priority - * of currently in-use atoms. - */ - for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; - prio++) { - if (kctx->atoms_count[prio]) { - new_priority = prio; - break; - } - } - } - - kbase_js_set_ctx_priority(kctx, new_priority); -} -KBASE_EXPORT_TEST_API(kbase_js_update_ctx_priority); - -bool kbasep_js_add_job(struct kbase_context *kctx, struct kbase_jd_atom *atom) -{ - unsigned long flags; - struct kbasep_js_kctx_info *js_kctx_info; - struct kbase_device *kbdev; - struct kbasep_js_device_data *js_devdata; - - bool enqueue_required = false; - bool timer_sync = false; - - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(atom != NULL); - lockdep_assert_held(&kctx->jctx.lock); - - kbdev = kctx->kbdev; - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - - /* - * Begin Runpool transaction - */ - mutex_lock(&js_devdata->runpool_mutex); - - /* Refcount ctx.nr_jobs */ - KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs < U32_MAX); - ++(js_kctx_info->ctx.nr_jobs); - dev_dbg(kbdev->dev, "Add atom %pK to kctx %pK; now %d in ctx\n", (void *)atom, (void *)kctx, - js_kctx_info->ctx.nr_jobs); - - /* Lock for state available during IRQ */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - if (++kctx->atoms_count[atom->sched_priority] == 1) - kbase_js_update_ctx_priority(kctx); - - if (!kbase_js_dep_validate(kctx, atom)) { - /* Dependencies could not be represented */ - --(js_kctx_info->ctx.nr_jobs); - dev_dbg(kbdev->dev, "Remove atom %pK from kctx %pK; now %d in ctx\n", (void *)atom, - (void *)kctx, js_kctx_info->ctx.nr_jobs); - - /* Setting atom status back to queued as it still has unresolved - * dependencies - */ - atom->status = KBASE_JD_ATOM_STATE_QUEUED; - dev_dbg(kbdev->dev, "Atom %pK status to queued\n", (void *)atom); - - /* Undo the count, as the atom will get added again later but - * leave the context priority adjusted or boosted, in case if - * this was the first higher priority atom received for this - * context. - * This will prevent the scenario of priority inversion, where - * another context having medium priority atoms keeps getting - * scheduled over this context, which is having both lower and - * higher priority atoms, but higher priority atoms are blocked - * due to dependency on lower priority atoms. With priority - * boost the high priority atom will get to run at earliest. - */ - kctx->atoms_count[atom->sched_priority]--; - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_devdata->runpool_mutex); - - goto out_unlock; - } - - enqueue_required = kbase_js_dep_resolved_submit(kctx, atom); - - KBASE_KTRACE_ADD_JM_REFCOUNT(kbdev, JS_ADD_JOB, kctx, atom, atom->jc, - kbase_ktrace_get_ctx_refcnt(kctx)); - - /* Context Attribute Refcounting */ - kbasep_js_ctx_attr_ctx_retain_atom(kbdev, kctx, atom); - - if (enqueue_required) { - if (kbase_js_ctx_pullable(kctx, atom->slot_nr, false)) - timer_sync = - kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, atom->slot_nr); - else - timer_sync = - kbase_js_ctx_list_add_unpullable_nolock(kbdev, kctx, atom->slot_nr); - } - /* If this context is active and the atom is the first on its slot, - * kick the job manager to attempt to fast-start the atom - */ - if (enqueue_required && kctx == kbdev->hwaccess.active_kctx[atom->slot_nr]) - kbase_jm_try_kick(kbdev, 1UL << atom->slot_nr); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - if (timer_sync) - kbase_backend_ctx_count_changed(kbdev); - mutex_unlock(&js_devdata->runpool_mutex); - /* End runpool transaction */ - - if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) { - if (kbase_ctx_flag(kctx, KCTX_DYING)) { - /* A job got added while/after kbase_job_zap_context() - * was called on a non-scheduled context. Kill that job - * by killing the context. - */ - kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, false); - } else if (js_kctx_info->ctx.nr_jobs == 1) { - /* Handle Refcount going from 0 to 1: schedule the - * context on the Queue - */ - KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - dev_dbg(kbdev->dev, "JS: Enqueue Context %pK", kctx); - - /* Queue was updated - caller must try to schedule the - * head context - */ - WARN_ON(!enqueue_required); - } - } -out_unlock: - dev_dbg(kbdev->dev, "Enqueue of kctx %pK is %srequired\n", kctx, - enqueue_required ? "" : "not "); - - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - mutex_unlock(&js_devdata->queue_mutex); - - return enqueue_required; -} - -void kbasep_js_remove_job(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *atom) -{ - struct kbasep_js_kctx_info *js_kctx_info; - unsigned long flags; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(atom != NULL); - - js_kctx_info = &kctx->jctx.sched_info; - - KBASE_KTRACE_ADD_JM_REFCOUNT(kbdev, JS_REMOVE_JOB, kctx, atom, atom->jc, - kbase_ktrace_get_ctx_refcnt(kctx)); - - /* De-refcount ctx.nr_jobs */ - KBASE_DEBUG_ASSERT(js_kctx_info->ctx.nr_jobs > 0); - --(js_kctx_info->ctx.nr_jobs); - dev_dbg(kbdev->dev, "Remove atom %pK from kctx %pK; now %d in ctx\n", (void *)atom, - (void *)kctx, js_kctx_info->ctx.nr_jobs); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - if (--kctx->atoms_count[atom->sched_priority] == 0) - kbase_js_update_ctx_priority(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -} - -bool kbasep_js_remove_cancelled_job(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *katom) -{ - unsigned long flags; - struct kbasep_js_atom_retained_state katom_retained_state; - bool attr_state_changed; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(katom != NULL); - - kbasep_js_atom_retained_state_copy(&katom_retained_state, katom); - kbasep_js_remove_job(kbdev, kctx, katom); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* The atom has 'finished' (will not be re-run), so no need to call - * kbasep_js_has_atom_finished(). - * - * This is because it returns false for soft-stopped atoms, but we - * want to override that, because we're cancelling an atom regardless of - * whether it was soft-stopped or not - */ - attr_state_changed = - kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, &katom_retained_state); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - return attr_state_changed; -} - -/** - * kbasep_js_run_jobs_after_ctx_and_atom_release - Try running more jobs after - * releasing a context and/or atom - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * @katom_retained_state: Retained state from the atom - * @runpool_ctx_attr_change: True if the runpool context attributes have changed - * - * This collates a set of actions that must happen whilst hwaccess_lock is held. - * - * This includes running more jobs when: - * - The previously released kctx caused a ctx attribute change, - * - The released atom caused a ctx attribute change, - * - Slots were previously blocked due to affinity restrictions, - * - Submission during IRQ handling failed. - * - * Return: %KBASEP_JS_RELEASE_RESULT_SCHED_ALL if context attributes were - * changed. The caller should try scheduling all contexts - */ -static kbasep_js_release_result kbasep_js_run_jobs_after_ctx_and_atom_release( - struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state, bool runpool_ctx_attr_change) -{ - struct kbasep_js_device_data *js_devdata; - kbasep_js_release_result result = 0; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(katom_retained_state != NULL); - js_devdata = &kbdev->js_data; - - lockdep_assert_held(&kctx->jctx.sched_info.ctx.jsctx_mutex); - lockdep_assert_held(&js_devdata->runpool_mutex); - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (js_devdata->nr_user_contexts_running != 0 && runpool_ctx_attr_change) { - /* A change in runpool ctx attributes might mean we can - * run more jobs than before - */ - result = KBASEP_JS_RELEASE_RESULT_SCHED_ALL; - - KBASE_KTRACE_ADD_JM_SLOT(kbdev, JD_DONE_TRY_RUN_NEXT_JOB, kctx, NULL, 0u, 0); - } - return result; -} - -/** - * kbasep_js_runpool_release_ctx_internal - Internal function to release the reference - * on a ctx and an atom's "retained state", only - * taking the runpool and as transaction mutexes - * @kbdev: The kbase_device to operate on - * @kctx: The kbase_context to operate on - * @katom_retained_state: Retained state from the atom - * - * This also starts more jobs running in the case of an ctx-attribute state change - * - * This does none of the followup actions for scheduling: - * - It does not schedule in a new context - * - It does not requeue or handle dying contexts - * - * For those tasks, just call kbasep_js_runpool_release_ctx() instead - * - * Has following requirements - * - Context is scheduled in, and kctx->as_nr matches kctx_as_nr - * - Context has a non-zero refcount - * - Caller holds js_kctx_info->ctx.jsctx_mutex - * - Caller holds js_devdata->runpool_mutex - * - * Return: A bitpattern, containing KBASEP_JS_RELEASE_RESULT_* flags, indicating - * the result of releasing a context that whether the caller should try - * scheduling a new context or should try scheduling all contexts. - */ -static kbasep_js_release_result -kbasep_js_runpool_release_ctx_internal(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state) -{ - unsigned long flags; - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - - kbasep_js_release_result release_result = 0u; - bool runpool_ctx_attr_change = false; - int kctx_as_nr; - int new_ref_count; - CSTD_UNUSED(kctx_as_nr); - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - js_kctx_info = &kctx->jctx.sched_info; - js_devdata = &kbdev->js_data; - - /* Ensure context really is scheduled in */ - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - kctx_as_nr = kctx->as_nr; - KBASE_DEBUG_ASSERT(kctx_as_nr != KBASEP_AS_NR_INVALID); - KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0); - - /* - * Transaction begins on AS and runpool_irq - * - * Assert about out calling contract - */ - mutex_lock(&kbdev->pm.lock); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - KBASE_DEBUG_ASSERT(kctx_as_nr == kctx->as_nr); - KBASE_DEBUG_ASSERT(atomic_read(&kctx->refcount) > 0); - - /* Update refcount */ - kbase_ctx_sched_release_ctx(kctx); - new_ref_count = atomic_read(&kctx->refcount); - - /* Release the atom if it finished (i.e. wasn't soft-stopped) */ - if (kbasep_js_has_atom_finished(katom_retained_state)) - runpool_ctx_attr_change |= - kbasep_js_ctx_attr_ctx_release_atom(kbdev, kctx, katom_retained_state); - - if (new_ref_count == 2 && kbase_ctx_flag(kctx, KCTX_PRIVILEGED) && - !kbase_io_is_aw_removed(kbdev) && !kbase_pm_is_suspending(kbdev)) { - /* Context is kept scheduled into an address space even when - * there are no jobs, in this case we have to handle the - * situation where all jobs have been evicted from the GPU and - * submission is disabled. - * - * At this point we re-enable submission to allow further jobs - * to be executed - */ - kbasep_js_set_submit_allowed(js_devdata, kctx); - } - - /* Make a set of checks to see if the context should be scheduled out. - * Note that there'll always be at least 1 reference to the context - * which was previously acquired by kbasep_js_schedule_ctx(). - */ - if (new_ref_count == 1 && - (!kbasep_js_is_submit_allowed(js_devdata, kctx) || kbase_io_is_aw_removed(kbdev) || - kbase_pm_is_suspending(kbdev))) { - int num_slots = kbdev->gpu_props.num_job_slots; - unsigned int slot; - - /* Last reference, and we've been told to remove this context - * from the Run Pool - */ - dev_dbg(kbdev->dev, - "JS: RunPool Remove Context %pK because refcount=%d, jobs=%d, allowed=%d", - kctx, new_ref_count, js_kctx_info->ctx.nr_jobs, - kbasep_js_is_submit_allowed(js_devdata, kctx)); - - KBASE_TLSTREAM_TL_NRET_AS_CTX(kbdev, &kbdev->as[kctx->as_nr], kctx); - - kbase_backend_release_ctx_irq(kbdev, kctx); - - for (slot = 0; slot < num_slots; slot++) { - if (kbdev->hwaccess.active_kctx[slot] == kctx) { - dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%d)\n", - (void *)kctx, slot); - kbdev->hwaccess.active_kctx[slot] = NULL; - } - } - - /* Ctx Attribute handling - * - * Releasing atoms attributes must either happen before this, or - * after the KCTX_SHEDULED flag is changed, otherwise we - * double-decount the attributes - */ - runpool_ctx_attr_change |= kbasep_js_ctx_attr_runpool_release_ctx(kbdev, kctx); - - /* Releasing the context and katom retained state can allow - * more jobs to run - */ - release_result |= kbasep_js_run_jobs_after_ctx_and_atom_release( - kbdev, kctx, katom_retained_state, runpool_ctx_attr_change); - - /* - * Transaction ends on AS and runpool_irq: - * - * By this point, the AS-related data is now clear and ready - * for re-use. - * - * Since releases only occur once for each previous successful - * retain, and no more retains are allowed on this context, no - * other thread will be operating in this - * code whilst we are - */ - - /* Recalculate pullable status for all slots */ - for (slot = 0; slot < num_slots; slot++) { - if (kbase_js_ctx_pullable(kctx, slot, false)) - kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, slot); - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - kbase_backend_release_ctx_noirq(kbdev, kctx); - - mutex_unlock(&kbdev->pm.lock); - - /* Note: Don't reuse kctx_as_nr now */ - - /* Synchronize with any timers */ - kbase_backend_ctx_count_changed(kbdev); - - /* update book-keeping info */ - kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); - /* Signal any waiter that the context is not scheduled, so is - * safe for termination - once the jsctx_mutex is also dropped, - * and jobs have finished. - */ - wake_up(&js_kctx_info->ctx.is_scheduled_wait); - - /* Queue an action to occur after we've dropped the lock */ - release_result |= KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED | - KBASEP_JS_RELEASE_RESULT_SCHED_ALL; - } else { - kbasep_js_run_jobs_after_ctx_and_atom_release(kbdev, kctx, katom_retained_state, - runpool_ctx_attr_change); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->pm.lock); - } - - return release_result; -} - -void kbasep_js_runpool_release_ctx_nolock(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - struct kbasep_js_atom_retained_state katom_retained_state; - - /* Setup a dummy katom_retained_state */ - kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); - - kbasep_js_runpool_release_ctx_internal(kbdev, kctx, &katom_retained_state); -} - -void kbasep_js_runpool_requeue_or_kill_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, - bool has_pm_ref) -{ - CSTD_UNUSED(has_pm_ref); - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - - /* This is called if and only if you've you've detached the context from - * the Runpool Queue, and not added it back to the Runpool - */ - KBASE_DEBUG_ASSERT(!kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - if (kbase_ctx_flag(kctx, KCTX_DYING)) { - /* Dying: don't requeue, but kill all jobs on the context. This - * happens asynchronously - */ - dev_dbg(kbdev->dev, "JS: ** Killing Context %pK on RunPool Remove **", kctx); - kbase_js_foreach_ctx_job(kctx, &kbase_jd_cancel); - } -} - -void kbasep_js_runpool_release_ctx_and_katom_retained_state( - struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - kbasep_js_release_result release_result; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - js_kctx_info = &kctx->jctx.sched_info; - js_devdata = &kbdev->js_data; - - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - - release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); - - /* Drop the runpool mutex to allow requeing kctx */ - mutex_unlock(&js_devdata->runpool_mutex); - - if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) - kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true); - - /* Drop the jsctx_mutex to allow scheduling in a new context */ - - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - - if (release_result & KBASEP_JS_RELEASE_RESULT_SCHED_ALL) - kbase_js_sched_all(kbdev); -} - -void kbasep_js_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - struct kbasep_js_atom_retained_state katom_retained_state; - - kbasep_js_atom_retained_state_init_invalid(&katom_retained_state); - - kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &katom_retained_state); -} - -/* Variant of kbasep_js_runpool_release_ctx() that doesn't call into - * kbase_js_sched_all() - */ -static void kbasep_js_runpool_release_ctx_no_schedule(struct kbase_device *kbdev, - struct kbase_context *kctx) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - kbasep_js_release_result release_result; - struct kbasep_js_atom_retained_state katom_retained_state_struct; - struct kbasep_js_atom_retained_state *katom_retained_state = &katom_retained_state_struct; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - js_kctx_info = &kctx->jctx.sched_info; - js_devdata = &kbdev->js_data; - kbasep_js_atom_retained_state_init_invalid(katom_retained_state); - - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - - release_result = kbasep_js_runpool_release_ctx_internal(kbdev, kctx, katom_retained_state); - - /* Drop the runpool mutex to allow requeing kctx */ - mutex_unlock(&js_devdata->runpool_mutex); - if ((release_result & KBASEP_JS_RELEASE_RESULT_WAS_DESCHEDULED) != 0u) - kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, true); - - /* Drop the jsctx_mutex to allow scheduling in a new context */ - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - /* NOTE: could return release_result if the caller would like to know - * whether it should schedule a new context, but currently no callers do - */ -} - -void kbase_js_set_timeouts(struct kbase_device *kbdev) -{ - lockdep_assert_held(&kbdev->hwaccess_lock); - - kbase_backend_timeouts_changed(kbdev); -} - -static bool kbasep_js_schedule_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - unsigned long flags; - bool kctx_suspended = false; - int as_nr; - - dev_dbg(kbdev->dev, "Scheduling kctx %pK (s:%u)\n", kctx, js); - - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - /* Pick available address space for this context */ - mutex_lock(&kbdev->mmu_hw_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - as_nr = kbase_ctx_sched_retain_ctx(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - if (as_nr == KBASEP_AS_NR_INVALID) { - as_nr = kbase_backend_find_and_release_free_address_space(kbdev, kctx); - if (as_nr != KBASEP_AS_NR_INVALID) { - /* Attempt to retain the context again, this should - * succeed - */ - mutex_lock(&kbdev->mmu_hw_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - as_nr = kbase_ctx_sched_retain_ctx(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - - WARN_ON(as_nr == KBASEP_AS_NR_INVALID); - } - } - if ((as_nr < 0) || (as_nr >= BASE_MAX_NR_AS)) - return false; /* No address space currently available */ - - /* - * Atomic transaction on the Context and Run Pool begins - */ - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - mutex_lock(&kbdev->mmu_hw_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* Check to see if context is dying due to kbase_job_zap_context() */ - if (kbase_ctx_flag(kctx, KCTX_DYING)) { - /* Roll back the transaction so far and return */ - kbase_ctx_sched_release_ctx(kctx); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - return false; - } - - KBASE_KTRACE_ADD_JM_REFCOUNT(kbdev, JS_TRY_SCHEDULE_HEAD_CTX, kctx, NULL, 0u, - kbase_ktrace_get_ctx_refcnt(kctx)); - - kbase_ctx_flag_set(kctx, KCTX_SCHEDULED); - - /* Assign context to previously chosen address space */ - if (!kbase_backend_use_ctx(kbdev, kctx, as_nr)) { - /* Roll back the transaction so far and return */ - kbase_ctx_sched_release_ctx(kctx); - kbase_ctx_flag_clear(kctx, KCTX_SCHEDULED); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - return false; - } - - kbdev->hwaccess.active_kctx[js] = kctx; - - KBASE_TLSTREAM_TL_RET_AS_CTX(kbdev, &kbdev->as[kctx->as_nr], kctx); - - /* Cause any future waiter-on-termination to wait until the context is - * descheduled - */ - wake_up(&js_kctx_info->ctx.is_scheduled_wait); - - /* Re-check for suspending: a suspend could've occurred, and all the - * contexts could've been removed from the runpool before we took this - * lock. In this case, we don't want to allow this context to run jobs, - * we just want it out immediately. - * - * The DMB required to read the suspend flag was issued recently as part - * of the hwaccess_lock locking. If a suspend occurs *after* that lock - * was taken (i.e. this condition doesn't execute), then the - * kbasep_js_suspend() code will cleanup this context instead (by virtue - * of it being called strictly after the suspend flag is set, and will - * wait for this lock to drop) - */ - if (kbase_pm_is_suspending(kbdev) || kbase_io_is_aw_removed(kbdev)) { - /* Cause it to leave at some later point */ - bool retained; - CSTD_UNUSED(retained); - - retained = kbase_ctx_sched_inc_refcount_nolock(kctx); - KBASE_DEBUG_ASSERT(retained); - - kbasep_js_clear_submit_allowed(js_devdata, kctx); - kctx_suspended = true; - } - - kbase_ctx_flag_clear(kctx, KCTX_PULLED_SINCE_ACTIVE_JS0 << js); - - /* Transaction complete */ - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kbdev->mmu_hw_mutex); - - /* Synchronize with any timers */ - kbase_backend_ctx_count_changed(kbdev); - - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - /* Note: after this point, the context could potentially get scheduled - * out immediately - */ - - if (kctx_suspended) { - /* Finishing forcing out the context due to a suspend. Use a - * variant of kbasep_js_runpool_release_ctx() that doesn't - * schedule a new context, to prevent a risk of recursion back - * into this function - */ - kbasep_js_runpool_release_ctx_no_schedule(kbdev, kctx); - return false; - } - return true; -} - -static bool kbase_js_use_ctx(struct kbase_device *kbdev, struct kbase_context *kctx, - unsigned int js) -{ - unsigned long flags; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && kbase_backend_use_ctx_sched(kbdev, kctx, js)) { - dev_dbg(kbdev->dev, "kctx %pK already has ASID - mark as active (s:%u)\n", - (void *)kctx, js); - - if (kbdev->hwaccess.active_kctx[js] != kctx) { - kbdev->hwaccess.active_kctx[js] = kctx; - kbase_ctx_flag_clear(kctx, KCTX_PULLED_SINCE_ACTIVE_JS0 << js); - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - return true; /* Context already scheduled */ - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - return kbasep_js_schedule_ctx(kbdev, kctx, js); -} - -void kbasep_js_schedule_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - struct kbasep_js_kctx_info *js_kctx_info; - struct kbasep_js_device_data *js_devdata; - bool is_scheduled; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - /* This should only happen in response to a system call - * from a user-space thread. - * In a non-arbitrated environment this can never happen - * whilst suspending. - * - * In an arbitrated environment, user-space threads can run - * while we are suspended (for example GPU not available - * to this VM), however in that case we will block on - * the wait event for KCTX_SCHEDULED, since no context - * can be scheduled until we have the GPU again. - */ - if (!kbase_has_arbiter(kbdev)) { - if (WARN_ON(kbase_pm_is_suspending(kbdev))) - return; - } - - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - - /* Mark the context as privileged */ - kbase_ctx_flag_set(kctx, KCTX_PRIVILEGED); - - is_scheduled = kbase_ctx_flag(kctx, KCTX_SCHEDULED); - if (!is_scheduled) { - /* Add the context to the pullable list */ - if (kbase_js_ctx_list_add_pullable_head(kbdev, kctx, 0)) - kbase_js_sync_timers(kbdev); - - /* Fast-starting requires the jsctx_mutex to be dropped, - * because it works on multiple ctxs - */ - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - - /* Try to schedule the context in */ - kbase_js_sched_all(kbdev); - - /* Wait for the context to be scheduled in */ - wait_event(kctx->jctx.sched_info.ctx.is_scheduled_wait, - kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - } else { - /* Already scheduled in - We need to retain it to keep the - * corresponding address space - */ - WARN_ON(!kbase_ctx_sched_inc_refcount(kctx)); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - } -} -KBASE_EXPORT_TEST_API(kbasep_js_schedule_privileged_ctx); - -void kbasep_js_release_privileged_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - struct kbasep_js_kctx_info *js_kctx_info; - - KBASE_DEBUG_ASSERT(kctx != NULL); - js_kctx_info = &kctx->jctx.sched_info; - - /* We don't need to use the address space anymore */ - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - kbase_ctx_flag_clear(kctx, KCTX_PRIVILEGED); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - /* Release the context - it will be scheduled out */ - kbasep_js_runpool_release_ctx(kbdev, kctx); - - kbase_js_sched_all(kbdev); -} -KBASE_EXPORT_TEST_API(kbasep_js_release_privileged_ctx); - -void kbasep_js_suspend(struct kbase_device *kbdev) -{ - unsigned long flags; - struct kbasep_js_device_data *js_devdata; - int i; - u16 retained = 0u; - - KBASE_DEBUG_ASSERT(kbdev); - KBASE_DEBUG_ASSERT(kbase_pm_is_suspending(kbdev)); - js_devdata = &kbdev->js_data; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - /* Prevent all contexts from submitting */ - js_devdata->runpool_irq.submit_allowed = 0; - - /* Retain each of the contexts, so we can cause it to leave even if it - * had no refcount to begin with - */ - for (i = BASE_MAX_NR_AS - 1; i >= 0; --i) { - struct kbase_context *kctx = kbdev->as_to_kctx[i]; - - retained = retained << 1; - - if (kctx && !(kbdev->as_free & (1u << i))) { - kbase_ctx_sched_retain_ctx_refcount(kctx); - retained |= 1u; - /* This loop will not have an effect on the privileged - * contexts as they would have an extra ref count - * compared to the normal contexts, so they will hold - * on to their address spaces. MMU will re-enabled for - * them on resume. - */ - } - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* De-ref the previous retain to ensure each context gets pulled out - * sometime later. - */ - for (i = 0; i < BASE_MAX_NR_AS; ++i, retained = retained >> 1) { - struct kbase_context *kctx = kbdev->as_to_kctx[i]; - - if (retained & 1u) - kbasep_js_runpool_release_ctx(kbdev, kctx); - } - - /* Caller must wait for all Power Manager active references to be - * dropped - */ -} - -void kbasep_js_resume(struct kbase_device *kbdev) -{ - struct kbasep_js_device_data *js_devdata; - unsigned int js; - int prio; - - KBASE_DEBUG_ASSERT(kbdev); - js_devdata = &kbdev->js_data; - KBASE_DEBUG_ASSERT(!kbase_pm_is_suspending(kbdev)); - - mutex_lock(&js_devdata->queue_mutex); - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - for (prio = KBASE_JS_ATOM_SCHED_PRIO_FIRST; prio < KBASE_JS_ATOM_SCHED_PRIO_COUNT; - prio++) { - struct kbase_context *kctx, *n; - unsigned long flags; - - if (kbase_has_arbiter(kbdev)) { - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - list_for_each_entry_safe( - kctx, n, &kbdev->js_data.ctx_list_unpullable[js][prio], - jctx.sched_info.ctx.ctx_list_entry[js]) { - struct kbasep_js_kctx_info *js_kctx_info; - bool timer_sync = false; - - /* Drop lock so we can take kctx mutexes */ - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - js_kctx_info = &kctx->jctx.sched_info; - - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - mutex_lock(&js_devdata->runpool_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) && - kbase_js_ctx_pullable(kctx, js, false)) - timer_sync = kbase_js_ctx_list_add_pullable_nolock( - kbdev, kctx, js); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (timer_sync) - kbase_backend_ctx_count_changed(kbdev); - - mutex_unlock(&js_devdata->runpool_mutex); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - - /* Take lock before accessing list again */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } else { - bool timer_sync = false; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - list_for_each_entry_safe( - kctx, n, &kbdev->js_data.ctx_list_unpullable[js][prio], - jctx.sched_info.ctx.ctx_list_entry[js]) { - if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED) && - kbase_js_ctx_pullable(kctx, js, false)) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock( - kbdev, kctx, js); - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (timer_sync) { - mutex_lock(&js_devdata->runpool_mutex); - kbase_backend_ctx_count_changed(kbdev); - mutex_unlock(&js_devdata->runpool_mutex); - } - } - } - } - mutex_unlock(&js_devdata->queue_mutex); - - /* Restart atom processing */ - kbase_js_sched_all(kbdev); - - /* JS Resume complete */ -} - -bool kbase_js_is_atom_valid(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - CSTD_UNUSED(kbdev); - - if ((katom->core_req & BASE_JD_REQ_FS) && - (katom->core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T))) - return false; - - if ((katom->core_req & BASE_JD_REQ_JOB_SLOT) && (katom->jobslot >= BASE_JM_MAX_NR_SLOTS)) - return false; - - return true; -} - -static unsigned int kbase_js_get_slot(struct kbase_device *kbdev, struct kbase_jd_atom *katom) -{ - if (katom->core_req & BASE_JD_REQ_JOB_SLOT) - return katom->jobslot; - - if (katom->core_req & BASE_JD_REQ_FS) - return 0; - - if (katom->core_req & BASE_JD_REQ_ONLY_COMPUTE) { - if (katom->device_nr == 1 && kbdev->gpu_props.num_core_groups == 2) - return 2; - } - - return 1; -} - -bool kbase_js_dep_resolved_submit(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - bool enqueue_required; - - katom->slot_nr = kbase_js_get_slot(kctx->kbdev, katom); - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - lockdep_assert_held(&kctx->jctx.lock); - - /* If slot will transition from unpullable to pullable then add to - * pullable list - */ - enqueue_required = jsctx_rb_none_to_pull(kctx, katom->slot_nr); - - if ((katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) || - (katom->pre_dep && - (katom->pre_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) { - int prio = katom->sched_priority; - unsigned int js = katom->slot_nr; - struct jsctx_queue *queue = &kctx->jsctx_queue[prio][js]; - - dev_dbg(kctx->kbdev->dev, "Add atom %pK to X_DEP list (s:%u)\n", (void *)katom, js); - - list_add_tail(&katom->queue, &queue->x_dep_head); - katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST; - enqueue_required = false; - } else { - dev_dbg(kctx->kbdev->dev, "Atom %pK not added to X_DEP list\n", (void *)katom); - /* Check if there are lower priority jobs to soft stop */ - kbase_job_slot_ctx_priority_check_locked(kctx, katom); - - /* Add atom to ring buffer. */ - jsctx_tree_add(kctx, katom); - katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE; - } - - dev_dbg(kctx->kbdev->dev, "Enqueue of kctx %pK is %srequired to submit atom %pK\n", kctx, - enqueue_required ? "" : "not ", katom); - - return enqueue_required; -} - -/** - * kbase_js_move_to_tree - Move atom (and any dependent atoms) to the - * runnable_tree, ready for execution - * @katom: Atom to submit - * - * It is assumed that @katom does not have KBASE_KATOM_FLAG_X_DEP_BLOCKED set, - * but is still present in the x_dep list. If @katom has a same-slot dependent - * atom then that atom (and any dependents) will also be moved. - */ -static void kbase_js_move_to_tree(struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&katom->kctx->kbdev->hwaccess_lock); - - while (katom) { - WARN_ON(!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST)); - - if (!(katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED)) { - dev_dbg(katom->kctx->kbdev->dev, - "Del atom %pK from X_DEP list in js_move_to_tree\n", (void *)katom); - - list_del(&katom->queue); - katom->atom_flags &= ~KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST; - jsctx_tree_add(katom->kctx, katom); - katom->atom_flags |= KBASE_KATOM_FLAG_JSCTX_IN_TREE; - } else { - dev_dbg(katom->kctx->kbdev->dev, - "Atom %pK blocked on x-dep in js_move_to_tree\n", (void *)katom); - break; - } - - katom = katom->post_dep; - } -} - -/** - * kbase_js_evict_deps - Evict dependencies of a failed atom. - * @kctx: Context pointer - * @katom: Pointer to the atom that has failed. - * @js: The job slot the katom was run on. - * @prio: Priority of the katom. - * - * Remove all post dependencies of an atom from the context ringbuffers. - * - * The original atom's event_code will be propagated to all dependent atoms. - * - * Context: Caller must hold the HW access lock - */ -static void kbase_js_evict_deps(struct kbase_context *kctx, struct kbase_jd_atom *katom, - unsigned int js, int prio) -{ - struct kbase_jd_atom *x_dep = katom->x_post_dep; - struct kbase_jd_atom *next_katom = katom->post_dep; - - CSTD_UNUSED(js); - CSTD_UNUSED(prio); - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - if (next_katom) { - KBASE_DEBUG_ASSERT(next_katom->status != KBASE_JD_ATOM_STATE_HW_COMPLETED); - next_katom->will_fail_event_code = katom->event_code; - } - - /* Has cross slot depenency. */ - if (x_dep && (x_dep->atom_flags & - (KBASE_KATOM_FLAG_JSCTX_IN_TREE | KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST))) { - /* Remove dependency.*/ - x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED; - - dev_dbg(kctx->kbdev->dev, "Cleared X_DEP flag on atom %pK\n", (void *)x_dep); - - /* Fail if it had a data dependency. */ - if (x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) - x_dep->will_fail_event_code = katom->event_code; - - if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST) - kbase_js_move_to_tree(x_dep); - } -} - -struct kbase_jd_atom *kbase_js_pull(struct kbase_context *kctx, unsigned int js) -{ - struct kbase_jd_atom *katom; - struct kbasep_js_device_data *js_devdata; - struct kbase_device *kbdev; - int pulled; - - KBASE_DEBUG_ASSERT(kctx); - - kbdev = kctx->kbdev; - dev_dbg(kbdev->dev, "JS: pulling an atom from kctx %pK (s:%u)\n", (void *)kctx, js); - - js_devdata = &kbdev->js_data; - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) { - dev_dbg(kbdev->dev, "JS: No submit allowed for kctx %pK\n", (void *)kctx); - return NULL; - } - if (kbase_pm_is_suspending(kbdev) || kbase_io_is_aw_removed(kbdev)) - return NULL; - - katom = jsctx_rb_peek(kctx, js); - if (!katom) { - dev_dbg(kbdev->dev, "JS: No pullable atom in kctx %pK (s:%u)\n", (void *)kctx, js); - return NULL; - } - if (kbase_jsctx_slot_prio_is_blocked(kctx, js, katom->sched_priority)) { - dev_dbg(kbdev->dev, - "JS: kctx %pK is blocked from submitting atoms at priority %d and lower (s:%u)\n", - (void *)kctx, katom->sched_priority, js); - return NULL; - } - if (atomic_read(&katom->blocked)) { - dev_dbg(kbdev->dev, "JS: Atom %pK is blocked in js_pull\n", (void *)katom); - return NULL; - } - - /* Due to ordering restrictions when unpulling atoms on failure, we do - * not allow multiple runs of fail-dep atoms from the same context to be - * present on the same slot - */ - if (katom->pre_dep && kbase_jsctx_slot_atoms_pulled(kctx, js)) { - struct kbase_jd_atom *prev_atom = kbase_backend_inspect_tail(kbdev, js); - - if (prev_atom && prev_atom->kctx != kctx) - return NULL; - } - - if (katom->atom_flags & KBASE_KATOM_FLAG_X_DEP_BLOCKED) { - if (katom->x_pre_dep->gpu_rb_state == KBASE_ATOM_GPU_RB_NOT_IN_SLOT_RB || - katom->x_pre_dep->will_fail_event_code) { - dev_dbg(kbdev->dev, - "JS: X pre-dep %pK is not present in slot FIFO or will fail\n", - (void *)katom->x_pre_dep); - return NULL; - } - if ((katom->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER) && - kbase_backend_nr_atoms_on_slot(kbdev, js)) { - dev_dbg(kbdev->dev, - "JS: Atom %pK has cross-slot fail dependency and atoms on slot (s:%u)\n", - (void *)katom, js); - return NULL; - } - } - - KBASE_KTRACE_ADD_JM_SLOT_INFO(kbdev, JS_PULL_JOB, kctx, katom, katom->jc, js, - (u64)katom->sched_priority); - kbase_ctx_flag_set(kctx, KCTX_PULLED); - kbase_ctx_flag_set(kctx, (KCTX_PULLED_SINCE_ACTIVE_JS0 << js)); - - pulled = kbase_jsctx_slot_atom_pulled_inc(kctx, katom); - if (pulled == 1 && !kctx->slots_pullable) { - WARN_ON(kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_set(kctx, KCTX_RUNNABLE_REF); - atomic_inc(&kbdev->js_data.nr_contexts_runnable); - } - jsctx_rb_pull(kctx, katom); - - kbase_ctx_sched_retain_ctx_refcount(kctx); - - katom->ticks = 0; - - dev_dbg(kbdev->dev, "JS: successfully pulled atom %pK from kctx %pK (s:%u)\n", - (void *)katom, (void *)kctx, js); - - return katom; -} - -static void js_return_worker(struct work_struct *data) -{ - struct kbase_jd_atom *katom = container_of(data, struct kbase_jd_atom, work); - struct kbase_context *kctx = katom->kctx; - struct kbase_device *kbdev = kctx->kbdev; - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; - struct kbasep_js_atom_retained_state retained_state; - unsigned int js = katom->slot_nr; - bool slot_became_unblocked; - bool timer_sync = false; - bool context_idle = false; - unsigned long flags; - base_jd_core_req core_req = katom->core_req; - u64 cache_jc = katom->jc; - - dev_dbg(kbdev->dev, "%s for atom %pK with event code 0x%x\n", __func__, (void *)katom, - katom->event_code); - - KBASE_KTRACE_ADD_JM(kbdev, JS_RETURN_WORKER, kctx, katom, katom->jc, 0); - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTSTOP_EX(kbdev, katom); - - kbase_backend_complete_wq(kbdev, katom); - - kbasep_js_atom_retained_state_copy(&retained_state, katom); - - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - - atomic_dec(&katom->blocked); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - slot_became_unblocked = kbase_jsctx_slot_atom_pulled_dec(kctx, katom); - - if (!kbase_jsctx_slot_atoms_pulled(kctx, js) && jsctx_rb_none_to_pull(kctx, js)) - timer_sync |= kbase_js_ctx_list_remove_nolock(kbdev, kctx, js); - - /* If the context is now unblocked on this slot after soft-stopped - * atoms, then only mark it as pullable on this slot if it is not - * idle - */ - if (slot_became_unblocked && kbase_jsctx_atoms_pulled(kctx) && - kbase_js_ctx_pullable(kctx, js, true)) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, js); - - if (!kbase_jsctx_atoms_pulled(kctx)) { - dev_dbg(kbdev->dev, "No atoms currently pulled from context %pK\n", (void *)kctx); - - if (!kctx->slots_pullable) { - dev_dbg(kbdev->dev, "Context %pK %s counted as runnable\n", (void *)kctx, - kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF) ? "is" : "isn't"); - - WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); - atomic_dec(&kbdev->js_data.nr_contexts_runnable); - timer_sync = true; - } - - if (kctx->as_nr != KBASEP_AS_NR_INVALID && !kbase_ctx_flag(kctx, KCTX_DYING)) { - unsigned int num_slots = kbdev->gpu_props.num_job_slots; - unsigned int slot; - - if (!kbasep_js_is_submit_allowed(js_devdata, kctx)) - kbasep_js_set_submit_allowed(js_devdata, kctx); - - for (slot = 0; slot < num_slots; slot++) { - if (kbase_js_ctx_pullable(kctx, slot, true)) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock( - kbdev, kctx, slot); - } - } - - kbase_jm_idle_ctx(kbdev, kctx); - - context_idle = true; - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - if (context_idle) { - dev_dbg(kbdev->dev, "Context %pK %s counted as active\n", (void *)kctx, - kbase_ctx_flag(kctx, KCTX_ACTIVE) ? "is" : "isn't"); - WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); - kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); - kbase_pm_context_idle(kbdev); - } - - if (timer_sync) - kbase_js_sync_timers(kbdev); - - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - - dev_dbg(kbdev->dev, "JS: retained state %s finished", - kbasep_js_has_atom_finished(&retained_state) ? "has" : "hasn't"); - - WARN_ON(kbasep_js_has_atom_finished(&retained_state)); - - kbasep_js_runpool_release_ctx_and_katom_retained_state(kbdev, kctx, &retained_state); - - kbase_js_sched_all(kbdev); - - kbase_backend_complete_wq_post_sched(kbdev, core_req); - - KBASE_KTRACE_ADD_JM(kbdev, JS_RETURN_WORKER_END, kctx, NULL, cache_jc, 0); - - dev_dbg(kbdev->dev, "Leaving %s for atom %pK\n", __func__, (void *)katom); -} - -void kbase_js_unpull(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - dev_dbg(kctx->kbdev->dev, "Unpulling atom %pK in kctx %pK\n", (void *)katom, (void *)kctx); - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - jsctx_rb_unpull(kctx, katom); - - WARN_ON(work_pending(&katom->work)); - - /* Block re-submission until workqueue has run */ - atomic_inc(&katom->blocked); - - kbase_job_check_leave_disjoint(kctx->kbdev, katom); - - INIT_WORK(&katom->work, js_return_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); -} - -bool kbase_js_complete_atom_wq(struct kbase_context *kctx, struct kbase_jd_atom *katom) -{ - struct kbasep_js_kctx_info *js_kctx_info; - struct kbasep_js_device_data *js_devdata; - struct kbase_device *kbdev; - unsigned long flags; - bool timer_sync = false; - unsigned int atom_slot; - bool context_idle = false; - int prio = katom->sched_priority; - - kbdev = kctx->kbdev; - atom_slot = katom->slot_nr; - - dev_dbg(kbdev->dev, "%s for atom %pK (s:%u)\n", __func__, (void *)katom, atom_slot); - - js_kctx_info = &kctx->jctx.sched_info; - js_devdata = &kbdev->js_data; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - - mutex_lock(&js_devdata->runpool_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - if (katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) { - bool slot_became_unblocked; - - dev_dbg(kbdev->dev, "Atom %pK is in runnable_tree\n", (void *)katom); - - slot_became_unblocked = kbase_jsctx_slot_atom_pulled_dec(kctx, katom); - context_idle = !kbase_jsctx_atoms_pulled(kctx); - - if (!kbase_jsctx_atoms_pulled(kctx) && !kctx->slots_pullable) { - WARN_ON(!kbase_ctx_flag(kctx, KCTX_RUNNABLE_REF)); - kbase_ctx_flag_clear(kctx, KCTX_RUNNABLE_REF); - atomic_dec(&kbdev->js_data.nr_contexts_runnable); - timer_sync = true; - } - - /* If this slot has been blocked due to soft-stopped atoms, and - * all atoms have now been processed at this priority level and - * higher, then unblock the slot - */ - if (slot_became_unblocked) { - dev_dbg(kbdev->dev, - "kctx %pK is no longer blocked from submitting on slot %u at priority %d or higher\n", - (void *)kctx, atom_slot, prio); - - if (kbase_js_ctx_pullable(kctx, atom_slot, true)) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, - atom_slot); - } - } - WARN_ON(!(katom->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE)); - - if (!kbase_jsctx_slot_atoms_pulled(kctx, atom_slot) && - jsctx_rb_none_to_pull(kctx, atom_slot)) { - if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[atom_slot])) - timer_sync |= kbase_js_ctx_list_remove_nolock(kctx->kbdev, kctx, atom_slot); - } - - /* - * If submission is disabled on this context (most likely due to an - * atom failure) and there are now no atoms left in the system then - * re-enable submission so that context can be scheduled again. - */ - if (!kbasep_js_is_submit_allowed(js_devdata, kctx) && !kbase_jsctx_atoms_pulled(kctx) && - !kbase_ctx_flag(kctx, KCTX_DYING)) { - unsigned int js; - - kbasep_js_set_submit_allowed(js_devdata, kctx); - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - if (kbase_js_ctx_pullable(kctx, js, true)) - timer_sync |= - kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, js); - } - } else if (katom->x_post_dep && kbasep_js_is_submit_allowed(js_devdata, kctx)) { - unsigned int js; - - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - if (kbase_js_ctx_pullable(kctx, js, true)) - timer_sync |= - kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, js); - } - } - - /* Mark context as inactive. The pm reference will be dropped later in - * jd_done_worker(). - */ - if (context_idle) { - dev_dbg(kbdev->dev, "kctx %pK is no longer active\n", (void *)kctx); - kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); - } - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - if (timer_sync) - kbase_backend_ctx_count_changed(kbdev); - mutex_unlock(&js_devdata->runpool_mutex); - - dev_dbg(kbdev->dev, "Leaving %s\n", __func__); - return context_idle; -} - -struct kbase_jd_atom *kbase_js_complete_atom(struct kbase_jd_atom *katom, ktime_t *end_timestamp) -{ - struct kbase_device *kbdev; - struct kbase_context *kctx = katom->kctx; - struct kbase_jd_atom *x_dep = katom->x_post_dep; - - kbdev = kctx->kbdev; - dev_dbg(kbdev->dev, "Atom %pK complete in kctx %pK (post-dep %pK)\n", (void *)katom, - (void *)kctx, (void *)x_dep); - - lockdep_assert_held(&kctx->kbdev->hwaccess_lock); - - if (katom->will_fail_event_code) - katom->event_code = katom->will_fail_event_code; - - katom->status = KBASE_JD_ATOM_STATE_HW_COMPLETED; - dev_dbg(kbdev->dev, "Atom %pK status to HW completed\n", (void *)katom); - if (kbase_is_quick_reset_enabled(kbdev)) { - kbdev->num_of_atoms_hw_completed++; - if (kbdev->num_of_atoms_hw_completed >= 20) - kbase_disable_quick_reset(kbdev); - } - - if (katom->event_code != BASE_JD_EVENT_DONE) { - kbase_js_evict_deps(kctx, katom, katom->slot_nr, katom->sched_priority); - } - - KBASE_TLSTREAM_AUX_EVENT_JOB_SLOT(kbdev, NULL, katom->slot_nr, 0, TL_JS_EVENT_STOP); - - trace_sysgraph_gpu(SGR_COMPLETE, kctx->id, kbase_jd_atom_id(katom->kctx, katom), - katom->slot_nr); - - KBASE_TLSTREAM_TL_JD_DONE_START(kbdev, katom); - kbase_jd_done(katom, katom->slot_nr, end_timestamp, 0); - KBASE_TLSTREAM_TL_JD_DONE_END(kbdev, katom); - - /* Unblock cross dependency if present */ - if (x_dep && - (katom->event_code == BASE_JD_EVENT_DONE || - !(x_dep->atom_flags & KBASE_KATOM_FLAG_FAIL_BLOCKER)) && - (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_X_DEP_LIST)) { - bool was_pullable = kbase_js_ctx_pullable(kctx, x_dep->slot_nr, false); - x_dep->atom_flags &= ~KBASE_KATOM_FLAG_X_DEP_BLOCKED; - dev_dbg(kbdev->dev, "Cleared X_DEP flag on atom %pK\n", (void *)x_dep); - - kbase_js_move_to_tree(x_dep); - - if (!was_pullable && kbase_js_ctx_pullable(kctx, x_dep->slot_nr, false)) - kbase_js_ctx_list_add_pullable_nolock(kbdev, kctx, x_dep->slot_nr); - - if (x_dep->atom_flags & KBASE_KATOM_FLAG_JSCTX_IN_TREE) { - dev_dbg(kbdev->dev, "Atom %pK is in runnable tree\n", (void *)x_dep); - return x_dep; - } - } else { - dev_dbg(kbdev->dev, "No cross-slot dep to unblock for atom %pK\n", (void *)katom); - } - - return NULL; -} - -void kbase_js_sched(struct kbase_device *kbdev, unsigned int js_mask) -{ - struct kbasep_js_device_data *js_devdata; - struct kbase_context *last_active_kctx[BASE_JM_MAX_NR_SLOTS]; - bool timer_sync = false; - bool ctx_waiting[BASE_JM_MAX_NR_SLOTS]; - unsigned int js; - - KBASE_TLSTREAM_TL_JS_SCHED_START(kbdev, 0); - - dev_dbg(kbdev->dev, "%s kbdev %pK mask 0x%x\n", __func__, (void *)kbdev, - (unsigned int)js_mask); - - js_devdata = &kbdev->js_data; - - down(&js_devdata->schedule_sem); - mutex_lock(&js_devdata->queue_mutex); - - for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { - last_active_kctx[js] = kbdev->hwaccess.active_kctx[js]; - ctx_waiting[js] = false; - } - - while (js_mask) { - js = (unsigned int)ffs((int)js_mask) - 1; - - while (1) { - struct kbase_context *kctx; - unsigned long flags; - bool context_idle = false; - - kctx = kbase_js_ctx_list_pop_head(kbdev, js); - - if (!kctx) { - js_mask &= ~(1UL << js); - dev_dbg(kbdev->dev, "No kctx on pullable list (s:%u)\n", js); - break; - } - - if (!kbase_ctx_flag(kctx, KCTX_ACTIVE)) { - context_idle = true; - - dev_dbg(kbdev->dev, "kctx %pK is not active (s:%u)\n", (void *)kctx, - js); - - if (kbase_pm_context_active_handle_suspend( - kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_INCREASE)) { - dev_dbg(kbdev->dev, "Suspend pending (s:%u)\n", js); - /* Suspend pending - return context to - * queue and stop scheduling - */ - mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - if (kbase_js_ctx_list_add_pullable_head(kctx->kbdev, kctx, - js)) - kbase_js_sync_timers(kbdev); - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - up(&js_devdata->schedule_sem); - KBASE_TLSTREAM_TL_JS_SCHED_END(kbdev, 0); - return; - } - kbase_ctx_flag_set(kctx, KCTX_ACTIVE); - } - - if (!kbase_js_use_ctx(kbdev, kctx, js)) { - mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - - dev_dbg(kbdev->dev, "kctx %pK cannot be used at this time\n", kctx); - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - if (kbase_js_ctx_pullable(kctx, js, false) || - kbase_ctx_flag(kctx, KCTX_PRIVILEGED)) - timer_sync |= kbase_js_ctx_list_add_pullable_head_nolock( - kctx->kbdev, kctx, js); - else - timer_sync |= kbase_js_ctx_list_add_unpullable_nolock( - kctx->kbdev, kctx, js); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - if (context_idle) { - WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); - kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); - kbase_pm_context_idle(kbdev); - } - - /* No more jobs can be submitted on this slot */ - js_mask &= ~(1UL << js); - break; - } - mutex_lock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - kbase_ctx_flag_clear(kctx, KCTX_PULLED); - - if (!kbase_jm_kick(kbdev, 1UL << js)) { - dev_dbg(kbdev->dev, "No more jobs can be submitted (s:%u)\n", js); - js_mask &= ~(1UL << js); - } - if (!kbase_ctx_flag(kctx, KCTX_PULLED)) { - bool pullable; - - dev_dbg(kbdev->dev, "No atoms pulled from kctx %pK (s:%u)\n", - (void *)kctx, js); - - pullable = kbase_js_ctx_pullable(kctx, js, true); - - /* Failed to pull jobs - push to head of list. - * Unless this context is already 'active', in - * which case it's effectively already scheduled - * so push it to the back of the list. - */ - if (pullable && kctx == last_active_kctx[js] && - kbase_ctx_flag(kctx, (KCTX_PULLED_SINCE_ACTIVE_JS0 << js))) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock( - kctx->kbdev, kctx, js); - else if (pullable) - timer_sync |= kbase_js_ctx_list_add_pullable_head_nolock( - kctx->kbdev, kctx, js); - else - timer_sync |= kbase_js_ctx_list_add_unpullable_nolock( - kctx->kbdev, kctx, js); - - /* If this context is not the active context, - * but the active context is pullable on this - * slot, then we need to remove the active - * marker to prevent it from submitting atoms in - * the IRQ handler, which would prevent this - * context from making progress. - */ - if (last_active_kctx[js] && kctx != last_active_kctx[js] && - kbase_js_ctx_pullable(last_active_kctx[js], js, true)) - ctx_waiting[js] = true; - - if (context_idle) { - kbase_jm_idle_ctx(kbdev, kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - WARN_ON(!kbase_ctx_flag(kctx, KCTX_ACTIVE)); - kbase_ctx_flag_clear(kctx, KCTX_ACTIVE); - kbase_pm_context_idle(kbdev); - } else { - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - - js_mask &= ~(1UL << js); - break; /* Could not run atoms on this slot */ - } - - dev_dbg(kbdev->dev, "Push kctx %pK to back of list\n", (void *)kctx); - if (kbase_js_ctx_pullable(kctx, js, true)) - timer_sync |= kbase_js_ctx_list_add_pullable_nolock(kctx->kbdev, - kctx, js); - else - timer_sync |= kbase_js_ctx_list_add_unpullable_nolock(kctx->kbdev, - kctx, js); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&kctx->jctx.sched_info.ctx.jsctx_mutex); - } - } - - if (timer_sync) - kbase_js_sync_timers(kbdev); - - for (js = 0; js < BASE_JM_MAX_NR_SLOTS; js++) { - if (kbdev->hwaccess.active_kctx[js] == last_active_kctx[js] && ctx_waiting[js]) { - dev_dbg(kbdev->dev, "Marking kctx %pK as inactive (s:%u)\n", - (void *)last_active_kctx[js], js); - kbdev->hwaccess.active_kctx[js] = NULL; - } - } - - mutex_unlock(&js_devdata->queue_mutex); - up(&js_devdata->schedule_sem); - KBASE_TLSTREAM_TL_JS_SCHED_END(kbdev, 0); -} - -void kbase_js_zap_context(struct kbase_context *kctx) -{ - struct kbase_device *kbdev = kctx->kbdev; - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - struct kbasep_js_kctx_info *js_kctx_info = &kctx->jctx.sched_info; - - /* - * Critical assumption: No more submission is possible outside of the - * workqueue. This is because the OS *must* prevent U/K calls (IOCTLs) - * whilst the struct kbase_context is terminating. - */ - - /* First, atomically do the following: - * - mark the context as dying - * - try to evict it from the queue - */ - mutex_lock(&kctx->jctx.lock); - mutex_lock(&js_devdata->queue_mutex); - mutex_lock(&js_kctx_info->ctx.jsctx_mutex); - kbase_ctx_flag_set(kctx, KCTX_DYING); - - dev_dbg(kbdev->dev, "Zap: Try Evict Ctx %pK", kctx); - - /* - * At this point we know: - * - If eviction succeeded, it was in the queue, but now no - * longer is - * - We must cancel the jobs here. No Power Manager active reference to - * release. - * - This happens asynchronously - kbase_jd_zap_context() will wait for - * those jobs to be killed. - * - If eviction failed, then it wasn't in the queue. It is one - * of the following: - * - a. it didn't have any jobs, and so is not in the Queue or - * the Run Pool (not scheduled) - * - Hence, no more work required to cancel jobs. No Power Manager - * active reference to release. - * - b. it was in the middle of a scheduling transaction (and thus must - * have at least 1 job). This can happen from a syscall or a - * kernel thread. We still hold the jsctx_mutex, and so the thread - * must be waiting inside kbasep_js_try_schedule_head_ctx(), - * before checking whether the runpool is full. That thread will - * continue after we drop the mutex, and will notice the context - * is dying. It will rollback the transaction, killing all jobs at - * the same time. kbase_jd_zap_context() will wait for those jobs - * to be killed. - * - Hence, no more work required to cancel jobs, or to release the - * Power Manager active reference. - * - c. it is scheduled, and may or may not be running jobs - * - We must cause it to leave the runpool by stopping it from - * submitting any more jobs. When it finally does leave, - * kbasep_js_runpool_requeue_or_kill_ctx() will kill all remaining jobs - * (because it is dying), release the Power Manager active reference, - * and will not requeue the context in the queue. - * kbase_jd_zap_context() will wait for those jobs to be killed. - * - Hence, work required just to make it leave the runpool. Cancelling - * jobs and releasing the Power manager active reference will be - * handled when it leaves the runpool. - */ - if (!kbase_ctx_flag(kctx, KCTX_SCHEDULED)) { - unsigned long flags; - unsigned int js; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) { - if (!list_empty(&kctx->jctx.sched_info.ctx.ctx_list_entry[js])) - list_del_init(&kctx->jctx.sched_info.ctx.ctx_list_entry[js]); - } - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* The following events require us to kill off remaining jobs - * and update PM book-keeping: - * - we evicted it correctly (it must have jobs to be in the - * Queue) - * - * These events need no action, but take this path anyway: - * - Case a: it didn't have any jobs, and was never in the Queue - * - Case b: scheduling transaction will be partially rolled- - * back (this already cancels the jobs) - */ - - KBASE_KTRACE_ADD_JM(kbdev, JM_ZAP_NON_SCHEDULED, kctx, NULL, 0u, - kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - dev_dbg(kbdev->dev, "Zap: Ctx %pK scheduled=0", kctx); - - /* Only cancel jobs when we evicted from the - * queue. No Power Manager active reference was held. - * - * Having is_dying set ensures that this kills, and doesn't - * requeue - */ - kbasep_js_runpool_requeue_or_kill_ctx(kbdev, kctx, false); - - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - mutex_unlock(&kctx->jctx.lock); - } else { - unsigned long flags; - bool was_retained; - CSTD_UNUSED(was_retained); - - /* Case c: didn't evict, but it is scheduled - it's in the Run - * Pool - */ - KBASE_KTRACE_ADD_JM(kbdev, JM_ZAP_SCHEDULED, kctx, NULL, 0u, - kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - dev_dbg(kbdev->dev, "Zap: Ctx %pK is in RunPool", kctx); - - /* Disable the ctx from submitting any more jobs */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - kbasep_js_clear_submit_allowed(js_devdata, kctx); - - /* Retain and (later) release the context whilst it is now - * disallowed from submitting jobs - ensures that someone - * somewhere will be removing the context later on - */ - was_retained = kbase_ctx_sched_inc_refcount_nolock(kctx); - - /* Since it's scheduled and we have the jsctx_mutex, it must be - * retained successfully - */ - KBASE_DEBUG_ASSERT(was_retained); - - dev_dbg(kbdev->dev, "Zap: Ctx %pK Kill Any Running jobs", kctx); - - /* Cancel any remaining running jobs for this kctx - if any. - * Submit is disallowed which takes effect immediately, so no - * more new jobs will appear after we do this. - */ - kbase_backend_jm_kill_running_jobs_from_kctx(kctx); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - mutex_unlock(&js_kctx_info->ctx.jsctx_mutex); - mutex_unlock(&js_devdata->queue_mutex); - mutex_unlock(&kctx->jctx.lock); - - dev_dbg(kbdev->dev, - "Zap: Ctx %pK Release (may or may not schedule out immediately)", kctx); - - kbasep_js_runpool_release_ctx(kbdev, kctx); - } - - KBASE_KTRACE_ADD_JM(kbdev, JM_ZAP_DONE, kctx, NULL, 0u, 0u); - - /* After this, you must wait on both the - * kbase_jd_context::zero_jobs_wait and the - * kbasep_js_kctx_info::ctx::is_scheduled_waitq - to wait for the jobs - * to be destroyed, and the context to be de-scheduled (if it was on the - * runpool). - * - * kbase_jd_zap_context() will do this. - */ -} - -static inline int trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - CSTD_UNUSED(kbdev); - return atomic_read(&kctx->refcount); -} - -/** - * kbase_js_foreach_ctx_job(): - Call a function on all jobs in context - * @kctx: Pointer to context. - * @callback: Pointer to function to call for each job. - * - * Call a function on all jobs belonging to a non-queued, non-running - * context, and detach the jobs from the context as it goes. - * - * Due to the locks that might be held at the time of the call, the callback - * may need to defer work on a workqueue to complete its actions (e.g. when - * cancelling jobs) - * - * Atoms will be removed from the queue, so this must only be called when - * cancelling jobs (which occurs as part of context destruction). - * - * The locking conditions on the caller are as follows: - * - it will be holding kbasep_js_kctx_info::ctx::jsctx_mutex. - */ -static void kbase_js_foreach_ctx_job(struct kbase_context *kctx, kbasep_js_ctx_job_cb *callback) -{ - struct kbase_device *kbdev; - unsigned long flags; - unsigned int js; - - kbdev = kctx->kbdev; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - - KBASE_KTRACE_ADD_JM_REFCOUNT(kbdev, JS_POLICY_FOREACH_CTX_JOBS, kctx, NULL, 0u, - trace_get_refcnt(kbdev, kctx)); - - /* Invoke callback on jobs on each slot in turn */ - for (js = 0; js < kbdev->gpu_props.num_job_slots; js++) - jsctx_queue_foreach(kctx, js, callback); - - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -} - -base_jd_prio kbase_js_priority_check(struct kbase_device *kbdev, base_jd_prio priority) -{ - struct priority_control_manager_device *pcm_device = kbdev->pcm_dev; - int req_priority, out_priority; - - req_priority = kbasep_js_atom_prio_to_sched_prio(priority); - out_priority = req_priority; - /* Does not use pcm defined priority check if PCM not defined or if - * kbasep_js_atom_prio_to_sched_prio returns an error - * (KBASE_JS_ATOM_SCHED_PRIO_INVALID). - */ - if (pcm_device && (req_priority != KBASE_JS_ATOM_SCHED_PRIO_INVALID)) - out_priority = pcm_device->ops.pcm_scheduler_priority_check(pcm_device, current, - req_priority); - return kbasep_js_sched_prio_to_atom_prio(kbdev, out_priority); -} diff --git a/drivers/gpu/arm/valhall/mali_kbase_js.h b/drivers/gpu/arm/valhall/mali_kbase_js.h deleted file mode 100644 index 89c3b45c735b..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_js.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Job Scheduler APIs. - */ - -#ifndef _KBASE_JS_H_ -#define _KBASE_JS_H_ - -#include "context/mali_kbase_context.h" -#include "mali_kbase_defs.h" -#include "mali_kbase_debug.h" -#include -#include "jm/mali_kbase_jm_js.h" -#include "jm/mali_kbase_js_defs.h" - -#endif /* _KBASE_JS_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.c b/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.c deleted file mode 100644 index 6fc6b8a93027..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.c +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include - -/* - * Private functions follow - */ - -/** - * kbasep_js_ctx_attr_runpool_retain_attr - Check whether a ctx has a certain attribute - * and if so, retain that attribute on the runpool. - * - * @kbdev: Device pointer - * @kctx: KBase context - * @attribute: Atribute to check/retain - * - * Requires: - * - jsctx mutex - * - runpool_irq spinlock - * - ctx is scheduled on the runpool - * - * Return: true indicates a change in ctx attributes state of the runpool. - * In this state, the scheduler might be able to submit more jobs than - * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() - * or similar is called sometime later. - * false indicates no change in ctx attributes state of the runpool. - */ -static bool kbasep_js_ctx_attr_runpool_retain_attr(struct kbase_device *kbdev, - struct kbase_context *kctx, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - bool runpool_state_changed = false; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - lockdep_assert_held(&kbdev->hwaccess_lock); - - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) { - KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] < S8_MAX); - ++(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); - - if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 1) { - /* First refcount indicates a state change */ - runpool_state_changed = true; - KBASE_KTRACE_ADD_JM(kbdev, JS_CTX_ATTR_NOW_ON_RUNPOOL, kctx, NULL, 0u, - attribute); - } - } - - return runpool_state_changed; -} - -/** - * kbasep_js_ctx_attr_runpool_release_attr - Check whether a ctx has a certain attribute, - * and if so, release that attribute on the runpool. - * - * @kbdev: Device pointer - * @kctx: KBase context - * @attribute: Atribute to release - * - * Requires: - * - jsctx mutex - * - runpool_irq spinlock - * - ctx is scheduled on the runpool - * - * Return: true indicates a change in ctx attributes state of the runpool. - * In this state, the scheduler might be able to submit more jobs than - * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() - * or similar is called sometime later. - * false indicates no change in ctx attributes state of the runpool. - */ -static bool kbasep_js_ctx_attr_runpool_release_attr(struct kbase_device *kbdev, - struct kbase_context *kctx, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_device_data *js_devdata; - struct kbasep_js_kctx_info *js_kctx_info; - bool runpool_state_changed = false; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_devdata = &kbdev->js_data; - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - lockdep_assert_held(&kbdev->hwaccess_lock); - KBASE_DEBUG_ASSERT(kbase_ctx_flag(kctx, KCTX_SCHEDULED)); - - if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, attribute) != false) { - KBASE_DEBUG_ASSERT(js_devdata->runpool_irq.ctx_attr_ref_count[attribute] > 0); - --(js_devdata->runpool_irq.ctx_attr_ref_count[attribute]); - - if (js_devdata->runpool_irq.ctx_attr_ref_count[attribute] == 0) { - /* Last de-refcount indicates a state change */ - runpool_state_changed = true; - KBASE_KTRACE_ADD_JM(kbdev, JS_CTX_ATTR_NOW_OFF_RUNPOOL, kctx, NULL, 0u, - attribute); - } - } - - return runpool_state_changed; -} - -/** - * kbasep_js_ctx_attr_ctx_retain_attr - Retain a certain attribute on a ctx, - * also retaining it on the runpool if the context is scheduled. - * - * @kbdev: Device pointer - * @kctx: KBase context - * @attribute: Atribute to retain - * - * Requires: - * - jsctx mutex - * - If the context is scheduled, then runpool_irq spinlock must also be held - * - * Return: true indicates a change in ctx attributes state of the runpool. - * This may allow the scheduler to submit more jobs than previously. - * false indicates no change in ctx attributes state of the runpool. - */ -static bool kbasep_js_ctx_attr_ctx_retain_attr(struct kbase_device *kbdev, - struct kbase_context *kctx, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_kctx_info *js_kctx_info; - bool runpool_state_changed = false; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&kbdev->hwaccess_lock); - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] < U32_MAX); - - ++(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); - - if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && - js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { - /* Only ref-count the attribute on the runpool for the first time this contexts sees this attribute */ - KBASE_KTRACE_ADD_JM(kbdev, JS_CTX_ATTR_NOW_ON_CTX, kctx, NULL, 0u, attribute); - runpool_state_changed = - kbasep_js_ctx_attr_runpool_retain_attr(kbdev, kctx, attribute); - } - - return runpool_state_changed; -} - -/** - * kbasep_js_ctx_attr_ctx_release_attr - Release a certain attribute on a ctx, - * also releasing it from the runpool if the context is scheduled. - * - * @kbdev: Device pointer - * @kctx: KBase context - * @attribute: Atribute to release - * - * Requires: - * - jsctx mutex - * - If the context is scheduled, then runpool_irq spinlock must also be held - * - * Return: true indicates a change in ctx attributes state of the runpool. - * This may allow the scheduler to submit more jobs than previously. - * false indicates no change in ctx attributes state of the runpool. - */ -static bool kbasep_js_ctx_attr_ctx_release_attr(struct kbase_device *kbdev, - struct kbase_context *kctx, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_kctx_info *js_kctx_info; - bool runpool_state_changed = false; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_kctx_info = &kctx->jctx.sched_info; - - lockdep_assert_held(&js_kctx_info->ctx.jsctx_mutex); - KBASE_DEBUG_ASSERT(js_kctx_info->ctx.ctx_attr_ref_count[attribute] > 0); - - if (kbase_ctx_flag(kctx, KCTX_SCHEDULED) && - js_kctx_info->ctx.ctx_attr_ref_count[attribute] == 1) { - lockdep_assert_held(&kbdev->hwaccess_lock); - /* Only de-ref-count the attribute on the runpool when this is the last ctx-reference to it */ - runpool_state_changed = - kbasep_js_ctx_attr_runpool_release_attr(kbdev, kctx, attribute); - KBASE_KTRACE_ADD_JM(kbdev, JS_CTX_ATTR_NOW_OFF_CTX, kctx, NULL, 0u, attribute); - } - - /* De-ref must happen afterwards, because kbasep_js_ctx_attr_runpool_release() needs to check it too */ - --(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); - - return runpool_state_changed; -} - -/* - * More commonly used public functions - */ - -void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - bool runpool_state_changed; - int i; - - /* Retain any existing attributes */ - for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { - if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr)i) != false) { - /* The context is being scheduled in, so update the runpool with the new attributes */ - runpool_state_changed = kbasep_js_ctx_attr_runpool_retain_attr( - kbdev, kctx, (enum kbasep_js_ctx_attr)i); - - /* We don't need to know about state changed, because retaining a - * context occurs on scheduling it, and that itself will also try - * to run new atoms - */ - CSTD_UNUSED(runpool_state_changed); - } - } -} - -bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) -{ - bool runpool_state_changed = false; - int i; - - /* Release any existing attributes */ - for (i = 0; i < KBASEP_JS_CTX_ATTR_COUNT; ++i) { - if (kbasep_js_ctx_attr_is_attr_on_ctx(kctx, (enum kbasep_js_ctx_attr)i) != false) { - /* The context is being scheduled out, so update the runpool on the removed attributes */ - runpool_state_changed |= kbasep_js_ctx_attr_runpool_release_attr( - kbdev, kctx, (enum kbasep_js_ctx_attr)i); - } - } - - return runpool_state_changed; -} - -void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *katom) -{ - bool runpool_state_changed = false; - base_jd_core_req core_req; - - KBASE_DEBUG_ASSERT(katom); - core_req = katom->core_req; - - if (core_req & BASE_JD_REQ_ONLY_COMPUTE) - runpool_state_changed |= - kbasep_js_ctx_attr_ctx_retain_attr(kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); - else - runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr( - kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); - - if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && - (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { - /* Atom that can run on slot1 or slot2, and can use all cores */ - runpool_state_changed |= kbasep_js_ctx_attr_ctx_retain_attr( - kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); - } - - /* We don't need to know about state changed, because retaining an atom - * occurs on adding it, and that itself will also try to run new atoms - */ - CSTD_UNUSED(runpool_state_changed); -} - -bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state) -{ - bool runpool_state_changed = false; - base_jd_core_req core_req; - - KBASE_DEBUG_ASSERT(katom_retained_state); - core_req = katom_retained_state->core_req; - - /* No-op for invalid atoms */ - if (kbasep_js_atom_retained_state_is_valid(katom_retained_state) == false) - return false; - - if (core_req & BASE_JD_REQ_ONLY_COMPUTE) - runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr( - kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE); - else - runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr( - kbdev, kctx, KBASEP_JS_CTX_ATTR_NON_COMPUTE); - - if ((core_req & (BASE_JD_REQ_CS | BASE_JD_REQ_ONLY_COMPUTE | BASE_JD_REQ_T)) != 0 && - (core_req & (BASE_JD_REQ_COHERENT_GROUP | BASE_JD_REQ_SPECIFIC_COHERENT_GROUP)) == 0) { - /* Atom that can run on slot1 or slot2, and can use all cores */ - runpool_state_changed |= kbasep_js_ctx_attr_ctx_release_attr( - kbdev, kctx, KBASEP_JS_CTX_ATTR_COMPUTE_ALL_CORES); - } - - return runpool_state_changed; -} diff --git a/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.h b/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.h deleted file mode 100644 index 471f54081d75..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_js_ctx_attr.h +++ /dev/null @@ -1,152 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Job Scheduler Context Attribute APIs - */ - -#ifndef _KBASE_JS_CTX_ATTR_H_ -#define _KBASE_JS_CTX_ATTR_H_ - -/** - * kbasep_js_ctx_attr_runpool_retain_ctx - Retain all attributes of a context - * - * @kbdev: KBase device - * @kctx: KBase context - * - * This occurs on scheduling in the context on the runpool (but after - * is_scheduled is set) - * - * Requires: - * - jsctx mutex - * - runpool_irq spinlock - * - ctx->is_scheduled is true - */ -void kbasep_js_ctx_attr_runpool_retain_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbasep_js_ctx_attr_runpool_release_ctx - Release all attributes of a context - * - * @kbdev: KBase device - * @kctx: KBase context - * - * This occurs on scheduling out the context from the runpool (but before - * is_scheduled is cleared) - * - * Requires: - * - jsctx mutex - * - runpool_irq spinlock - * - ctx->is_scheduled is true - * - * Return: true indicates a change in ctx attributes state of the runpool. - * In this state, the scheduler might be able to submit more jobs than - * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() - * or similar is called sometime later. - * false indicates no change in ctx attributes state of the runpool. - */ -bool kbasep_js_ctx_attr_runpool_release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx); - -/** - * kbasep_js_ctx_attr_ctx_retain_atom - Retain all attributes of an atom - * - * @kbdev: KBase device - * @kctx: KBase context - * @katom: Atom - * - * This occurs on adding an atom to a context - * - * Requires: - * - jsctx mutex - * - If the context is scheduled, then runpool_irq spinlock must also be held - */ -void kbasep_js_ctx_attr_ctx_retain_atom(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_jd_atom *katom); - -/** - * kbasep_js_ctx_attr_ctx_release_atom - Release all attributes of an atom, - * given its retained state. - * - * @kbdev: KBase device - * @kctx: KBase context - * @katom_retained_state: Retained state - * - * This occurs after (permanently) removing an atom from a context - * - * Requires: - * - jsctx mutex - * - If the context is scheduled, then runpool_irq spinlock must also be held - * - * This is a no-op when \a katom_retained_state is invalid. - * - * Return: true indicates a change in ctx attributes state of the runpool. - * In this state, the scheduler might be able to submit more jobs than - * previously, and so the caller should ensure kbasep_js_try_run_next_job_nolock() - * or similar is called sometime later. - * false indicates no change in ctx attributes state of the runpool. - */ -bool kbasep_js_ctx_attr_ctx_release_atom(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbasep_js_atom_retained_state *katom_retained_state); - -/* - * Requires: - * - runpool_irq spinlock - */ -static inline s8 kbasep_js_ctx_attr_count_on_runpool(struct kbase_device *kbdev, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_device_data *js_devdata; - - KBASE_DEBUG_ASSERT(kbdev != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_devdata = &kbdev->js_data; - - return js_devdata->runpool_irq.ctx_attr_ref_count[attribute]; -} - -/* - * Requires: - * - runpool_irq spinlock - */ -static inline bool kbasep_js_ctx_attr_is_attr_on_runpool(struct kbase_device *kbdev, - enum kbasep_js_ctx_attr attribute) -{ - /* In general, attributes are 'on' when they have a non-zero refcount (note: the refcount will never be < 0) */ - return (bool)kbasep_js_ctx_attr_count_on_runpool(kbdev, attribute); -} - -/* - * Requires: - * - jsctx mutex - */ -static inline bool kbasep_js_ctx_attr_is_attr_on_ctx(struct kbase_context *kctx, - enum kbasep_js_ctx_attr attribute) -{ - struct kbasep_js_kctx_info *js_kctx_info; - - KBASE_DEBUG_ASSERT(kctx != NULL); - KBASE_DEBUG_ASSERT(attribute < KBASEP_JS_CTX_ATTR_COUNT); - js_kctx_info = &kctx->jctx.sched_info; - - /* In general, attributes are 'on' when they have a refcount (which should never be < 0) */ - return (bool)(js_kctx_info->ctx.ctx_attr_ref_count[attribute]); -} - -#endif /* _KBASE_JS_DEFS_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.c b/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.c deleted file mode 100644 index 13e225507017..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.c +++ /dev/null @@ -1,880 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * mali_kbase_kinstr_jm.c - * Kernel driver public interface to job manager atom tracing - */ - -#include "mali_kbase_kinstr_jm.h" -#include - -#include "mali_kbase.h" -#include "mali_kbase_linux.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Explicitly include epoll header for old kernels. Not required from 4.16. */ -#if KERNEL_VERSION(4, 16, 0) > LINUX_VERSION_CODE -#include -#endif - -/* Define static_assert(). - * - * The macro was introduced in kernel 5.1. But older vendor kernels may define - * it too. - */ -#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE -#include -#elif !defined(static_assert) -// Stringify the expression if no message is given. -#define static_assert(e, ...) __static_assert(e, #__VA_ARGS__, #e) -#define __static_assert(e, msg, ...) _Static_assert(e, msg) -#endif - -/* The module printing prefix */ -#define PR_ "mali_kbase_kinstr_jm: " - -/* Allows us to perform ASM goto for the tracing - * https://www.kernel.org/doc/Documentation/static-keys.txt - */ -DEFINE_STATIC_KEY_FALSE(basep_kinstr_jm_reader_static_key); - -#define KBASE_KINSTR_JM_VERSION 2 - -/** - * struct kbase_kinstr_jm - The context for the kernel job manager atom tracing - * @readers: a bitlocked list of opened readers. Readers are attached to the - * private data of a file descriptor that the user opens with the - * KBASE_IOCTL_KINSTR_JM_FD IO control call. - * @refcount: reference count for the context. Any reader will have a link - * back to the context so that they can remove themselves from the - * list. - * - * This is opaque outside this compilation unit - */ -struct kbase_kinstr_jm { - struct hlist_bl_head readers; - struct kref refcount; -}; - -/** - * struct kbase_kinstr_jm_atom_state_change - Represents an atom changing to a - * new state - * @timestamp: Raw monotonic nanoseconds of the state change - * @state: The state that the atom has moved to - * @atom: The atom number that has changed state - * @flags: Flags associated with the state change. See - * KBASE_KINSTR_JM_ATOM_STATE_FLAG_* defines. - * @reserved: Reserved for future use. - * @data: Extra data for the state change. Active member depends on state. - * @data.start: Extra data for the state change. Active member depends on - * state. - * @data.start.slot: Extra data for the state change. Active member depends on - * state. - * @data.padding: Padding - * - * We can add new fields to the structure and old user code will gracefully - * ignore the new fields. - * - * We can change the size of the structure and old user code will gracefully - * skip over the new size via `struct kbase_kinstr_jm_fd_out->size`. - * - * If we remove fields, the version field in `struct - * kbase_kinstr_jm_fd_out->version` will be incremented and old user code will - * gracefully fail and tell the user that the kernel API is too new and has - * backwards-incompatible changes. Note that one userspace can opt to handle - * multiple kernel major versions of the structure. - * - * If we need to change the _meaning_ of one of the fields, i.e. the state - * machine has had a incompatible change, we can keep the same members in the - * structure and update the version as above. User code will no longer - * recognise that it has the supported field and can gracefully explain to the - * user that the kernel API is no longer supported. - * - * When making changes to this structure, make sure they are either: - * - additions to the end (for minor version bumps (i.e. only a size increase)) - * such that the layout of existing fields doesn't change, or; - * - update the version reported to userspace so that it can fail explicitly. - */ -struct kbase_kinstr_jm_atom_state_change { - u64 timestamp; - s8 state; /* enum kbase_kinstr_jm_reader_atom_state */ - u8 atom; - u8 flags; - u8 reserved[1]; - /* Tagged union based on state. Ensure members are aligned correctly! */ - union { - struct { - u8 slot; - } start; - u8 padding[4]; - } data; -}; -static_assert(((1 << 8 * sizeof(((struct kbase_kinstr_jm_atom_state_change *)0)->state)) - 1) >= - KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT); - -#define KBASE_KINSTR_JM_ATOM_STATE_FLAG_OVERFLOW BIT(0) - -/** - * struct reader_changes - The circular buffer of kernel atom state changes - * @data: The allocated buffer. This is allocated when the user requests - * the reader file descriptor. It is released when the user calls - * close() on the fd. When accessing this, lock the producer spin - * lock to prevent races on the allocated memory. The consume lock - * does not need to be held because newly-inserted data will always - * be outside the currenly-read range. - * @producer: The producing spinlock which allows us to push changes into the - * buffer at the same time as a user read occurring. This needs to - * be locked when saving/restoring the IRQ because we can receive an - * interrupt from the GPU when an atom completes. The CPU could have - * a task preempted that is holding this lock. - * @consumer: The consuming mutex which locks around the user read(). - * Must be held when updating the tail of the circular buffer. - * @head: The head of the circular buffer. Can be used with Linux @c CIRC_ - * helpers. The producer should lock and update this with an SMP - * store when a new change lands. The consumer can read with an - * SMP load. This allows the producer to safely insert new changes - * into the circular buffer. - * @tail: The tail of the circular buffer. Can be used with Linux @c CIRC_ - * helpers. The producer should do a READ_ONCE load and the consumer - * should SMP store. - * @size: The number of changes that are allowed in @c data. Can be used - * with Linux @c CIRC_ helpers. Will always be a power of two. The - * producer lock should be held when updating this and stored with - * an SMP release memory barrier. This means that the consumer can - * do an SMP load. - * @threshold: The number of changes above which threads polling on the reader - * file descriptor will be woken up. - */ -struct reader_changes { - struct kbase_kinstr_jm_atom_state_change *data; - spinlock_t producer; - struct mutex consumer; - u32 head; - u32 tail; - u32 size; - u32 threshold; -}; - -/** - * reader_changes_is_valid_size() - Determines if requested changes buffer size - * is valid. - * @size: The requested memory size - * - * We have a constraint that the underlying physical buffer must be a - * power of two so that we can use the efficient circular buffer helpers that - * the kernel provides. It also needs to be representable within a u32. - * - * Return: - * * true - the size is valid - * * false - the size is invalid - */ -static inline bool reader_changes_is_valid_size(const size_t size) -{ - const size_t elem_size = sizeof(*((struct reader_changes *)0)->data); - const size_t size_size = sizeof(((struct reader_changes *)0)->size); - const size_t size_max = (1ull << (size_size * 8)) - 1; - - return is_power_of_2(size) && /* Is a power of two */ - ((size / elem_size) <= size_max); /* Small enough */ -} - -/** - * reader_changes_init() - Initializes the reader changes and allocates the - * changes buffer - * @changes: The context pointer, must point to a zero-inited allocated reader - * changes structure. We may support allocating the structure in the - * future. - * @size: The requested changes buffer size - * - * Return: - * (0, U16_MAX] - the number of data elements allocated - * -ERANGE - the requested memory size was invalid - * -ENOMEM - could not allocate the memory - */ -static int reader_changes_init(struct reader_changes *const changes, const size_t size) -{ - BUILD_BUG_ON((PAGE_SIZE % sizeof(*changes->data)) != 0); - - if (!reader_changes_is_valid_size(size)) { - pr_warn(PR_ "invalid size %zu\n", size); - return -ERANGE; - } - - changes->data = vmalloc(size); - if (!changes->data) - return -ENOMEM; - - spin_lock_init(&changes->producer); - mutex_init(&changes->consumer); - - changes->size = size / sizeof(*changes->data); - changes->threshold = - min(((size_t)(changes->size)) / 4, ((size_t)(PAGE_SIZE)) / sizeof(*changes->data)); - - return (int)changes->size; -} - -/** - * reader_changes_term() - Cleans up a reader changes structure - * @changes: The context to clean up - * - * Releases the allocated state changes memory - */ -static void reader_changes_term(struct reader_changes *const changes) -{ - struct kbase_kinstr_jm_atom_state_change *data = NULL; - unsigned long irq; - - /* - * Although changes->data is used on the consumer side, too, no active - * consumer is possible by the time we clean up the reader changes, so - * no need to take the consumer lock. However, we do need the producer - * lock because the list removal can race with list traversal. - */ - spin_lock_irqsave(&changes->producer, irq); - swap(changes->data, data); - spin_unlock_irqrestore(&changes->producer, irq); - - mutex_destroy(&changes->consumer); - vfree(data); -} - -/** - * reader_changes_count_locked() - Retrieves the count of state changes from the - * tail to the physical end of the buffer - * @changes: The state changes context - * - * The consumer mutex must be held. Uses the CIRC_CNT_TO_END macro to - * determine the count, so there may be more items. However, that's the maximum - * number that can be read in one contiguous read. - * - * Return: the number of changes in the circular buffer until the end of the - * allocation - */ -static u32 reader_changes_count_locked(struct reader_changes *const changes) -{ - u32 head; - - lockdep_assert_held_once(&changes->consumer); - - head = smp_load_acquire(&changes->head); - - return CIRC_CNT_TO_END(head, changes->tail, changes->size); -} - -/** - * reader_changes_count() - Retrieves the count of state changes from the - * tail to the physical end of the buffer - * @changes: The state changes context - * - * Return: the number of changes in the circular buffer until the end of the - * allocation - */ -static u32 reader_changes_count(struct reader_changes *const changes) -{ - u32 ret; - - mutex_lock(&changes->consumer); - ret = reader_changes_count_locked(changes); - mutex_unlock(&changes->consumer); - return ret; -} - -/** - * reader_changes_push() - Pushes a change into the reader circular buffer. - * @changes: The buffer to insert the change into - * @change: Kernel atom change to insert - * @wait_queue: The queue to be kicked when changes should be read from - * userspace. Kicked when a threshold is reached or there is - * overflow. - */ -static void reader_changes_push(struct reader_changes *const changes, - const struct kbase_kinstr_jm_atom_state_change *const change, - wait_queue_head_t *const wait_queue) -{ - u32 head, tail, size, space; - unsigned long irq; - struct kbase_kinstr_jm_atom_state_change *data; - - spin_lock_irqsave(&changes->producer, irq); - - /* We may be called for a reader_changes that's awaiting cleanup. */ - data = changes->data; - if (!data) - goto unlock; - - size = changes->size; - head = changes->head; - tail = smp_load_acquire(&changes->tail); - - space = CIRC_SPACE(head, tail, size); - if (space >= 1) { - data[head] = *change; - if (space == 1) { - data[head].flags |= KBASE_KINSTR_JM_ATOM_STATE_FLAG_OVERFLOW; - pr_warn(PR_ "overflow of circular buffer\n"); - } - smp_store_release(&changes->head, (head + 1) & (size - 1)); - } - - /* Wake for either overflow or over-threshold cases. */ - if (CIRC_CNT(head + 1, tail, size) >= changes->threshold) - wake_up_interruptible(wait_queue); - -unlock: - spin_unlock_irqrestore(&changes->producer, irq); -} - -/** - * struct reader - Allows the kernel state changes to be read by user space. - * @node: The node in the @c readers locked list - * @rcu_head: storage for the RCU callback to free this reader (see kfree_rcu) - * @changes: The circular buffer of user changes - * @wait_queue: A wait queue for poll - * @context: a pointer to the parent context that created this reader. Can be - * used to remove the reader from the list of readers. Reference - * counted. - * - * The reader is a circular buffer in kernel space. State changes are pushed - * into the buffer. The flow from user space is: - * - * * Request file descriptor with KBASE_IOCTL_KINSTR_JM_FD. This will - * allocate the kernel side circular buffer with a size specified in the - * ioctl argument. - * * The user will then poll the file descriptor for data - * * Upon receiving POLLIN, perform a read() on the file descriptor to get - * the data out. - * * The buffer memory will be freed when the file descriptor is closed - */ -struct reader { - struct hlist_bl_node node; - struct rcu_head rcu_head; - struct reader_changes changes; - wait_queue_head_t wait_queue; - struct kbase_kinstr_jm *context; -}; - -static struct kbase_kinstr_jm *kbase_kinstr_jm_ref_get(struct kbase_kinstr_jm *const ctx); -static void kbase_kinstr_jm_ref_put(struct kbase_kinstr_jm *const ctx); -static int kbase_kinstr_jm_readers_add(struct kbase_kinstr_jm *const ctx, - struct reader *const reader); -static void kbase_kinstr_jm_readers_del(struct kbase_kinstr_jm *const ctx, - struct reader *const reader); - -/** - * reader_term() - Terminate a instrumentation job manager reader context. - * @reader: Pointer to context to be terminated. - */ -static void reader_term(struct reader *const reader) -{ - if (!reader) - return; - - kbase_kinstr_jm_readers_del(reader->context, reader); - reader_changes_term(&reader->changes); - kbase_kinstr_jm_ref_put(reader->context); - - kfree_rcu(reader, rcu_head); -} - -/** - * reader_init() - Initialise a instrumentation job manager reader context. - * @out_reader: Non-NULL pointer to where the pointer to the created context - * will be stored on success. - * @ctx: the pointer to the parent context. Reference count will be - * increased if initialization is successful - * @num_changes: The number of changes to allocate a buffer for - * - * Return: 0 on success, else error code. - */ -static int reader_init(struct reader **const out_reader, struct kbase_kinstr_jm *const ctx, - size_t const num_changes) -{ - struct reader *reader = NULL; - const size_t change_size = sizeof(struct kbase_kinstr_jm_atom_state_change); - int status; - - if (!out_reader || !ctx || !num_changes) - return -EINVAL; - - reader = kzalloc(sizeof(*reader), GFP_KERNEL); - if (!reader) - return -ENOMEM; - - INIT_HLIST_BL_NODE(&reader->node); - init_waitqueue_head(&reader->wait_queue); - - reader->context = kbase_kinstr_jm_ref_get(ctx); - - status = reader_changes_init(&reader->changes, num_changes * change_size); - if (status < 0) - goto fail; - - status = kbase_kinstr_jm_readers_add(ctx, reader); - if (status < 0) - goto fail; - - *out_reader = reader; - - return 0; - -fail: - kbase_kinstr_jm_ref_put(reader->context); - kfree(reader); - return status; -} - -/** - * reader_release() - Invoked when the reader file descriptor is released - * @node: The inode that the file descriptor that the file corresponds to. In - * our case our reader file descriptor is backed by an anonymous node so - * not much is in this. - * @file: the file data. Our reader context is held in the private data - * Return: zero on success - */ -static int reader_release(struct inode *const node, struct file *const file) -{ - struct reader *const reader = file->private_data; - - CSTD_UNUSED(node); - - reader_term(reader); - file->private_data = NULL; - - return 0; -} - -/** - * reader_changes_copy_to_user() - Copy any changes from a changes structure to - * the user-provided buffer. - * @changes: The changes structure from which to copy. - * @buffer: The user buffer to copy the data to. - * @buffer_size: The number of bytes in the buffer. - * Return: The number of bytes copied or negative errno on failure. - */ -static ssize_t reader_changes_copy_to_user(struct reader_changes *const changes, - char __user *buffer, size_t buffer_size) -{ - ssize_t ret = 0; - struct kbase_kinstr_jm_atom_state_change const *src_buf = READ_ONCE(changes->data); - size_t const entry_size = sizeof(*src_buf); - size_t changes_tail, changes_count, read_size; - size_t copy_size; - - /* Needed for the quick buffer capacity calculation below. - * Note that we can't use is_power_of_2() since old compilers don't - * understand it's a constant expression. - */ -#define is_power_of_two(x) ((x) && !((x) & ((x)-1))) - static_assert(is_power_of_two(sizeof(struct kbase_kinstr_jm_atom_state_change))); -#undef is_power_of_two - - lockdep_assert_held_once(&changes->consumer); - - /* Read continuously until either: - * - we've filled the output buffer, or - * - there are no changes when we check. - * - * If more changes arrive while we're copying to the user, we can copy - * those as well, space permitting. - */ - do { - changes_tail = changes->tail; - changes_count = reader_changes_count_locked(changes); - - if (check_mul_overflow(changes_count, entry_size, ©_size)) { - ret = -EINVAL; - goto exit; - } - - read_size = min(copy_size, buffer_size & ~(entry_size - 1)); - - if (!read_size) - break; - - if (copy_to_user(buffer, &(src_buf[changes_tail]), read_size)) { - ret = -EFAULT; - goto exit; - } - - buffer += read_size; - buffer_size -= read_size; - ret += (ssize_t)read_size; - changes_tail = (changes_tail + read_size / entry_size) & (changes->size - 1); - smp_store_release(&changes->tail, changes_tail); - } while (read_size); -exit: - return ret; -} - -/** - * reader_read() - Handles a read call on the reader file descriptor - * - * @filp: The file that the read was performed on - * @buffer: The destination buffer - * @buffer_size: The maximum number of bytes to read - * @offset: The offset into the 'file' to read from. - * - * Note the destination buffer needs to be fully mapped in userspace or the read - * will fault. - * - * Return: - * * The number of bytes read or: - * * -EBADF - the file descriptor did not have an attached reader - * * -EFAULT - memory access fault - * * -EAGAIN - if the file is set to nonblocking reads with O_NONBLOCK and there - * is no data available - * - * Note: The number of bytes read will always be a multiple of the size of an - * entry. - */ -static ssize_t reader_read(struct file *const filp, char __user *const buffer, - size_t const buffer_size, loff_t *const offset) -{ - struct reader *const reader = filp->private_data; - struct reader_changes *changes; - ssize_t ret; - - CSTD_UNUSED(offset); - - if (!reader) - return -EBADF; - - if (buffer_size < sizeof(struct kbase_kinstr_jm_atom_state_change)) - return -ENOBUFS; - -#if KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE - if (!access_ok(buffer, buffer_size)) - return -EIO; -#else - if (!access_ok(VERIFY_WRITE, buffer, buffer_size)) - return -EIO; -#endif - - changes = &reader->changes; - - mutex_lock(&changes->consumer); - if (!reader_changes_count_locked(changes)) { - if (filp->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto exit; - } - - if (wait_event_interruptible(reader->wait_queue, - !!reader_changes_count_locked(changes))) { - ret = -EINTR; - goto exit; - } - } - - ret = reader_changes_copy_to_user(changes, buffer, buffer_size); - -exit: - mutex_unlock(&changes->consumer); - return ret; -} - -/** - * reader_poll() - Handles a poll call on the reader file descriptor - * @file: The file that the poll was performed on - * @wait: The poll table - * - * The results of the poll will be unreliable if there is no mapped memory as - * there is no circular buffer to push atom state changes into. - * - * Return: - * * 0 - no data ready - * * EPOLLIN | EPOLLRDNORM - state changes have been buffered - * * EPOLLHUP | EPOLLERR - IO control arguments were invalid or the file - * descriptor did not have an attached reader. - */ -static __poll_t reader_poll(struct file *const file, struct poll_table_struct *const wait) -{ - struct reader *reader; - struct reader_changes *changes; - __poll_t mask = 0; - - if (unlikely(!file || !wait)) - return EPOLLHUP | EPOLLERR; - - reader = file->private_data; - if (unlikely(!reader)) - return EPOLLHUP | EPOLLERR; - - changes = &reader->changes; - if (reader_changes_count(changes) >= changes->threshold) - return EPOLLIN | EPOLLRDNORM; - - poll_wait(file, &reader->wait_queue, wait); - - if (reader_changes_count(changes) > 0) - mask |= EPOLLIN | EPOLLRDNORM; - - return mask; -} - -/* The file operations virtual function table */ -static const struct file_operations file_operations = { .owner = THIS_MODULE, - .llseek = no_llseek, - .read = reader_read, - .poll = reader_poll, - .release = reader_release }; - -/* The maximum amount of readers that can be created on a context. */ -static const size_t kbase_kinstr_jm_readers_max = 16; - -/** - * kbase_kinstr_jm_release() - Invoked when the reference count is dropped - * @ref: the context reference count - */ -static void kbase_kinstr_jm_release(struct kref *const ref) -{ - struct kbase_kinstr_jm *const ctx = container_of(ref, struct kbase_kinstr_jm, refcount); - - kfree(ctx); -} - -/** - * kbase_kinstr_jm_ref_get() - Reference counts the instrumentation context - * @ctx: the context to reference count - * Return: the reference counted context - */ -static struct kbase_kinstr_jm *kbase_kinstr_jm_ref_get(struct kbase_kinstr_jm *const ctx) -{ - if (likely(ctx)) - kref_get(&ctx->refcount); - return ctx; -} - -/** - * kbase_kinstr_jm_ref_put() - Dereferences the instrumentation context - * @ctx: the context to lower the reference count on - */ -static void kbase_kinstr_jm_ref_put(struct kbase_kinstr_jm *const ctx) -{ - if (likely(ctx)) - kref_put(&ctx->refcount, kbase_kinstr_jm_release); -} - -/** - * kbase_kinstr_jm_readers_add() - Adds a reader to the list of readers - * @ctx: the instrumentation context - * @reader: the reader to add - * - * Return: - * 0 - success - * -ENOMEM - too many readers already added. - */ -static int kbase_kinstr_jm_readers_add(struct kbase_kinstr_jm *const ctx, - struct reader *const reader) -{ - struct hlist_bl_head *const readers = &ctx->readers; - struct hlist_bl_node *node; - struct reader *temp; - size_t count = 0; - - hlist_bl_lock(readers); - - hlist_bl_for_each_entry_rcu(temp, node, readers, node) - ++count; - - if (kbase_kinstr_jm_readers_max < count) { - hlist_bl_unlock(readers); - return -ENOMEM; - } - - hlist_bl_add_head_rcu(&reader->node, readers); - - hlist_bl_unlock(readers); - - static_branch_inc(&basep_kinstr_jm_reader_static_key); - - return 0; -} - -/** - * kbase_kinstr_jm_readers_del() - Deletes a reader from the list of readers - * @ctx: the instrumentation context - * @reader: the reader to delete - */ -static void kbase_kinstr_jm_readers_del(struct kbase_kinstr_jm *const ctx, - struct reader *const reader) -{ - struct hlist_bl_head *const readers = &ctx->readers; - - hlist_bl_lock(readers); - hlist_bl_del_rcu(&reader->node); - hlist_bl_unlock(readers); - - static_branch_dec(&basep_kinstr_jm_reader_static_key); -} - -int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx, union kbase_kinstr_jm_fd *jm_fd_arg) -{ - struct kbase_kinstr_jm_fd_in const *in; - struct reader *reader; - size_t const change_size = sizeof(struct kbase_kinstr_jm_atom_state_change); - int status; - int fd; - - if (!ctx || !jm_fd_arg) - return -EINVAL; - - in = &jm_fd_arg->in; - - if (!is_power_of_2(in->count)) - return -EINVAL; - - status = reader_init(&reader, ctx, in->count); - if (status < 0) - return status; - - jm_fd_arg->out.version = KBASE_KINSTR_JM_VERSION; - jm_fd_arg->out.size = change_size; - memset(&jm_fd_arg->out.padding, 0, sizeof(jm_fd_arg->out.padding)); - - fd = anon_inode_getfd("[mali_kinstr_jm]", &file_operations, reader, O_CLOEXEC); - if (fd < 0) - reader_term(reader); - - return fd; -} - -int kbase_kinstr_jm_init(struct kbase_kinstr_jm **const out_ctx) -{ - struct kbase_kinstr_jm *ctx = NULL; - - if (!out_ctx) - return -EINVAL; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_HLIST_BL_HEAD(&ctx->readers); - kref_init(&ctx->refcount); - - *out_ctx = ctx; - - return 0; -} - -void kbase_kinstr_jm_term(struct kbase_kinstr_jm *const ctx) -{ - kbase_kinstr_jm_ref_put(ctx); -} - -void kbasep_kinstr_jm_atom_state(struct kbase_jd_atom *const katom, - const enum kbase_kinstr_jm_reader_atom_state state) -{ - struct kbase_context *const kctx = katom->kctx; - struct kbase_kinstr_jm *const ctx = kctx->kinstr_jm; - const u8 id = kbase_jd_atom_id(kctx, katom); - struct kbase_kinstr_jm_atom_state_change change = { .timestamp = ktime_get_raw_ns(), - .atom = id, - .state = state }; - struct reader *reader; - struct hlist_bl_node *node; - - WARN(KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT < state || 0 > state, - PR_ "unsupported katom (%u) state (%i)", id, state); - - switch (state) { - case KBASE_KINSTR_JM_READER_ATOM_STATE_START: - change.data.start.slot = katom->slot_nr; - break; - default: - break; - } - - rcu_read_lock(); - hlist_bl_for_each_entry_rcu(reader, node, &ctx->readers, node) - reader_changes_push(&reader->changes, &change, &reader->wait_queue); - rcu_read_unlock(); -} - -KBASE_EXPORT_TEST_API(kbasep_kinstr_jm_atom_state); - -void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const katom) -{ - struct kbase_context *const kctx = katom->kctx; - struct kbase_device *const kbdev = kctx->kbdev; - const unsigned int slot = katom->slot_nr; - struct kbase_jd_atom *const submitted = kbase_gpu_inspect(kbdev, slot, 0); - - BUILD_BUG_ON(SLOT_RB_SIZE != 2); - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (WARN_ON(slot >= GPU_MAX_JOB_SLOTS)) - return; - if (WARN_ON(!submitted)) - return; - - if (submitted == katom) - kbase_kinstr_jm_atom_state_start(katom); -} - -void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const katom) -{ - struct kbase_context *const kctx = katom->kctx; - struct kbase_device *const kbdev = kctx->kbdev; - const unsigned int slot = katom->slot_nr; - struct kbase_jd_atom *const submitted = kbase_gpu_inspect(kbdev, slot, 0); - struct kbase_jd_atom *const queued = kbase_gpu_inspect(kbdev, slot, 1); - - BUILD_BUG_ON(SLOT_RB_SIZE != 2); - - lockdep_assert_held(&kbdev->hwaccess_lock); - - if (WARN_ON(slot >= GPU_MAX_JOB_SLOTS)) - return; - if (WARN_ON(!submitted)) - return; - if (WARN_ON((submitted != katom) && (queued != katom))) - return; - - if (queued == katom) - return; - - if (katom->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) - kbase_kinstr_jm_atom_state_stop(katom); - if (queued && queued->gpu_rb_state == KBASE_ATOM_GPU_RB_SUBMITTED) - kbase_kinstr_jm_atom_state_start(queued); -} diff --git a/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.h b/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.h deleted file mode 100644 index ae5b63f0372f..000000000000 --- a/drivers/gpu/arm/valhall/mali_kbase_kinstr_jm.h +++ /dev/null @@ -1,257 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * mali_kbase_kinstr_jm.h - * Kernel driver public interface to job manager atom tracing. This API provides - * a method to get the atom state changes into user space. - * - * The flow of operation is: - * - * | kernel | user | - * | ----------------------------------- | ----------------------------------- | - * | Initialize API with | | - * | kbase_kinstr_jm_init() | | - * | | | - * | Kernel code injects states with | | - * | kbase_kinstr_jm_atom_state_*() APIs | | - * | | Call ioctl() to get file descriptor | - * | | via KBASE_IOCTL_KINSTR_JM_FD | - * | Allocates a reader attached to FD | | - * | Allocates circular buffer and | | - * | patches, via ASM goto, the | | - * | kbase_kinstr_jm_atom_state_*() | | - * | | loop: | - * | | Call poll() on FD for POLLIN | - * | When threshold of changes is hit, | | - * | the poll is interrupted with | | - * | POLLIN. If circular buffer is | | - * | full then store the missed count | | - * | and interrupt poll | Call read() to get data from | - * | | circular buffer via the fd | - * | Kernel advances tail of circular | | - * | buffer | | - * | | Close file descriptor | - * | Deallocates circular buffer | | - * | | | - * | Terminate API with | | - * | kbase_kinstr_jm_term() | | - * - * All tracepoints are guarded on a static key. The static key is activated when - * a user space reader gets created. This means that there is negligible cost - * inserting the tracepoints into code when there are no readers. - */ - -#ifndef _KBASE_KINSTR_JM_H_ -#define _KBASE_KINSTR_JM_H_ - -#include - -#ifdef __KERNEL__ -#include -#include -#else -/* empty wrapper macros for userspace */ -#define static_branch_unlikely(key) (1) -#endif /* __KERNEL__ */ - -/* Forward declarations */ -struct kbase_context; -struct kbase_kinstr_jm; -struct kbase_jd_atom; -union kbase_kinstr_jm_fd; - -/** - * kbase_kinstr_jm_init() - Initialise an instrumentation job manager context. - * @ctx: Non-NULL pointer to where the pointer to the created context will - * be stored on success. - * - * Return: 0 on success, else error code. - */ -int kbase_kinstr_jm_init(struct kbase_kinstr_jm **ctx); - -/** - * kbase_kinstr_jm_term() - Terminate an instrumentation job manager context. - * @ctx: Pointer to context to be terminated. - */ -void kbase_kinstr_jm_term(struct kbase_kinstr_jm *ctx); - -/** - * kbase_kinstr_jm_get_fd() - Retrieves a file descriptor that can be used to - * read the atom state changes from userspace - * - * @ctx: Pointer to the initialized context - * @jm_fd_arg: Pointer to the union containing the in/out params - * Return: -1 on failure, valid file descriptor on success - */ -int kbase_kinstr_jm_get_fd(struct kbase_kinstr_jm *const ctx, union kbase_kinstr_jm_fd *jm_fd_arg); - -/** - * kbasep_kinstr_jm_atom_state() - Signifies that an atom has changed state - * @atom: The atom that has changed state - * @state: The new state of the atom - * - * This performs the actual storage of the state ready for user space to - * read the data. It is only called when the static key is enabled from - * kbase_kinstr_jm_atom_state(). There is almost never a need to invoke this - * function directly. - */ -void kbasep_kinstr_jm_atom_state(struct kbase_jd_atom *const atom, - const enum kbase_kinstr_jm_reader_atom_state state); - -/* Allows ASM goto patching to reduce tracing overhead. This is - * incremented/decremented when readers are created and terminated. This really - * shouldn't be changed externally, but if you do, make sure you use - * a static_key_inc()/static_key_dec() pair. - */ -extern struct static_key_false basep_kinstr_jm_reader_static_key; - -/** - * kbase_kinstr_jm_atom_state() - Signifies that an atom has changed state - * @atom: The atom that has changed state - * @state: The new state of the atom - * - * This uses a static key to reduce overhead when tracing is disabled - */ -static inline void kbase_kinstr_jm_atom_state(struct kbase_jd_atom *const atom, - const enum kbase_kinstr_jm_reader_atom_state state) -{ - if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key)) - kbasep_kinstr_jm_atom_state(atom, state); -} - -/** - * kbase_kinstr_jm_atom_state_queue() - Signifies that an atom has entered a - * hardware or software queue. - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_state_queue(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE); -} - -/** - * kbase_kinstr_jm_atom_state_start() - Signifies that work has started on an - * atom - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_state_start(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_START); -} - -/** - * kbase_kinstr_jm_atom_state_stop() - Signifies that work has stopped on an - * atom - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_state_stop(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_STOP); -} - -/** - * kbase_kinstr_jm_atom_state_complete() - Signifies that all work has completed - * on an atom - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_state_complete(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state(atom, KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE); -} - -/** - * kbase_kinstr_jm_atom_queue() - A software *or* hardware atom is queued for - * execution - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_queue(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state_queue(atom); -} - -/** - * kbase_kinstr_jm_atom_complete() - A software *or* hardware atom is fully - * completed - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_complete(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state_complete(atom); -} - -/** - * kbase_kinstr_jm_atom_sw_start() - A software atom has started work - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_sw_start(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state_start(atom); -} - -/** - * kbase_kinstr_jm_atom_sw_stop() - A software atom has stopped work - * @atom: The atom that has changed state - */ -static inline void kbase_kinstr_jm_atom_sw_stop(struct kbase_jd_atom *const atom) -{ - kbase_kinstr_jm_atom_state_stop(atom); -} - -/** - * kbasep_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted - * @atom: The atom that has been submitted - * - * This private implementation should not be called directly, it is protected - * by a static key in kbase_kinstr_jm_atom_hw_submit(). Use that instead. - */ -void kbasep_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom); - -/** - * kbase_kinstr_jm_atom_hw_submit() - A hardware atom has been submitted - * @atom: The atom that has been submitted - */ -static inline void kbase_kinstr_jm_atom_hw_submit(struct kbase_jd_atom *const atom) -{ - if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key)) - kbasep_kinstr_jm_atom_hw_submit(atom); -} - -/** - * kbasep_kinstr_jm_atom_hw_release() - A hardware atom has been released - * @atom: The atom that has been released - * - * This private implementation should not be called directly, it is protected - * by a static key in kbase_kinstr_jm_atom_hw_release(). Use that instead. - */ -void kbasep_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom); - -/** - * kbase_kinstr_jm_atom_hw_release() - A hardware atom has been released - * @atom: The atom that has been released - */ -static inline void kbase_kinstr_jm_atom_hw_release(struct kbase_jd_atom *const atom) -{ - if (static_branch_unlikely(&basep_kinstr_jm_reader_static_key)) - kbasep_kinstr_jm_atom_hw_release(atom); -} - -#endif /* _KBASE_KINSTR_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem.c b/drivers/gpu/arm/valhall/mali_kbase_mem.c index cb2e230fbc91..4f5e1980d772 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem.c @@ -246,9 +246,6 @@ int kbase_mem_init(struct kbase_device *kbdev) } } - kbase_mem_pool_group_config_set_max_size(&kbdev->mem_pool_defaults, - KBASE_MEM_POOL_MAX_SIZE_KCTX); - spin_lock_init(&kbdev->gpu_mem_usage_lock); kbdev->process_root = RB_ROOT; kbdev->dma_buf_root = RB_ROOT; @@ -282,20 +279,37 @@ int kbase_mem_init(struct kbase_device *kbdev) } } of_node_put(mgm_node); + if (unlikely(err)) + goto init_fail; } #endif - if (likely(!err)) { - struct kbase_mem_pool_group_config mem_pool_defaults; + err = kbase_mem_pool_init_no_reclaim(&kbdev->pgd_mem_pool, BASE_PGD_MEM_POOL_MAX_SIZE_KBDEV, + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER, 0, kbdev); - kbase_mem_pool_group_config_set_max_size(&mem_pool_defaults, - KBASE_MEM_POOL_MAX_SIZE_KBDEV); + if (unlikely(err)) + goto init_fail; - err = kbase_mem_pool_group_init(&kbdev->mem_pools, kbdev, &mem_pool_defaults, NULL); - if (likely(!err)) - return err; - } + err = kbase_mem_pool_init_no_reclaim(&kbdev->fw_mem_pools.small, + KBASE_FW_MEM_POOL_MAX_SIZE_KBDEV, + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER, 0, kbdev); + if (unlikely(err)) + goto term_kbase_pgd_mem_pool; + + err = kbase_mem_pool_init_no_reclaim(&kbdev->fw_mem_pools.large, + KBASE_FW_MEM_POOL_MAX_SIZE_KBDEV >> + (KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER - + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER), + KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, 0, kbdev); + + if (likely(!err)) + return err; + + kbase_mem_pool_term(&kbdev->fw_mem_pools.small); +term_kbase_pgd_mem_pool: + kbase_mem_pool_term(&kbdev->pgd_mem_pool); +init_fail: kmem_cache_destroy(kbdev->page_metadata_slab); kbdev->page_metadata_slab = NULL; page_metadata_slab_fail: @@ -324,7 +338,9 @@ void kbase_mem_term(struct kbase_device *kbdev) if (pages != 0) dev_warn(kbdev->dev, "%s: %d pages in use!\n", __func__, pages); - kbase_mem_pool_group_term(&kbdev->mem_pools); + kbase_mem_pool_term(&kbdev->pgd_mem_pool); + kbase_mem_pool_term(&kbdev->fw_mem_pools.small); + kbase_mem_pool_term(&kbdev->fw_mem_pools.large); kbase_mem_migrate_term(kbdev); @@ -848,11 +864,10 @@ static int kbase_do_syncset(struct kbase_context *kctx, struct basep_syncset *ss kbase_gpu_vm_lock(kctx); /* find the region where the virtual address is contained */ - reg = kbase_region_tracker_find_region_enclosing_address(kctx, - sset->mem_handle.basep.handle); + reg = kbase_region_tracker_find_region_enclosing_address(kctx, sset->gpu_va); if (kbase_is_region_invalid_or_free(reg)) { dev_warn(kctx->kbdev->dev, "Can't find a valid region at VA 0x%016llX", - sset->mem_handle.basep.handle); + sset->gpu_va); err = -EINVAL; goto out_unlock; } @@ -938,8 +953,8 @@ int kbase_sync_now(struct kbase_context *kctx, struct basep_syncset *sset) KBASE_DEBUG_ASSERT(kctx != NULL); KBASE_DEBUG_ASSERT(sset != NULL); - if (sset->mem_handle.basep.handle & ~PAGE_MASK) { - dev_warn(kctx->kbdev->dev, "mem_handle: passed parameter is invalid"); + if (sset->gpu_va & ~PAGE_MASK) { + dev_warn(kctx->kbdev->dev, "gpu_va 0x%016llX parameter is invalid", sset->gpu_va); return -EINVAL; } @@ -1003,7 +1018,6 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re goto out; } -#if MALI_USE_CSF if (((kbase_bits_to_zone(reg->flags)) == FIXED_VA_ZONE) || ((kbase_bits_to_zone(reg->flags)) == EXEC_FIXED_VA_ZONE)) { if (reg->flags & KBASE_REG_FIXED_ADDRESS) @@ -1011,7 +1025,6 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re else atomic64_dec(&kctx->num_fixable_allocs); } -#endif /* This will also free the physical pages */ kbase_free_alloced_region(reg); @@ -1137,12 +1150,6 @@ int kbase_update_region_flags(struct kbase_context *kctx, struct kbase_va_region reg->flags |= KBASE_REG_SHARE_IN; } -#if !MALI_USE_CSF - if (flags & BASE_MEM_TILER_ALIGN_TOP) - reg->flags |= KBASE_REG_TILER_ALIGN_TOP; -#endif /* !MALI_USE_CSF */ - -#if MALI_USE_CSF if (flags & BASE_MEM_CSF_EVENT) { reg->flags |= KBASE_REG_CSF_EVENT; reg->flags |= KBASE_REG_PERMANENT_KERNEL_MAPPING; @@ -1155,7 +1162,6 @@ int kbase_update_region_flags(struct kbase_context *kctx, struct kbase_va_region reg->flags &= ~KBASE_REG_GPU_CACHED; } } -#endif /* Set up default MEMATTR usage */ if (!(reg->flags & KBASE_REG_GPU_CACHED)) { @@ -1168,12 +1174,10 @@ int kbase_update_region_flags(struct kbase_context *kctx, struct kbase_va_region "Can't allocate GPU uncached memory due to MMU in Legacy Mode\n"); return -EINVAL; } -#if MALI_USE_CSF } else if (reg->flags & KBASE_REG_CSF_EVENT) { WARN_ON(!(reg->flags & KBASE_REG_SHARE_BOTH)); reg->flags |= KBASE_REG_MEMATTR_INDEX(KBASE_MEMATTR_INDEX_SHARED); -#endif } else if (kctx->kbdev->system_coherency == COHERENCY_ACE && (reg->flags & KBASE_REG_SHARE_BOTH)) { reg->flags |= KBASE_REG_MEMATTR_INDEX(KBASE_MEMATTR_INDEX_DEFAULT_ACE); @@ -1193,10 +1197,8 @@ int kbase_update_region_flags(struct kbase_context *kctx, struct kbase_va_region if (flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) reg->flags |= KBASE_REG_GPU_VA_SAME_4GB_PAGE; -#if MALI_USE_CSF if (flags & BASE_MEM_FIXED) reg->flags |= KBASE_REG_FIXED_ADDRESS; -#endif if (flags & BASEP_MEM_ACTIVE_JIT_ALLOC) reg->flags |= BASEP_MEM_ACTIVE_JIT_ALLOC; @@ -2085,26 +2087,12 @@ bool kbase_check_alloc_flags(struct kbase_context *kctx, unsigned long flags) (flags & (BASE_MEM_PROT_GPU_WR | BASE_MEM_GROW_ON_GPF))) return false; -#if !MALI_USE_CSF - /* GPU executable memory also cannot have the top of its initial - * commit aligned to 'extension' - */ - if ((flags & BASE_MEM_PROT_GPU_EX) && (flags & BASE_MEM_TILER_ALIGN_TOP)) - return false; -#endif /* !MALI_USE_CSF */ - /* To have an allocation lie within a 4GB chunk is required only for * TLS memory, which will never be used to contain executable code. */ if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) && (flags & BASE_MEM_PROT_GPU_EX)) return false; -#if !MALI_USE_CSF - /* TLS memory should also not be used for tiler heap */ - if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) && (flags & BASE_MEM_TILER_ALIGN_TOP)) - return false; -#endif /* !MALI_USE_CSF */ - /* GPU should have at least read or write access otherwise there is no * reason for allocating. */ @@ -2127,13 +2115,11 @@ bool kbase_check_alloc_flags(struct kbase_context *kctx, unsigned long flags) (BASE_MEM_COHERENT_LOCAL | BASE_MEM_COHERENT_SYSTEM)) return false; -#if MALI_USE_CSF if ((flags & BASE_MEM_SAME_VA) && (flags & (BASE_MEM_FIXABLE | BASE_MEM_FIXED))) return false; if ((flags & BASE_MEM_FIXABLE) && (flags & BASE_MEM_FIXED)) return false; -#endif /* Cannot be set only allocation, only with base_mem_set */ if ((flags & BASE_MEM_DONT_NEED) && @@ -2155,30 +2141,13 @@ bool kbase_check_alloc_flags(struct kbase_context *kctx, unsigned long flags) (mali_kbase_supports_reject_alloc_mem_unused_bit_7(kctx->api_version))) return false; -#if !MALI_USE_CSF - if ((flags & BASE_MEM_UNUSED_BIT_8) && - (mali_kbase_supports_reject_alloc_mem_unused_bit_8(kctx->api_version))) - return false; - - if ((flags & BASE_MEM_UNUSED_BIT_19) && - (mali_kbase_supports_reject_alloc_mem_unused_bit_19(kctx->api_version))) - return false; - -#else if ((flags & BASE_MEM_UNUSED_BIT_20) && (mali_kbase_supports_reject_alloc_mem_unused_bit_20(kctx->api_version))) return false; -#endif /* !MALI_USE_CSF */ if ((flags & BASE_MEM_UNUSED_BIT_27) && (mali_kbase_supports_reject_alloc_mem_unused_bit_27(kctx->api_version))) return false; -#if !MALI_USE_CSF - - if ((flags & BASE_MEM_UNUSED_BIT_29) && - (mali_kbase_supports_reject_alloc_mem_unused_bit_29(kctx->api_version))) - return false; -#endif /* !MALI_USE_CSF */ return true; } @@ -2201,15 +2170,9 @@ bool kbase_check_import_flags(unsigned long flags) if (flags & BASE_MEM_GROW_ON_GPF) return false; -#if MALI_USE_CSF /* Imported memory cannot be fixed */ if ((flags & (BASE_MEM_FIXED | BASE_MEM_FIXABLE))) return false; -#else - /* Imported memory cannot be aligned to the end of its initial commit */ - if (flags & BASE_MEM_TILER_ALIGN_TOP) - return false; -#endif /* !MALI_USE_CSF */ /* GPU should have at least read or write access otherwise there is no * reason for importing. @@ -2267,59 +2230,12 @@ int kbase_check_alloc_sizes(struct kbase_context *kctx, unsigned long flags, u64 return -EINVAL; } -#if !MALI_USE_CSF - if ((flags & BASE_MEM_TILER_ALIGN_TOP) && (test_reg.extension == 0)) { - dev_warn(dev, KBASE_MSG_PRE "BASE_MEM_TILER_ALIGN_TOP but extension == 0\n"); - return -EINVAL; - } - - if (!(flags & (BASE_MEM_GROW_ON_GPF | BASE_MEM_TILER_ALIGN_TOP)) && - test_reg.extension != 0) { - dev_warn( - dev, KBASE_MSG_PRE - "neither BASE_MEM_GROW_ON_GPF nor BASE_MEM_TILER_ALIGN_TOP set but extension != 0\n"); - return -EINVAL; - } -#else if (!(flags & BASE_MEM_GROW_ON_GPF) && test_reg.extension != 0) { dev_warn(dev, KBASE_MSG_PRE "BASE_MEM_GROW_ON_GPF not set but extension != 0\n"); return -EINVAL; } -#endif /* !MALI_USE_CSF */ -#if !MALI_USE_CSF - /* BASE_MEM_TILER_ALIGN_TOP memory has a number of restrictions */ - if (flags & BASE_MEM_TILER_ALIGN_TOP) { -#define KBASE_MSG_PRE_FLAG KBASE_MSG_PRE "BASE_MEM_TILER_ALIGN_TOP and " - unsigned long small_extension; - - if (large_extension > BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES) { - dev_warn(dev, KBASE_MSG_PRE_FLAG "extension==%lld pages exceeds limit %lld", - (unsigned long long)large_extension, - BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES); - return -EINVAL; - } - /* For use with is_power_of_2, which takes unsigned long, so - * must ensure e.g. on 32-bit kernel it'll fit in that type - */ - small_extension = (unsigned long)large_extension; - - if (!is_power_of_2(small_extension)) { - dev_warn(dev, KBASE_MSG_PRE_FLAG "extension==%ld not a non-zero power of 2", - small_extension); - return -EINVAL; - } - - if (commit_pages > large_extension) { - dev_warn(dev, KBASE_MSG_PRE_FLAG "commit_pages==%ld exceeds extension==%ld", - (unsigned long)commit_pages, (unsigned long)large_extension); - return -EINVAL; - } -#undef KBASE_MSG_PRE_FLAG - } -#else CSTD_UNUSED(commit_pages); -#endif /* !MALI_USE_CSF */ if ((flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE) && (va_pages > (BASE_MEM_PFN_MASK_4GB + 1))) { dev_warn( @@ -2343,9 +2259,7 @@ KBASE_EXPORT_TEST_API(kbase_gpu_vm_lock); void kbase_gpu_vm_lock_with_pmode_sync(struct kbase_context *kctx) { -#if MALI_USE_CSF down_read(&kctx->kbdev->csf.mmu_sync_sem); -#endif kbase_gpu_vm_lock(kctx); } @@ -2359,9 +2273,7 @@ KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock); void kbase_gpu_vm_unlock_with_pmode_sync(struct kbase_context *kctx) { kbase_gpu_vm_unlock(kctx); -#if MALI_USE_CSF up_read(&kctx->kbdev->csf.mmu_sync_sem); -#endif } #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -2524,17 +2436,11 @@ static int kbase_jit_debugfs_used_get(struct kbase_jit_debugfs_data *data) struct kbase_context *kctx = data->kctx; struct kbase_va_region *reg; -#if !MALI_USE_CSF - mutex_lock(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ mutex_lock(&kctx->jit_evict_lock); list_for_each_entry(reg, &kctx->jit_active_head, jit_node) { data->active_value += reg->used_pages; } mutex_unlock(&kctx->jit_evict_lock); -#if !MALI_USE_CSF - mutex_unlock(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ return 0; } @@ -2550,9 +2456,6 @@ static int kbase_jit_debugfs_trim_get(struct kbase_jit_debugfs_data *data) struct kbase_context *kctx = data->kctx; struct kbase_va_region *reg; -#if !MALI_USE_CSF - mutex_lock(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ kbase_gpu_vm_lock(kctx); mutex_lock(&kctx->jit_evict_lock); list_for_each_entry(reg, &kctx->jit_active_head, jit_node) { @@ -2570,9 +2473,6 @@ static int kbase_jit_debugfs_trim_get(struct kbase_jit_debugfs_data *data) } mutex_unlock(&kctx->jit_evict_lock); kbase_gpu_vm_unlock(kctx); -#if !MALI_USE_CSF - mutex_unlock(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ return 0; } @@ -2677,14 +2577,9 @@ int kbase_jit_init(struct kbase_context *kctx) INIT_LIST_HEAD(&kctx->jit_destroy_head); INIT_WORK(&kctx->jit_work, kbase_jit_destroy_worker); -#if MALI_USE_CSF mutex_init(&kctx->csf.kcpu_queues.jit_lock); INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_cmds_head); INIT_LIST_HEAD(&kctx->csf.kcpu_queues.jit_blocked_queues); -#else /* !MALI_USE_CSF */ - INIT_LIST_HEAD(&kctx->jctx.jit_atoms_head); - INIT_LIST_HEAD(&kctx->jctx.jit_pending_alloc); -#endif /* MALI_USE_CSF */ mutex_unlock(&kctx->jit_evict_lock); return 0; @@ -2702,16 +2597,6 @@ static bool meet_size_and_tiler_align_top_requirements(const struct kbase_va_reg if (walker->nr_pages != info->va_pages) meet_reqs = false; -#if !MALI_USE_CSF - if (meet_reqs && (info->flags & BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP)) { - size_t align = info->extension; - size_t align_mask = align - 1; - - if ((walker->start_pfn + info->commit_pages) & align_mask) - meet_reqs = false; - } -#endif /* !MALI_USE_CSF */ - return meet_reqs; } @@ -2729,9 +2614,6 @@ static int kbase_mem_jit_trim_pages_from_region(struct kbase_context *kctx, size_t to_free = 0u; size_t max_allowed_pages = old_pages; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kctx->reg_lock); /* Is this a JIT allocation that has been reported on? */ @@ -2846,9 +2728,6 @@ static size_t kbase_mem_jit_trim_pages(struct kbase_context *kctx, size_t pages_ struct kbase_va_region *reg, *tmp; size_t total_freed = 0; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kctx->reg_lock); lockdep_assert_held(&kctx->jit_evict_lock); @@ -3048,9 +2927,6 @@ void kbase_jit_trim_necessary_pages(struct kbase_context *kctx, size_t needed_pa size_t jit_backing = 0; size_t pages_to_trim = 0; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kctx->reg_lock); lockdep_assert_held(&kctx->jit_evict_lock); @@ -3096,11 +2972,7 @@ void kbase_jit_trim_necessary_pages(struct kbase_context *kctx, size_t needed_pa static bool jit_allow_allocate(struct kbase_context *kctx, const struct base_jit_alloc_info *info, bool ignore_pressure_limit) { -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#else /* MALI_USE_CSF */ lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); -#endif /* !MALI_USE_CSF */ #if MALI_JIT_PRESSURE_LIMIT_BASE if (!ignore_pressure_limit && @@ -3187,11 +3059,7 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, */ const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_SYNC; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#else /* MALI_USE_CSF */ lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); -#endif /* !MALI_USE_CSF */ if (!jit_allow_allocate(kctx, info, ignore_pressure_limit)) return NULL; @@ -3330,11 +3198,6 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx, BASEP_MEM_ACTIVE_JIT_ALLOC; u64 gpu_addr; -#if !MALI_USE_CSF - if (info->flags & BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP) - flags |= BASE_MEM_TILER_ALIGN_TOP; -#endif /* !MALI_USE_CSF */ - flags |= kbase_mem_group_id_set(kctx->jit_group_id); #if MALI_JIT_PRESSURE_LIMIT_BASE if (!ignore_pressure_limit) { @@ -3431,11 +3294,7 @@ void kbase_jit_free(struct kbase_context *kctx, struct kbase_va_region *reg) { u64 old_pages; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#else /* MALI_USE_CSF */ lockdep_assert_held(&kctx->csf.kcpu_queues.jit_lock); -#endif /* !MALI_USE_CSF */ /* JIT id not immediately available here, so use 0u */ trace_mali_jit_free(reg, 0u); @@ -3669,10 +3528,6 @@ void kbase_jit_report_update_pressure(struct kbase_context *kctx, struct kbase_v { u64 diff; -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ - trace_mali_jit_report_pressure( reg, new_used_pages, kctx->jit_current_phys_pressure + new_used_pages - reg->used_pages, flags); @@ -4533,9 +4388,6 @@ void kbase_user_buf_from_dma_mapped_to_pinned(struct kbase_context *kctx, dev_dbg(kctx->kbdev->dev, "%s %pK in kctx %pK\n", __func__, (void *)reg, (void *)kctx); if (WARN_ON(reg->gpu_alloc->imported.user_buf.state != KBASE_USER_BUF_STATE_DMA_MAPPED)) return; -#if !MALI_USE_CSF - kbase_mem_shrink_cpu_mapping(kctx, reg, 0, reg->gpu_alloc->nents); -#endif kbase_user_buf_dma_unmap_pages(kctx, reg); reg->gpu_alloc->imported.user_buf.state = KBASE_USER_BUF_STATE_PINNED; diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem.h b/drivers/gpu/arm/valhall/mali_kbase_mem.h index 455c3efc3bd2..3a92ce9ec8b6 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem.h +++ b/drivers/gpu/arm/valhall/mali_kbase_mem.h @@ -174,7 +174,6 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int /* Normal memory, inner non-cacheable, outer non-cacheable (ARMv8 mode only) */ #define KBASE_MEMATTR_INDEX_NON_CACHEABLE 5 -#if MALI_USE_CSF /* Set to shared memory, that is inner cacheable on ACE and inner or outer * shared, otherwise inner non-cacheable. * Outer cacheable if inner or outer shared, otherwise outer non-cacheable. @@ -187,14 +186,12 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int /* Normal memory, shared between MCU and Host */ #define KBASE_MEMATTR_INDEX_SHARED 6 -#endif #define KBASE_REG_PROTECTED (1ul << 19) /* Imported buffer is padded? */ #define KBASE_REG_IMPORT_PAD (1ul << 21) -#if MALI_USE_CSF /* CSF event memory */ #define KBASE_REG_CSF_EVENT (1ul << 22) /* Bit 23 is reserved. @@ -202,17 +199,6 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int * Do not remove, use the next unreserved bit for new flags */ #define KBASE_REG_RESERVED_BIT_23 (1ul << 23) -#else -/* Bit 22 is reserved. - * - * Do not remove, use the next unreserved bit for new flags - */ -#define KBASE_REG_RESERVED_BIT_22 (1ul << 22) -/* The top of the initial commit is aligned to extension pages. - * Extent must be a power of 2 - */ -#define KBASE_REG_TILER_ALIGN_TOP (1ul << 23) -#endif /* MALI_USE_CSF */ /* Bit 24 is currently unused and is available for use for a new flag */ @@ -241,15 +227,11 @@ static inline void kbase_process_page_usage_inc(struct kbase_context *kctx, int */ #define KBASE_REG_HEAP_INFO_IS_SIZE (1ul << 27) -#if MALI_USE_CSF /* This flag only applies to allocations in the EXEC_FIXED_VA and FIXED_VA * memory zones, and it determines whether they were created with a fixed * GPU VA address requested by the user. */ #define KBASE_REG_FIXED_ADDRESS (1ul << 29) -#else -#define KBASE_REG_RESERVED_BIT_29 (1ul << 29) -#endif /* * A CPU mapping */ @@ -975,11 +957,25 @@ static inline int kbase_reg_prepare_native(struct kbase_va_region *reg, struct k */ #define KBASE_MEM_POOL_MAX_SIZE_KBDEV (SZ_64M >> PAGE_SHIFT) +/* + * Max size for kbdev pgd memory pool (in pages) + */ +#define BASE_PGD_MEM_POOL_MAX_SIZE_KBDEV (SZ_2M >> PAGE_SHIFT) + +/* + * Max size for kbdev fw memory pool (in pages) + */ +#define KBASE_FW_MEM_POOL_MAX_SIZE_KBDEV ((4 * SZ_2M) >> PAGE_SHIFT) /* * Max size for kctx memory pool (in pages) */ #define KBASE_MEM_POOL_MAX_SIZE_KCTX (SZ_64M >> PAGE_SHIFT) +/* + * Max size of kctx pgd memory pool (in pages) + */ +#define KBASE_PGD_MM_POOLMAX_SIZE_KCTX (SZ_2M >> PAGE_SHIFT) + /* * The order required for a 2MB page allocation (2^order * PAGE_SIZE = 2MB) */ @@ -1022,13 +1018,12 @@ kbase_mem_pool_config_get_max_size(const struct kbase_mem_pool_config *const con /** * kbase_mem_pool_init - Create a memory pool for a kbase device * @pool: Memory pool to initialize - * @config: Initial configuration for the memory pool + * @max_size: Maximum size for the memory pool * @order: Page order for physical page size (order=0 => small page, order != 0 => 2MB) * @group_id: A memory group ID to be passed to a platform-specific * memory group manager, if present. * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). * @kbdev: Kbase device where memory is used - * @next_pool: Pointer to the next pool or NULL. * * Allocations from @pool are in whole pages. Each @pool has a free list where * pages can be quickly allocated from. The free list is initially empty and @@ -1046,9 +1041,26 @@ kbase_mem_pool_config_get_max_size(const struct kbase_mem_pool_config *const con * * Return: 0 on success, negative -errno on error */ -int kbase_mem_pool_init(struct kbase_mem_pool *pool, const struct kbase_mem_pool_config *config, - unsigned int order, int group_id, struct kbase_device *kbdev, - struct kbase_mem_pool *next_pool); +int kbase_mem_pool_init(struct kbase_mem_pool *pool, size_t max_size, unsigned int order, + int group_id, struct kbase_device *kbdev); + +/** + * kbase_mem_pool_init_no_reclaim - Create a memory pool for a kbase device, with no reclaim. + * @pool: Memory pool to initialize + * @max_size: Maximum size for the memory pool + * @order: Page order for physical page size (order=0 => small page, order != 0 => 2MB) + * @group_id: A memory group ID to be passed to a platform-specific + * memory group manager, if present. + * Valid range is 0..(MEMORY_GROUP_MANAGER_NR_GROUPS-1). + * @kbdev: Kbase device where memory is used + * + * Identical to kbase_mem_pool_init, except the pool does not support reclaiming of pages. + * For that reason it also omits support of the next_pool feature. + * + * Return: 0 on success, negative -errno on error + */ +int kbase_mem_pool_init_no_reclaim(struct kbase_mem_pool *pool, size_t max_size, unsigned int order, + int group_id, struct kbase_device *kbdev); /** * kbase_mem_pool_term - Destroy a memory pool @@ -2000,9 +2012,6 @@ void kbase_jit_trim_necessary_pages(struct kbase_context *kctx, size_t needed_pa static inline void kbase_jit_request_phys_increase_locked(struct kbase_context *kctx, size_t needed_pages) { -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kctx->reg_lock); lockdep_assert_held(&kctx->jit_evict_lock); @@ -2038,9 +2047,6 @@ static inline void kbase_jit_request_phys_increase_locked(struct kbase_context * */ static inline void kbase_jit_request_phys_increase(struct kbase_context *kctx, size_t needed_pages) { -#if !MALI_USE_CSF - lockdep_assert_held(&kctx->jctx.lock); -#endif /* !MALI_USE_CSF */ lockdep_assert_held(&kctx->reg_lock); mutex_lock(&kctx->jit_evict_lock); @@ -2395,7 +2401,6 @@ static inline void kbase_mem_pool_unlock(struct kbase_mem_pool *pool) */ void kbase_mem_evictable_mark_reclaim(struct kbase_mem_phy_alloc *alloc); -#if MALI_USE_CSF /** * kbase_link_event_mem_page - Add the new event memory region to the per * context list of event pages. @@ -2451,7 +2456,6 @@ int kbase_mcu_shared_interface_region_tracker_init(struct kbase_device *kbdev); * @kbdev: Pointer to the kbase device */ void kbase_mcu_shared_interface_region_tracker_term(struct kbase_device *kbdev); -#endif /** * kbase_mem_umm_map - Map dma-buf diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_flags.h b/drivers/gpu/arm/valhall/mali_kbase_mem_flags.h index 84948f9fa445..3ffd7701bd0b 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_flags.h +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_flags.h @@ -22,11 +22,7 @@ #ifndef _KBASE_MEM_FLAGS_H_ #define _KBASE_MEM_FLAGS_H_ -#if MALI_USE_CSF #include -#else -#include -#endif /* Will be permanently mapped in kernel space. * Flag is only allowed on allocations originating from kbase. diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c b/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c index 321df3afd279..c8e36707aae9 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -97,10 +97,8 @@ MODULE_PARM_DESC( "Note that this should only be enabled for testing worst case memory usage " "and should not be enabled in production"); -#if MALI_USE_CSF static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, struct vm_area_struct *vma); static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx, struct vm_area_struct *vma); -#endif static int kbase_vmap_phy_pages(struct kbase_context *kctx, struct kbase_va_region *reg, u64 offset_bytes, size_t size, struct kbase_vmap_struct *map, @@ -132,7 +130,6 @@ static bool is_process_exiting(struct vm_area_struct *vma) */ static struct kbase_va_region *kbase_find_event_mem_region(struct kbase_context *kctx, u64 gpu_addr) { -#if MALI_USE_CSF u64 gpu_pfn = gpu_addr >> PAGE_SHIFT; struct kbase_va_region *reg; @@ -149,10 +146,6 @@ static struct kbase_va_region *kbase_find_event_mem_region(struct kbase_context return reg; } } -#else - CSTD_UNUSED(kctx); - CSTD_UNUSED(gpu_addr); -#endif return NULL; } @@ -310,13 +303,8 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages dev_dbg(dev, "Allocating %lld va_pages, %lld commit_pages, %lld extension, 0x%llX flags\n", va_pages, commit_pages, extension, *flags); -#if MALI_USE_CSF if (!(*flags & BASE_MEM_FIXED)) *gpu_va = 0; /* return 0 on failure */ -#else - if (!(*flags & BASEP_MEM_FLAG_MAP_FIXED)) - *gpu_va = 0; /* return 0 on failure */ -#endif else dev_dbg(dev, "Keeping requested GPU VA of 0x%llx\n", (unsigned long long)*gpu_va); @@ -370,7 +358,6 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages /* find out which VA zone to use */ if (*flags & BASE_MEM_SAME_VA) zone = SAME_VA_ZONE; -#if MALI_USE_CSF /* fixed va_zone always exists */ else if (*flags & (BASE_MEM_FIXED | BASE_MEM_FIXABLE)) { if (*flags & BASE_MEM_PROT_GPU_EX) { @@ -378,9 +365,7 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages } else { zone = FIXED_VA_ZONE; } - } -#endif - else if ((*flags & BASE_MEM_PROT_GPU_EX) && kbase_has_exec_va_zone(kctx)) { + } else if ((*flags & BASE_MEM_PROT_GPU_EX) && kbase_has_exec_va_zone(kctx)) { zone = EXEC_VA_ZONE; } else { zone = CUSTOM_VA_ZONE; @@ -415,10 +400,6 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages * reg->extension. */ reg->extension = extension; -#if !MALI_USE_CSF - } else if (*flags & BASE_MEM_TILER_ALIGN_TOP) { - reg->extension = extension; -#endif /* !MALI_USE_CSF */ } else { reg->extension = 0; } @@ -480,10 +461,6 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages } if (*gpu_va) align = 1; -#if !MALI_USE_CSF - if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) - align = 1; -#endif /* !MALI_USE_CSF */ } if (kbase_gpu_mmap(kctx, reg, *gpu_va, va_pages, align, mmu_sync_info) != 0) { dev_warn(dev, "Failed to map memory on GPU"); @@ -507,12 +484,10 @@ struct kbase_va_region *kbase_mem_alloc(struct kbase_context *kctx, u64 va_pages kbase_gpu_vm_unlock_with_pmode_sync(kctx); -#if MALI_USE_CSF if (*flags & BASE_MEM_FIXABLE) atomic64_inc(&kctx->num_fixable_allocs); else if (*flags & BASE_MEM_FIXED) atomic64_inc(&kctx->num_fixed_allocs); -#endif return reg; @@ -617,13 +592,8 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co if (KBASE_REG_PROTECTED & reg->flags) *out |= BASE_MEM_PROTECTED; } -#if !MALI_USE_CSF - if (KBASE_REG_TILER_ALIGN_TOP & reg->flags) - *out |= BASE_MEM_TILER_ALIGN_TOP; -#endif /* !MALI_USE_CSF */ if (!(KBASE_REG_GPU_CACHED & reg->flags)) *out |= BASE_MEM_UNCACHED_GPU; -#if MALI_USE_CSF if (KBASE_REG_CSF_EVENT & reg->flags) *out |= BASE_MEM_CSF_EVENT; if ((kbase_bits_to_zone(reg->flags) == FIXED_VA_ZONE) || @@ -633,7 +603,6 @@ int kbase_mem_query(struct kbase_context *kctx, u64 gpu_addr, u64 query, u64 *co else *out |= BASE_MEM_FIXABLE; } -#endif /* MALI_USE_CSF */ if (KBASE_REG_GPU_VA_SAME_4GB_PAGE & reg->flags) *out |= BASE_MEM_GPU_VA_SAME_4GB_PAGE; if (mali_kbase_supports_query_mem_import_sync_on_map_unmap(kctx->api_version)) { @@ -741,13 +710,11 @@ static unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s kctx = KBASE_GET_KBASE_DATA_FROM_SHRINKER(s, struct kbase_context, reclaim); -#if MALI_USE_CSF if (!down_read_trylock(&kctx->kbdev->csf.mmu_sync_sem)) { dev_warn(kctx->kbdev->dev, "Can't shrink GPU memory when P.Mode entrance is in progress"); return 0; } -#endif mutex_lock(&kctx->jit_evict_lock); list_for_each_entry_safe(alloc, tmp, &kctx->evict_list, evict_node) { @@ -786,9 +753,7 @@ static unsigned long kbase_mem_evictable_reclaim_scan_objects(struct shrinker *s } mutex_unlock(&kctx->jit_evict_lock); -#if MALI_USE_CSF up_read(&kctx->kbdev->csf.mmu_sync_sem); -#endif return freed; } @@ -1494,15 +1459,33 @@ static struct kbase_va_region *kbase_mem_from_umm(struct kbase_context *kctx, in *flags &= ~BASE_MEM_SAME_VA; /* - * Force CPU cached flag. - * - * We can't query the dma-buf exporter to get details about the CPU - * cache attributes of CPU mappings, so we have to assume that the - * buffer may be cached, and call into the exporter for cache - * maintenance, and rely on the exporter to do the right thing when - * handling our calls. + * mgm_get_import_memory_cached_access_permitted() returns true if externally visible + * accesses by the GPU for this dma_buf are allowed to be cached. Set CPU cacheabilty + * flag to match. */ - *flags |= BASE_MEM_CACHED_CPU; + if (kctx->kbdev->mgm_dev->ops.mgm_get_import_memory_cached_access_permitted) { + struct memory_group_manager_import_data mgm_import_data; + + mgm_import_data.type = MEMORY_GROUP_MANAGER_IMPORT_TYPE_DMA_BUF; + mgm_import_data.u.dma_buf = dma_buf; + + if (kctx->kbdev->mgm_dev->ops.mgm_get_import_memory_cached_access_permitted( + kctx->kbdev->mgm_dev, &mgm_import_data)) + *flags |= BASE_MEM_CACHED_CPU; + else + *flags &= ~BASE_MEM_CACHED_CPU; + } else { + /* + * Force CPU cached flag if we do not have the API to query MGM + * + * We can't query the dma-buf exporter to get details about the CPU + * cache attributes of CPU mappings, so we have to assume that the + * buffer may be cached, and call into the exporter for cache + * maintenance, and rely on the exporter to do the right thing when + * handling our calls. + */ + *flags |= BASE_MEM_CACHED_CPU; + } if (*flags & BASE_MEM_IMPORT_SHARED) shared_zone = true; @@ -1825,8 +1808,8 @@ u64 kbase_mem_alias(struct kbase_context *kctx, base_mem_alloc_flags *flags, u64 /* validate and add src handles */ for (i = 0; i < nents; i++) { - if (ai[i].handle.basep.handle < BASE_MEM_FIRST_FREE_ADDRESS) { - if (ai[i].handle.basep.handle != BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE) + if (ai[i].gpu_va < BASE_MEM_FIRST_FREE_ADDRESS) { + if (ai[i].gpu_va != BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE) goto bad_handle; /* unsupported magic handle */ if (!ai[i].length) goto bad_handle; /* must be > 0 */ @@ -1840,7 +1823,7 @@ u64 kbase_mem_alias(struct kbase_context *kctx, base_mem_alloc_flags *flags, u64 struct kbase_mem_phy_alloc *alloc; aliasing_reg = kbase_region_tracker_find_region_base_address( - kctx, (ai[i].handle.basep.handle >> PAGE_SHIFT) << PAGE_SHIFT); + kctx, (ai[i].gpu_va >> PAGE_SHIFT) << PAGE_SHIFT); /* validate found region */ if (kbase_is_region_invalid_or_free(aliasing_reg)) @@ -2734,10 +2717,8 @@ static int kbasep_reg_mmap(struct kbase_context *kctx, struct vm_area_struct *vm kctx->pending_regions[cookie] = NULL; bitmap_set(kctx->cookies, cookie, 1); -#if MALI_USE_CSF if (reg->flags & KBASE_REG_CSF_EVENT) kbase_link_event_mem_page(kctx, reg); -#endif /* * Overwrite the offset with the region start_pfn, so we effectively @@ -2813,7 +2794,6 @@ int kbase_context_mmap(struct kbase_context *const kctx, struct vm_area_struct * err = -EINVAL; goto out_unlock; #endif /* defined(CONFIG_MALI_VECTOR_DUMP) */ -#if MALI_USE_CSF case PFN_DOWN(BASEP_MEM_CSF_USER_REG_PAGE_HANDLE): kbase_gpu_vm_unlock_with_pmode_sync(kctx); err = kbase_csf_cpu_mmap_user_reg_page(kctx, vma); @@ -2825,7 +2805,6 @@ int kbase_context_mmap(struct kbase_context *const kctx, struct vm_area_struct * mutex_unlock(&kctx->csf.lock); goto out; } -#endif case PFN_DOWN(BASE_MEM_COOKIE_BASE)... PFN_DOWN(BASE_MEM_FIRST_FREE_ADDRESS) - 1: { err = kbasep_reg_mmap(kctx, vma, ®, &nr_pages, &aligned_offset); if (err != 0) @@ -3319,7 +3298,6 @@ static int kbase_tracking_page_setup(struct kbase_context *kctx, struct vm_area_ return 0; } -#if MALI_USE_CSF static unsigned long get_queue_doorbell_pfn(struct kbase_device *kbdev, struct kbase_queue *queue) { lockdep_assert_held(&kbdev->csf.reg_lock); @@ -3462,13 +3440,19 @@ static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf) output_cpu_addr = input_cpu_addr + PAGE_SIZE; if (mali_kbase_supports_csg_cs_user_page_allocation(queue->kctx->api_version)) { - if (!queue->group) { - ret = VM_FAULT_SIGBUS; - goto exit; + if (likely(queue->group)) { + input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[0])); + output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[1])); + } else { + /* This could happen if userspace tries to access this memory + * after the group has already been terminated due to a fault. + * Re-map to the dummy page to render the access harmless. + */ + input_page_pfn = + PFN_DOWN(as_phys_addr_t(kbdev->csf.user_reg.dummy_page)); + output_page_pfn = + PFN_DOWN(as_phys_addr_t(kbdev->csf.user_reg.dummy_page)); } - - input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[0])); - output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[1])); } else { input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[0])); output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[1])); @@ -3757,5 +3741,3 @@ static int kbase_csf_cpu_mmap_user_reg_page(struct kbase_context *kctx, struct v return 0; } - -#endif /* MALI_USE_CSF */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_pool.c b/drivers/gpu/arm/valhall/mali_kbase_mem_pool.c index 150236e05e37..3ebbe32ae74c 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_pool.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_pool.c @@ -34,9 +34,8 @@ #include #endif -#define pool_dbg(pool, format, ...) \ - dev_dbg(pool->kbdev->dev, "%s-pool [%zu/%zu]: " format, \ - (pool->next_pool) ? "kctx" : "kbdev", kbase_mem_pool_size(pool), \ +#define pool_dbg(pool, format, ...) \ + dev_dbg(pool->kbdev->dev, "%s-pool [%zu/%zu]: " format, "kctx", kbase_mem_pool_size(pool), \ kbase_mem_pool_max_size(pool), ##__VA_ARGS__) #define NOT_DIRTY false @@ -257,14 +256,6 @@ static void kbase_mem_pool_zero_page(struct kbase_mem_pool *pool, struct page *p kbase_mem_pool_sync_page(pool, p); } -static void kbase_mem_pool_spill(struct kbase_mem_pool *next_pool, struct page *p) -{ - /* Zero page before spilling */ - kbase_mem_pool_zero_page(next_pool, p); - - kbase_mem_pool_add(next_pool, p); -} - struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) { struct page *p; @@ -308,13 +299,15 @@ struct page *kbase_mem_alloc_page(struct kbase_mem_pool *pool) return p; } +KBASE_EXPORT_TEST_API(kbase_mem_alloc_page); static void enqueue_free_pool_pages_work(struct kbase_mem_pool *pool) { - struct kbase_mem_migrate *mem_migrate = &pool->kbdev->mem_migrate; + if (!pool->order && kbase_is_page_migration_enabled()) { + struct kbase_mem_migrate *mem_migrate = &pool->kbdev->mem_migrate; - if (!pool->order && kbase_is_page_migration_enabled()) queue_work(mem_migrate->free_pages_workq, &mem_migrate->free_pages_work); + } } void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, struct page *p) @@ -345,6 +338,7 @@ void kbase_mem_pool_free_page(struct kbase_mem_pool *pool, struct page *p) pool_dbg(pool, "freed page to kernel\n"); } } +KBASE_EXPORT_TEST_API(kbase_mem_pool_free_page); static size_t kbase_mem_pool_shrink_locked(struct kbase_mem_pool *pool, size_t nr_to_shrink) { @@ -383,10 +377,13 @@ int kbase_mem_pool_grow(struct kbase_mem_pool *pool, size_t nr_to_grow, kbase_mem_pool_lock(pool); - pool->dont_reclaim = true; + pool->reclaim_allowed = false; + for (i = 0; i < nr_to_grow; i++) { if (pool->dying) { - pool->dont_reclaim = false; + if (pool->pool_supports_reclaim) + pool->reclaim_allowed = true; + kbase_mem_pool_shrink_locked(pool, nr_to_grow); kbase_mem_pool_unlock(pool); if (page_owner) @@ -402,9 +399,11 @@ int kbase_mem_pool_grow(struct kbase_mem_pool *pool, size_t nr_to_grow, p = kbase_mem_alloc_page(pool); if (!p) { - kbase_mem_pool_lock(pool); - pool->dont_reclaim = false; - kbase_mem_pool_unlock(pool); + if (pool->pool_supports_reclaim) { + kbase_mem_pool_lock(pool); + pool->reclaim_allowed = true; + kbase_mem_pool_unlock(pool); + } return -ENOMEM; } @@ -412,7 +411,10 @@ int kbase_mem_pool_grow(struct kbase_mem_pool *pool, size_t nr_to_grow, kbase_mem_pool_lock(pool); kbase_mem_pool_add_locked(pool, p); } - pool->dont_reclaim = false; + + if (pool->pool_supports_reclaim) + pool->reclaim_allowed = true; + kbase_mem_pool_unlock(pool); return 0; @@ -443,6 +445,7 @@ void kbase_mem_pool_trim(struct kbase_mem_pool *pool, size_t new_size) (new_size - cur_size), (grown_size - cur_size)); } } +KBASE_EXPORT_TEST_API(kbase_mem_pool_trim); void kbase_mem_pool_set_max_size(struct kbase_mem_pool *pool, size_t max_size) { @@ -473,8 +476,12 @@ static unsigned long kbase_mem_pool_reclaim_count_objects(struct shrinker *s, pool = KBASE_GET_KBASE_DATA_FROM_SHRINKER(s, struct kbase_mem_pool, reclaim); + /* Pools not supporting reclaims are not assumed to register reclaim callbacks */ + if (WARN_ON(!pool->pool_supports_reclaim)) + return 0; + kbase_mem_pool_lock(pool); - if (pool->dont_reclaim && !pool->dying) { + if (!pool->reclaim_allowed && !pool->dying) { kbase_mem_pool_unlock(pool); /* Tell shrinker to skip reclaim * even though freeable pages are available @@ -495,10 +502,13 @@ static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s, pool = KBASE_GET_KBASE_DATA_FROM_SHRINKER(s, struct kbase_mem_pool, reclaim); + if (WARN_ON(!pool->pool_supports_reclaim)) + return SHRINK_STOP; + kbase_mem_pool_lock(pool); - if (pool->dont_reclaim && !pool->dying) { + if (!pool->reclaim_allowed && !pool->dying) { kbase_mem_pool_unlock(pool); - /* Tell shrinker that reclaim can't be made and + /* Tell shrinker that reclaim can't be done, and * do not attempt again for this reclaim context. */ return SHRINK_STOP; @@ -515,9 +525,8 @@ static unsigned long kbase_mem_pool_reclaim_scan_objects(struct shrinker *s, return freed; } -int kbase_mem_pool_init(struct kbase_mem_pool *pool, const struct kbase_mem_pool_config *config, - unsigned int order, int group_id, struct kbase_device *kbdev, - struct kbase_mem_pool *next_pool) +static int kbasep_mem_pool_init(struct kbase_mem_pool *pool, size_t max_size, unsigned int order, + int group_id, struct kbase_device *kbdev, bool support_reclaim) { struct shrinker *reclaim; @@ -526,71 +535,73 @@ int kbase_mem_pool_init(struct kbase_mem_pool *pool, const struct kbase_mem_pool } pool->cur_size = 0; - pool->max_size = kbase_mem_pool_config_get_max_size(config); + pool->max_size = max_size; pool->order = order; pool->group_id = group_id; pool->kbdev = kbdev; - pool->next_pool = next_pool; pool->dying = false; + pool->pool_supports_reclaim = support_reclaim; + pool->reclaim_allowed = false; atomic_set(&pool->isolation_in_progress_cnt, 0); spin_lock_init(&pool->pool_lock); INIT_LIST_HEAD(&pool->page_list); - reclaim = KBASE_INIT_RECLAIM(pool, reclaim, "mali-mem-pool"); - if (!reclaim) - return -ENOMEM; - KBASE_SET_RECLAIM(pool, reclaim, reclaim); + if (support_reclaim) { + reclaim = KBASE_INIT_RECLAIM(pool, reclaim, "mali-mem-pool"); + if (!reclaim) + return -ENOMEM; + KBASE_SET_RECLAIM(pool, reclaim, reclaim); - reclaim->count_objects = kbase_mem_pool_reclaim_count_objects; - reclaim->scan_objects = kbase_mem_pool_reclaim_scan_objects; - reclaim->seeks = DEFAULT_SEEKS; - reclaim->batch = 0; + reclaim->count_objects = kbase_mem_pool_reclaim_count_objects; + reclaim->scan_objects = kbase_mem_pool_reclaim_scan_objects; + reclaim->seeks = DEFAULT_SEEKS; + reclaim->batch = 0; - KBASE_REGISTER_SHRINKER(reclaim, "mali-mem-pool", pool); + KBASE_REGISTER_SHRINKER(reclaim, "mali-mem-pool", pool); + } pool_dbg(pool, "initialized\n"); return 0; } + +int kbase_mem_pool_init(struct kbase_mem_pool *pool, size_t max_size, unsigned int order, + int group_id, struct kbase_device *kbdev) +{ + return kbasep_mem_pool_init(pool, max_size, order, group_id, kbdev, true); +} KBASE_EXPORT_TEST_API(kbase_mem_pool_init); +int kbase_mem_pool_init_no_reclaim(struct kbase_mem_pool *pool, size_t max_size, unsigned int order, + int group_id, struct kbase_device *kbdev) +{ + return kbasep_mem_pool_init(pool, max_size, order, group_id, kbdev, false); +} +KBASE_EXPORT_TEST_API(kbase_mem_pool_init_no_reclaim); + void kbase_mem_pool_mark_dying(struct kbase_mem_pool *pool) { kbase_mem_pool_lock(pool); pool->dying = true; kbase_mem_pool_unlock(pool); } +KBASE_EXPORT_TEST_API(kbase_mem_pool_mark_dying); void kbase_mem_pool_term(struct kbase_mem_pool *pool) { - struct kbase_mem_pool *next_pool = pool->next_pool; struct page *p, *tmp; - size_t nr_to_spill = 0; LIST_HEAD(spill_list); LIST_HEAD(free_list); - size_t i; pool_dbg(pool, "terminate()\n"); - KBASE_UNREGISTER_SHRINKER(pool->reclaim); + if (pool->pool_supports_reclaim) + KBASE_UNREGISTER_SHRINKER(pool->reclaim); kbase_mem_pool_lock(pool); pool->max_size = 0; - if (next_pool && !kbase_mem_pool_is_full(next_pool)) { - /* Spill to next pool (may overspill) */ - nr_to_spill = kbase_mem_pool_capacity(next_pool); - nr_to_spill = min(kbase_mem_pool_size(pool), nr_to_spill); - - /* Zero pages first without holding the next_pool lock */ - for (i = 0; i < nr_to_spill; i++) { - p = kbase_mem_pool_remove_locked(pool, SPILL_IN_PROGRESS); - if (p) - list_add(&p->lru, &spill_list); - } - } - while (!kbase_mem_pool_is_empty(pool)) { /* Free remaining pages to kernel */ p = kbase_mem_pool_remove_locked(pool, FREE_IN_PROGRESS); @@ -600,16 +611,6 @@ void kbase_mem_pool_term(struct kbase_mem_pool *pool) kbase_mem_pool_unlock(pool); - if (next_pool && nr_to_spill) { - list_for_each_entry(p, &spill_list, lru) - kbase_mem_pool_zero_page(pool, p); - - /* Add new page list to next_pool */ - kbase_mem_pool_add_list(next_pool, &spill_list, nr_to_spill); - - pool_dbg(pool, "terminate() spilled %zu pages\n", nr_to_spill); - } - list_for_each_entry_safe(p, tmp, &free_list, lru) { list_del_init(&p->lru); kbase_mem_pool_free_page(pool, p); @@ -633,18 +634,12 @@ struct page *kbase_mem_pool_alloc(struct kbase_mem_pool *pool) { struct page *p; - do { - pool_dbg(pool, "alloc()\n"); - p = kbase_mem_pool_remove(pool, ALLOCATE_IN_PROGRESS); + pool_dbg(pool, "alloc()\n"); + p = kbase_mem_pool_remove(pool, ALLOCATE_IN_PROGRESS); - if (p) - return p; - - pool = pool->next_pool; - } while (pool); - - return NULL; + return p; } +KBASE_EXPORT_TEST_API(kbase_mem_pool_alloc); struct page *kbase_mem_pool_alloc_locked(struct kbase_mem_pool *pool) { @@ -656,8 +651,6 @@ struct page *kbase_mem_pool_alloc_locked(struct kbase_mem_pool *pool) void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *p, bool dirty) { - struct kbase_mem_pool *next_pool = pool->next_pool; - pool_dbg(pool, "free()\n"); if (!kbase_mem_pool_is_full(pool)) { @@ -666,9 +659,6 @@ void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *p, bool dirty kbase_mem_pool_sync_page(pool, p); kbase_mem_pool_add(pool, p); - } else if (next_pool && !kbase_mem_pool_is_full(next_pool)) { - /* Spill to next pool */ - kbase_mem_pool_spill(next_pool, p); } else { /* Free page */ kbase_mem_pool_free_page(pool, p); @@ -676,6 +666,7 @@ void kbase_mem_pool_free(struct kbase_mem_pool *pool, struct page *p, bool dirty enqueue_free_pool_pages_work(pool); } } +KBASE_EXPORT_TEST_API(kbase_mem_pool_free); void kbase_mem_pool_free_locked(struct kbase_mem_pool *pool, struct page *p, bool dirty) { @@ -696,6 +687,7 @@ void kbase_mem_pool_free_locked(struct kbase_mem_pool *pool, struct page *p, boo enqueue_free_pool_pages_work(pool); } } +KBASE_EXPORT_TEST_API(kbase_mem_pool_free_locked); int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_small_pages, struct tagged_addr *pages, bool partial_allowed, @@ -735,42 +727,31 @@ int kbase_mem_pool_alloc_pages(struct kbase_mem_pool *pool, size_t nr_small_page } kbase_mem_pool_unlock(pool); - if (i != nr_small_pages && pool->next_pool) { - /* Allocate via next pool */ - err = kbase_mem_pool_alloc_pages(pool->next_pool, nr_small_pages - i, pages + i, - partial_allowed, page_owner); - - if (err < 0) + /* Get any remaining pages from kernel */ + while (i != nr_small_pages) { + if (unlikely(!can_alloc_page(pool, page_owner))) goto err_rollback; - i += (size_t)err; - } else { - /* Get any remaining pages from kernel */ - while (i != nr_small_pages) { - if (unlikely(!can_alloc_page(pool, page_owner))) + p = kbase_mem_alloc_page(pool); + if (!p) { + if (partial_allowed) + goto done; + else goto err_rollback; + } - p = kbase_mem_alloc_page(pool); - if (!p) { - if (partial_allowed) - goto done; - else - goto err_rollback; - } - - if (pool->order) { - uint j; - - pages[i++] = as_tagged_tag(page_to_phys(p), HUGE_PAGE | HUGE_HEAD); - for (j = 1; j < (1u << pool->order); j++) { - phys_addr_t phys; - - phys = page_to_phys(p) + PAGE_SIZE * j; - pages[i++] = as_tagged_tag(phys, HUGE_PAGE); - } - } else { - pages[i++] = as_tagged(page_to_phys(p)); + if (pool->order) { + uint j; + + pages[i++] = as_tagged_tag(page_to_phys(p), HUGE_PAGE | HUGE_HEAD); + for (j = 1; j < (1u << pool->order); j++) { + phys_addr_t phys; + + phys = page_to_phys(p) + PAGE_SIZE * j; + pages[i++] = as_tagged_tag(phys, HUGE_PAGE); } + } else { + pages[i++] = as_tagged(page_to_phys(p)); } } @@ -782,6 +763,7 @@ err_rollback: kbase_mem_pool_free_pages(pool, i, pages, NOT_DIRTY, NOT_RECLAIMED); return err; } +KBASE_EXPORT_TEST_API(kbase_mem_pool_alloc_pages); int kbase_mem_pool_alloc_pages_locked(struct kbase_mem_pool *pool, size_t nr_small_pages, struct tagged_addr *pages) @@ -822,6 +804,7 @@ int kbase_mem_pool_alloc_pages_locked(struct kbase_mem_pool *pool, size_t nr_sma return nr_small_pages; } +KBASE_EXPORT_TEST_API(kbase_mem_pool_alloc_pages_locked); static void kbase_mem_pool_add_array(struct kbase_mem_pool *pool, size_t nr_pages, struct tagged_addr *pages, bool zero, bool sync) @@ -902,7 +885,6 @@ static void kbase_mem_pool_add_array_locked(struct kbase_mem_pool *pool, size_t void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, struct tagged_addr *pages, bool dirty, bool reclaimed) { - struct kbase_mem_pool *next_pool = pool->next_pool; struct page *p; size_t nr_to_pool; LIST_HEAD(to_pool_list); @@ -919,15 +901,6 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, kbase_mem_pool_add_array(pool, nr_to_pool, pages, false, dirty); i += nr_to_pool; - - if (i != nr_pages && next_pool) { - /* Spill to next pool (may overspill) */ - nr_to_pool = kbase_mem_pool_capacity(next_pool); - nr_to_pool = min(nr_pages - i, nr_to_pool); - - kbase_mem_pool_add_array(next_pool, nr_to_pool, pages + i, true, dirty); - i += nr_to_pool; - } } /* Free any remaining pages to kernel */ @@ -952,6 +925,7 @@ void kbase_mem_pool_free_pages(struct kbase_mem_pool *pool, size_t nr_pages, pool_dbg(pool, "free_pages(%zu) done\n", nr_pages); } +KBASE_EXPORT_TEST_API(kbase_mem_pool_free_pages); void kbase_mem_pool_free_pages_locked(struct kbase_mem_pool *pool, size_t nr_pages, struct tagged_addr *pages, bool dirty, bool reclaimed) @@ -999,3 +973,4 @@ void kbase_mem_pool_free_pages_locked(struct kbase_mem_pool *pool, size_t nr_pag pool_dbg(pool, "free_pages_locked(%zu) done\n", nr_pages); } +KBASE_EXPORT_TEST_API(kbase_mem_pool_free_pages_locked); diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_debugfs.c b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_debugfs.c index b757a1941124..3b89574790ba 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_debugfs.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2014-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2014-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -165,4 +165,10 @@ void kbase_mem_pool_debugfs_init(struct dentry *parent, struct kbase_context *kc debugfs_create_file("lp_mem_pool_max_size", mode, parent, &kctx->mem_pools.large, &kbase_mem_pool_debugfs_max_size_fops); + + debugfs_create_file("pdg_pool_size", mode, parent, &kctx->pgd_mem_pool, + &kbase_mem_pool_debugfs_fops); + + debugfs_create_file("pgd_mem_pool_max_size", mode, parent, &kctx->pgd_mem_pool, + &kbase_mem_pool_debugfs_max_size_fops); } diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.c b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.c index 1b224f7d0cc0..0c3c90d62995 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -25,36 +25,19 @@ #include -void kbase_mem_pool_group_config_set_max_size(struct kbase_mem_pool_group_config *const configs, - size_t const max_size) -{ - size_t const large_max_size = max_size >> (KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER - - KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER); - int gid; - - for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid) { - kbase_mem_pool_config_set_max_size(&configs->small[gid], max_size); - - kbase_mem_pool_config_set_max_size(&configs->large[gid], large_max_size); - } -} - int kbase_mem_pool_group_init(struct kbase_mem_pool_group *const mem_pools, - struct kbase_device *const kbdev, - const struct kbase_mem_pool_group_config *const configs, - struct kbase_mem_pool_group *next_pools) + struct kbase_device *const kbdev, size_t small_max_size, + size_t large_max_size, struct kbase_mem_pool_group *next_pools) { int gid, err = 0; for (gid = 0; gid < MEMORY_GROUP_MANAGER_NR_GROUPS; ++gid) { - err = kbase_mem_pool_init(&mem_pools->small[gid], &configs->small[gid], - KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER, gid, kbdev, - next_pools ? &next_pools->small[gid] : NULL); + err = kbase_mem_pool_init(&mem_pools->small[gid], small_max_size, + KBASE_MEM_POOL_SMALL_PAGE_TABLE_ORDER, gid, kbdev); if (!err) { - err = kbase_mem_pool_init(&mem_pools->large[gid], &configs->large[gid], - KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, gid, kbdev, - next_pools ? &next_pools->large[gid] : NULL); + err = kbase_mem_pool_init(&mem_pools->large[gid], large_max_size, + KBASE_MEM_POOL_2MB_PAGE_TABLE_ORDER, gid, kbdev); if (err) kbase_mem_pool_term(&mem_pools->small[gid]); } diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.h b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.h index cb69eab061ac..b32c71e3db4a 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.h +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_pool_group.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -24,53 +24,15 @@ #include -/** - * kbase_mem_pool_group_select() - Select the memory pool to use. - * - * @kbdev: Device pointer. - * @mem_group_id: Physical memory group ID to use. - * @is_small_page: Flag used to select between the small and - * large memory pool. - * - * Return: A pointer to the selected memory pool. - */ -static inline struct kbase_mem_pool * -kbase_mem_pool_group_select(struct kbase_device *kbdev, u32 mem_group_id, bool is_small_page) -{ - if (WARN_ON(unlikely(kbdev == NULL))) - return NULL; - - WARN_ON(mem_group_id > BASE_MEM_GROUP_COUNT); - - if (is_small_page) - return &kbdev->mem_pools.small[mem_group_id]; - - return &kbdev->mem_pools.large[mem_group_id]; -} - -/** - * kbase_mem_pool_group_config_set_max_size - Set the initial configuration for - * a set of memory pools - * - * @configs: Initial configuration for the set of memory pools - * @max_size: Maximum number of free small pages each pool can hold - * - * This function sets the initial configuration for every memory pool so that - * the maximum amount of free memory that each pool can hold is identical. - * The equivalent number of 2 MiB pages is calculated automatically for the - * purpose of configuring the large page pools. - */ -void kbase_mem_pool_group_config_set_max_size(struct kbase_mem_pool_group_config *configs, - size_t max_size); - /** * kbase_mem_pool_group_init - Initialize a set of memory pools * - * @mem_pools: Set of memory pools to initialize - * @kbdev: Kbase device where memory is used - * @configs: Initial configuration for the set of memory pools - * @next_pools: Set of memory pools from which to allocate memory if there - * is no free memory in one of the @mem_pools + * @mem_pools: Set of memory pools to initialize + * @kbdev: Kbase device where memory is used + * @small_max_size: Maximum size for small memory pools + * @large_max_size: Maximum size for large memory pools + * @next_pools: Set of memory pools from which to allocate memory if there + * is no free memory in one of the @mem_pools * * Initializes a complete set of physical memory pools. Memory pools are used to * allow efficient reallocation of previously-freed physical pages. A pair of @@ -87,7 +49,7 @@ void kbase_mem_pool_group_config_set_max_size(struct kbase_mem_pool_group_config * Return: 0 on success, otherwise a negative error code */ int kbase_mem_pool_group_init(struct kbase_mem_pool_group *mem_pools, struct kbase_device *kbdev, - const struct kbase_mem_pool_group_config *configs, + size_t small_max_size, size_t large_max_size, struct kbase_mem_pool_group *next_pools); /** diff --git a/drivers/gpu/arm/valhall/mali_kbase_pbha.c b/drivers/gpu/arm/valhall/mali_kbase_pbha.c index c201163b5424..b79d419e24de 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_pbha.c +++ b/drivers/gpu/arm/valhall/mali_kbase_pbha.c @@ -24,9 +24,7 @@ #include #include -#if MALI_USE_CSF #define DTB_SET_SIZE 2 -#endif static bool read_setting_valid(unsigned int prod_model, unsigned int id, unsigned int read_setting) { @@ -164,7 +162,6 @@ int kbase_pbha_record_settings(struct kbase_device *kbdev, bool runtime, unsigne unsigned int const sysc_alloc_num = id / sizeof(u32); u32 modified_reg; -#if MALI_USE_CSF if (runtime) { uint i; @@ -175,9 +172,6 @@ int kbase_pbha_record_settings(struct kbase_device *kbdev, bool runtime, unsigne kbase_reg_read32(kbdev, GPU_SYSC_ALLOC_OFFSET(i)); kbase_pm_context_idle(kbdev); } -#else - CSTD_UNUSED(runtime); -#endif /* MALI_USE_CSF */ modified_reg = kbdev->sysc_alloc[sysc_alloc_num]; @@ -224,7 +218,6 @@ int kbase_pbha_record_settings(struct kbase_device *kbdev, bool runtime, unsigne void kbase_pbha_write_settings(struct kbase_device *kbdev) { -#if MALI_USE_CSF if (kbasep_pbha_supported(kbdev)) { uint i; @@ -249,12 +242,8 @@ void kbase_pbha_write_settings(struct kbase_device *kbdev) kbase_reg_write32(kbdev, GPU_SYSC_PBHA_OVERRIDE_OFFSET(reg_index), pbha_override_val); } -#else - CSTD_UNUSED(kbdev); -#endif /* MALI_USE_CSF */ } -#if MALI_USE_CSF static int kbase_pbha_read_int_id_override_property(struct kbase_device *kbdev, const struct device_node *pbha_node) { @@ -376,11 +365,9 @@ static int kbase_pbha_read_mma_wa_id_property(struct kbase_device *kbdev, kbdev->mma_wa_id = mma_wa_id; return 0; } -#endif /* MALI_USE_CSF */ int kbase_pbha_read_dtb(struct kbase_device *kbdev) { -#if MALI_USE_CSF const struct device_node *pbha_node; int err; @@ -404,7 +391,4 @@ int kbase_pbha_read_dtb(struct kbase_device *kbdev) err = kbase_pbha_read_mma_wa_id_property(kbdev, pbha_node); return err; -#else - return 0; -#endif } diff --git a/drivers/gpu/arm/valhall/mali_kbase_pbha_debugfs.c b/drivers/gpu/arm/valhall/mali_kbase_pbha_debugfs.c index 81f2df5ea977..8341d664dd34 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_pbha_debugfs.c +++ b/drivers/gpu/arm/valhall/mali_kbase_pbha_debugfs.c @@ -25,9 +25,7 @@ #include #include -#if MALI_USE_CSF #include "backend/gpu/mali_kbase_pm_internal.h" -#endif static int int_id_overrides_show(struct seq_file *sfile, void *data) { @@ -43,11 +41,7 @@ static int int_id_overrides_show(struct seq_file *sfile, void *data) for (i = 0; i < GPU_SYSC_ALLOC_COUNT; ++i) { uint j; -#if MALI_USE_CSF u32 reg = kbase_reg_read32(kbdev, GPU_SYSC_ALLOC_OFFSET(i)); -#else /* MALI_USE_CSF */ - u32 reg = 0; -#endif /* MALI_USE_CSF */ for (j = 0; j < sizeof(u32); ++j) { u8 r_val = 0; @@ -120,7 +114,6 @@ static int int_id_overrides_open(struct inode *in, struct file *file) return single_open(file, int_id_overrides_show, in->i_private); } -#if MALI_USE_CSF /** * propagate_bits_show - Read PBHA bits from L2_CONFIG out to debugfs. * @@ -207,7 +200,6 @@ static const struct file_operations pbha_propagate_bits_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif /* MALI_USE_CSF */ static const struct file_operations pbha_int_id_overrides_fops = { .owner = THIS_MODULE, @@ -233,10 +225,8 @@ void kbase_pbha_debugfs_init(struct kbase_device *kbdev) debugfs_create_file("int_id_overrides", mode, debugfs_pbha_dir, kbdev, &pbha_int_id_overrides_fops); -#if MALI_USE_CSF if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PBHA_HWU)) debugfs_create_file("propagate_bits", mode, debugfs_pbha_dir, kbdev, &pbha_propagate_bits_fops); -#endif /* MALI_USE_CSF */ } } diff --git a/drivers/gpu/arm/valhall/mali_kbase_pm.c b/drivers/gpu/arm/valhall/mali_kbase_pm.c index e7e70b5389d8..d13cbbe48458 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_pm.c +++ b/drivers/gpu/arm/valhall/mali_kbase_pm.c @@ -35,16 +35,6 @@ #include -int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags) -{ - return kbase_hwaccess_pm_powerup(kbdev, flags); -} - -void kbase_pm_halt(struct kbase_device *kbdev) -{ - kbase_hwaccess_pm_halt(kbdev); -} - void kbase_pm_context_active(struct kbase_device *kbdev) { (void)kbase_pm_context_active_handle_suspend(kbdev, KBASE_PM_SUSPEND_HANDLER_NOT_POSSIBLE); @@ -62,13 +52,11 @@ kbasep_pm_context_active_handle_suspend_locked(struct kbase_device *kbdev, current->pid); lockdep_assert_held(&kbdev->pm.lock); -#if MALI_USE_CSF /* Check scheduler lock */ if (sched_lock_held) lockdep_assert_held(&kbdev->csf.scheduler.lock); else kbase_lockdep_assert_not_held(&kbdev->csf.scheduler.lock); -#endif /* If there is an Arbiter, wait for Arbiter to grant GPU back to KBase * so suspend request can be handled. @@ -170,40 +158,20 @@ static void reenable_hwcnt_on_resume(struct kbase_device *kbdev) unsigned long flags; /* Re-enable GPU hardware counters */ -#if MALI_USE_CSF - kbase_csf_scheduler_spin_lock(kbdev, &flags); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - kbase_csf_scheduler_spin_unlock(kbdev, flags); -#else - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#endif + if (kbdev->csf.firmware_hctl_core_pwr) { + kbase_csf_scheduler_spin_lock(kbdev, &flags); + kbase_hwcnt_context_enable(kbdev->hwcnt_gpu_ctx); + kbase_csf_scheduler_spin_unlock(kbdev, flags); + } /* Resume HW counters intermediaries. */ -#if MALI_USE_CSF if (kbdev->csf.firmware_inited) -#endif - { kbase_kinstr_prfcnt_resume(kbdev->kinstr_prfcnt_ctx); - } } static void resume_job_scheduling(struct kbase_device *kbdev) { -#if !MALI_USE_CSF - /* Resume any blocked atoms (which may cause contexts to be scheduled in - * and dependent atoms to run) - */ - kbase_resume_suspended_soft_jobs(kbdev); - - /* Resume the Job Scheduler and associated components, and start running - * atoms - */ - kbasep_js_resume(kbdev); -#else kbase_csf_scheduler_pm_resume(kbdev); -#endif } int kbase_pm_driver_suspend(struct kbase_device *kbdev) @@ -214,17 +182,14 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) /* Suspend HW counter intermediaries. This blocks until workers and timers * are no longer running. */ -#if MALI_USE_CSF if (kbdev->csf.firmware_inited) -#endif - { kbase_kinstr_prfcnt_suspend(kbdev->kinstr_prfcnt_ctx); - } /* Disable GPU hardware counters. * This call will block until counters are disabled. */ - kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); + if (kbdev->csf.firmware_hctl_core_pwr) + kbase_hwcnt_context_disable(kbdev->hwcnt_gpu_ctx); mutex_lock(&kbdev->pm.lock); if (WARN_ON(kbase_pm_is_suspending(kbdev))) { @@ -238,20 +203,9 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) if (kbase_has_arbiter(kbdev)) { unsigned long flags; -#if MALI_USE_CSF spin_lock_irqsave(&kbdev->hwaccess_lock, flags); kbase_disjoint_state_up(kbdev); spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#else - unsigned int i; - - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbdev->js_data.runpool_irq.submit_allowed = 0; - kbase_disjoint_state_up(kbdev); - for (i = 0; i < kbdev->gpu_props.num_job_slots; i++) - kbase_job_slot_softstop(kbdev, i, NULL); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#endif } /* From now on, the active count will drop towards zero. Sometimes, @@ -260,15 +214,8 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) * all pm references */ -#if !MALI_USE_CSF - /* Suspend job scheduler and associated components, so that it releases all - * the PM active count references - */ - kbasep_js_suspend(kbdev); -#else if (kbase_csf_scheduler_pm_suspend(kbdev)) goto exit; -#endif scheduling_suspended = true; @@ -281,7 +228,6 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) wait_event(kbdev->pm.zero_active_count_wait, kbdev->pm.active_count == 0); dev_dbg(kbdev->dev, ">wait_event - waiting done\n"); -#if MALI_USE_CSF /* At this point, any kbase context termination should either have run to * completion and any further context termination can only begin after * the system resumes. Therefore, it is now safe to skip taking the context @@ -289,7 +235,6 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) */ if (kbase_csf_kcpu_queue_halt_timers(kbdev)) goto exit; -#endif timers_halted = true; @@ -310,21 +255,17 @@ int kbase_pm_driver_suspend(struct kbase_device *kbdev) mutex_unlock(&kbdev->pm.arb_vm_state->vm_state_lock); } -#if MALI_USE_CSF kbase_backend_invalidate_gpu_timestamp_offset(kbdev); -#endif return 0; exit: if (timers_halted) { -#if MALI_USE_CSF /* Resume the timers in case of suspend failure. But that needs to * be done before clearing the 'pm.suspending' flag so as to keep the * context termination blocked. */ kbase_csf_kcpu_queue_resume_timers(kbdev); -#endif } mutex_lock(&kbdev->pm.lock); @@ -358,9 +299,7 @@ void kbase_pm_driver_resume(struct kbase_device *kbdev, bool arb_gpu_start) resume_job_scheduling(kbdev); -#if MALI_USE_CSF kbase_csf_kcpu_queue_resume_timers(kbdev); -#endif /* Matching idle call, to power off the GPU/cores if we didn't actually * need it and the policy doesn't want it on diff --git a/drivers/gpu/arm/valhall/mali_kbase_pm.h b/drivers/gpu/arm/valhall/mali_kbase_pm.h index f176f8cdfc31..e1c5388a7d54 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_pm.h +++ b/drivers/gpu/arm/valhall/mali_kbase_pm.h @@ -52,29 +52,6 @@ struct kbase_device; */ int kbase_pm_init(struct kbase_device *kbdev); -/** - * kbase_pm_powerup - Power up GPU after all modules have been initialized - * and interrupt handlers installed. - * - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * @flags: Flags to pass on to kbase_pm_init_hw - * - * Return: 0 if powerup was successful. - */ -int kbase_pm_powerup(struct kbase_device *kbdev, unsigned int flags); - -/** - * kbase_pm_halt - Halt the power management framework. - * - * @kbdev: The kbase device structure for the device (must be a valid pointer) - * - * Should ensure that no new interrupts are generated, - * but allow any currently running interrupt handlers to complete successfully. - * The GPU is forced off by the time this function returns, regardless of - * whether or not the active power policy asks for the GPU to be powered off. - */ -void kbase_pm_halt(struct kbase_device *kbdev); - /** * kbase_pm_term - Terminate the power management framework. * diff --git a/drivers/gpu/arm/valhall/mali_kbase_reg_track.c b/drivers/gpu/arm/valhall/mali_kbase_reg_track.c index 2d9ae789f7f4..9c26e33be18d 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_reg_track.c +++ b/drivers/gpu/arm/valhall/mali_kbase_reg_track.c @@ -42,14 +42,12 @@ char *kbase_reg_zone_get_name(enum kbase_memory_zone zone) return "CUSTOM_VA"; case EXEC_VA_ZONE: return "EXEC_VA"; -#if MALI_USE_CSF case MCU_SHARED_ZONE: return "MCU_SHARED"; case EXEC_FIXED_VA_ZONE: return "EXEC_FIXED_VA"; case FIXED_VA_ZONE: return "FIXED_VA"; -#endif default: return NULL; } @@ -345,7 +343,7 @@ kbase_region_tracker_find_region_meeting_reqs(struct kbase_va_region *reg_reqs, void kbase_remove_va_region(struct kbase_device *kbdev, struct kbase_va_region *reg) { struct rb_node *rbprev; - struct kbase_reg_zone *zone = container_of(reg->rbtree, struct kbase_reg_zone, reg_rbtree); + struct kbase_reg_zone *zone; struct kbase_va_region *prev = NULL; struct rb_node *rbnext; struct kbase_va_region *next = NULL; @@ -355,6 +353,10 @@ void kbase_remove_va_region(struct kbase_device *kbdev, struct kbase_va_region * int merged_front = 0; int merged_back = 0; + if (WARN_ON(reg == NULL)) + return; + + zone = container_of(reg->rbtree, struct kbase_reg_zone, reg_rbtree); reg_rbtree = reg->rbtree; if (WARN_ON(RB_EMPTY_ROOT(reg_rbtree))) @@ -566,14 +568,10 @@ int kbase_add_va_region(struct kbase_context *kctx, struct kbase_va_region *reg, * Also, executable allocations from EXEC_VA don't need the special * alignment. */ -#if MALI_USE_CSF /* The same is also true for the EXEC_FIXED_VA zone. */ -#endif if (!(reg->flags & KBASE_REG_GPU_NX) && !addr && -#if MALI_USE_CSF ((kbase_bits_to_zone(reg->flags)) != EXEC_FIXED_VA_ZONE) && -#endif ((kbase_bits_to_zone(reg->flags)) != EXEC_VA_ZONE)) { if (cpu_va_bits > gpu_pc_bits) { align = max(align, (size_t)((1ULL << gpu_pc_bits) >> PAGE_SHIFT)); @@ -665,16 +663,6 @@ int kbase_add_va_region_rbtree(struct kbase_device *kbdev, struct kbase_va_regio size_t align_offset = align; size_t align_mask = align - 1; -#if !MALI_USE_CSF - if ((reg->flags & KBASE_REG_TILER_ALIGN_TOP)) { - WARN(align > 1, - "%s with align %lx might not be honored for KBASE_REG_TILER_ALIGN_TOP memory", - __func__, (unsigned long)align); - align_mask = reg->extension - 1; - align_offset = reg->extension - reg->initial_commit; - } -#endif /* !MALI_USE_CSF */ - tmp = kbase_region_tracker_find_region_meeting_reqs(reg, nr_pages, align_offset, align_mask, &start_pfn); if (tmp) { @@ -768,7 +756,6 @@ static int kbase_reg_zone_same_va_init(struct kbase_context *kctx, u64 gpu_va_li lockdep_assert_held(&kctx->reg_lock); -#if MALI_USE_CSF if ((base_pfn + nr_pages) > KBASE_REG_ZONE_EXEC_VA_BASE_64) { /* Depending on how the kernel is configured, it's possible (eg on aarch64) for * same_va_bits to reach 48 bits. Cap same_va_pages so that the same_va zone @@ -776,7 +763,6 @@ static int kbase_reg_zone_same_va_init(struct kbase_context *kctx, u64 gpu_va_li */ nr_pages = KBASE_REG_ZONE_EXEC_VA_BASE_64 - base_pfn; } -#endif err = kbase_reg_zone_init(kctx->kbdev, zone, SAME_VA_ZONE, base_pfn, nr_pages); if (err) return -ENOMEM; @@ -841,17 +827,9 @@ static inline u64 kbase_get_exec_va_zone_base(struct kbase_context *kctx) { u64 base_pfn; -#if MALI_USE_CSF base_pfn = KBASE_REG_ZONE_EXEC_VA_BASE_64; if (kbase_ctx_compat_mode(kctx)) base_pfn = KBASE_REG_ZONE_EXEC_VA_BASE_32; -#else - CSTD_UNUSED(kctx); - /* EXEC_VA zone's codepaths are slightly easier when its base_pfn is - * initially U64_MAX - */ - base_pfn = U64_MAX; -#endif return base_pfn; } @@ -864,10 +842,6 @@ static inline int kbase_reg_zone_exec_va_init(struct kbase_context *kctx, u64 gp CSTD_UNUSED(gpu_va_limit); -#if !MALI_USE_CSF - nr_pages = 0; -#endif - return kbase_reg_zone_init(kctx->kbdev, zone, EXEC_VA_ZONE, base_pfn, nr_pages); } @@ -878,7 +852,6 @@ static void kbase_reg_zone_exec_va_term(struct kbase_context *kctx) kbase_reg_zone_term(zone); } -#if MALI_USE_CSF static inline u64 kbase_get_exec_fixed_va_zone_base(struct kbase_context *kctx) { return kbase_get_exec_va_zone_base(kctx) + KBASE_REG_ZONE_EXEC_VA_SIZE; @@ -931,7 +904,6 @@ static void kbase_reg_zone_fixed_va_term(struct kbase_context *kctx) kbase_reg_zone_term(zone); } -#endif typedef int kbase_memory_zone_init(struct kbase_context *kctx, u64 gpu_va_limit); typedef void kbase_memory_zone_term(struct kbase_context *kctx); @@ -949,13 +921,11 @@ static const struct kbase_memory_zone_init_meta zones_init[] = { "Could not initialize CUSTOM_VA zone" }, [EXEC_VA_ZONE] = { kbase_reg_zone_exec_va_init, kbase_reg_zone_exec_va_term, "Could not initialize EXEC_VA zone" }, -#if MALI_USE_CSF [EXEC_FIXED_VA_ZONE] = { kbase_reg_zone_exec_fixed_va_init, kbase_reg_zone_exec_fixed_va_term, "Could not initialize EXEC_FIXED_VA zone" }, [FIXED_VA_ZONE] = { kbase_reg_zone_fixed_va_init, kbase_reg_zone_fixed_va_term, "Could not initialize FIXED_VA zone" }, -#endif }; int kbase_region_tracker_init(struct kbase_context *kctx) @@ -975,9 +945,7 @@ int kbase_region_tracker_init(struct kbase_context *kctx) goto term; } } -#if MALI_USE_CSF INIT_LIST_HEAD(&kctx->csf.event_pages_head); -#endif kctx->jit_va = false; kbase_gpu_vm_unlock(kctx); @@ -1217,16 +1185,6 @@ KBASE_EXPORT_TEST_API(kbase_region_tracker_init_jit); int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages) { -#if !MALI_USE_CSF - struct kbase_reg_zone *exec_va_zone; - struct kbase_reg_zone *target_zone; - struct kbase_va_region *target_reg; - u64 target_zone_base_addr; - enum kbase_memory_zone target_zone_id; - u64 exec_va_start; - int err; -#endif - /* The EXEC_VA zone shall be created by making space either: * - for 64-bit clients, at the end of the process's address space * - for 32-bit clients, in the CUSTOM zone @@ -1239,85 +1197,14 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages if (exec_va_pages == 0 || exec_va_pages > KBASE_REG_ZONE_EXEC_VA_MAX_PAGES) return -EINVAL; -#if MALI_USE_CSF /* For CSF GPUs we now setup the EXEC_VA zone during initialization, * so this request is a null-op. */ CSTD_UNUSED(kctx); return 0; -#else - kbase_gpu_vm_lock(kctx); - - /* Verify that we've not already created a EXEC_VA zone, and that the - * EXEC_VA zone must come before JIT's CUSTOM_VA. - */ - if (kbase_has_exec_va_zone_locked(kctx) || kctx->jit_va) { - err = -EPERM; - goto exit_unlock; - } - - if (exec_va_pages > kctx->gpu_va_end) { - err = -ENOMEM; - goto exit_unlock; - } - - /* Verify no allocations have already been made */ - if (kbase_region_tracker_has_allocs(kctx)) { - err = -ENOMEM; - goto exit_unlock; - } - - if (kbase_ctx_compat_mode(kctx)) { - /* 32-bit client: take from CUSTOM_VA zone */ - target_zone_id = CUSTOM_VA_ZONE; - } else { - /* 64-bit client: take from SAME_VA zone */ - target_zone_id = SAME_VA_ZONE; - } - - target_zone = kbase_ctx_reg_zone_get(kctx, target_zone_id); - target_zone_base_addr = target_zone->base_pfn << PAGE_SHIFT; - - target_reg = kbase_region_tracker_find_region_base_address(kctx, target_zone_base_addr); - if (WARN(!target_reg, - "Already found a free region at the start of every zone, but now cannot find any region for zone base 0x%.16llx zone %s", - (unsigned long long)target_zone_base_addr, - kbase_reg_zone_get_name(target_zone_id))) { - err = -ENOMEM; - goto exit_unlock; - } - /* kbase_region_tracker_has_allocs() above has already ensured that all - * of the zones have no allocs, so no need to check that again on - * target_reg - */ - WARN_ON((!(target_reg->flags & KBASE_REG_FREE)) || - target_reg->nr_pages != target_zone->va_size_pages); - - if (target_reg->nr_pages <= exec_va_pages || target_zone->va_size_pages <= exec_va_pages) { - err = -ENOMEM; - goto exit_unlock; - } - - /* Taken from the end of the target zone */ - exec_va_start = kbase_reg_zone_end_pfn(target_zone) - exec_va_pages; - exec_va_zone = kbase_ctx_reg_zone_get(kctx, EXEC_VA_ZONE); - if (kbase_reg_zone_init(kctx->kbdev, exec_va_zone, EXEC_VA_ZONE, exec_va_start, - exec_va_pages)) - return -ENOMEM; - - /* Update target zone and corresponding region */ - target_reg->nr_pages -= exec_va_pages; - target_zone->va_size_pages -= exec_va_pages; - err = 0; - -exit_unlock: - kbase_gpu_vm_unlock(kctx); - return err; -#endif /* MALI_USE_CSF */ } KBASE_EXPORT_TEST_API(kbase_region_tracker_init_exec); -#if MALI_USE_CSF void kbase_mcu_shared_interface_region_tracker_term(struct kbase_device *kbdev) { kbase_reg_zone_term(&kbdev->csf.mcu_shared_zone); @@ -1328,7 +1215,6 @@ int kbase_mcu_shared_interface_region_tracker_init(struct kbase_device *kbdev) return kbase_reg_zone_init(kbdev, &kbdev->csf.mcu_shared_zone, MCU_SHARED_ZONE, KBASE_REG_ZONE_MCU_SHARED_BASE, MCU_SHARED_ZONE_SIZE); } -#endif /** * kbase_alloc_free_region - Allocate a free region object. @@ -1410,12 +1296,10 @@ KBASE_EXPORT_TEST_API(kbase_ctx_alloc_free_region); */ void kbase_free_alloced_region(struct kbase_va_region *reg) { -#if MALI_USE_CSF if (kbase_bits_to_zone(reg->flags) == MCU_SHARED_ZONE) { kfree(reg); return; } -#endif if (!(reg->flags & KBASE_REG_FREE)) { struct kbase_context *kctx = kbase_reg_to_kctx(reg); @@ -1427,7 +1311,6 @@ void kbase_free_alloced_region(struct kbase_va_region *reg) dev_dbg(kctx->kbdev->dev, "Freeing memory region %pK\n of zone %s", (void *)reg, kbase_reg_zone_get_name(kbase_bits_to_zone(reg->flags))); -#if MALI_USE_CSF if (reg->flags & KBASE_REG_CSF_EVENT) /* * This should not be reachable if called from 'mcu_shared' functions @@ -1437,7 +1320,6 @@ void kbase_free_alloced_region(struct kbase_va_region *reg) */ kbase_unlink_event_mem_page(kctx, reg); -#endif mutex_lock(&kctx->jit_evict_lock); diff --git a/drivers/gpu/arm/valhall/mali_kbase_reg_track.h b/drivers/gpu/arm/valhall/mali_kbase_reg_track.h index d29999fdcb9a..376951a9d569 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_reg_track.h +++ b/drivers/gpu/arm/valhall/mali_kbase_reg_track.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2023-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -33,22 +33,13 @@ struct kbase_va_region; struct kbase_device; struct kmem_cache; -#if MALI_USE_CSF /* Space for 8 different zones */ #define KBASE_REG_ZONE_BITS 3 -#else -/* Space for 4 different zones */ -#define KBASE_REG_ZONE_BITS 2 -#endif /** * KBASE_REG_ZONE_MAX - Maximum number of GPU memory region zones */ -#if MALI_USE_CSF #define KBASE_REG_ZONE_MAX 6ul -#else -#define KBASE_REG_ZONE_MAX 4ul -#endif /* The bits 11-13 (inclusive) of the kbase_va_region flag are reserved * for information about the zone in which it was allocated. @@ -62,22 +53,10 @@ struct kmem_cache; #define KBASE_REG_ZONE_CUSTOM_VA_BASE (0x100000000ULL >> PAGE_SHIFT) -#if MALI_USE_CSF /* only used with 32-bit clients */ /* On a 32bit platform, custom VA should be wired from 4GB to 2^(43). */ #define KBASE_REG_ZONE_CUSTOM_VA_SIZE (((1ULL << 43) >> PAGE_SHIFT) - KBASE_REG_ZONE_CUSTOM_VA_BASE) -#else -/* only used with 32-bit clients */ -/* On a 32bit platform, custom VA should be wired from 4GB to the VA limit of the - * GPU. Unfortunately, the Linux mmap() interface limits us to 2^32 pages (2^44 - * bytes, see mmap64 man page for reference). So we put the default limit to the - * maximum possible on Linux and shrink it down, if required by the GPU, during - * initialization. - */ -#define KBASE_REG_ZONE_CUSTOM_VA_SIZE (((1ULL << 44) >> PAGE_SHIFT) - KBASE_REG_ZONE_CUSTOM_VA_BASE) -/* end 32-bit clients only */ -#endif /* The starting address and size of the GPU-executable zone are dynamic * and depend on the platform and the number of pages requested by the @@ -86,7 +65,6 @@ struct kmem_cache; #define KBASE_REG_ZONE_EXEC_VA_MAX_PAGES ((1ULL << 32) >> PAGE_SHIFT) /* 4 GB */ #define KBASE_REG_ZONE_EXEC_VA_SIZE KBASE_REG_ZONE_EXEC_VA_MAX_PAGES -#if MALI_USE_CSF #define KBASE_REG_ZONE_MCU_SHARED_BASE (0x04000000ULL >> PAGE_SHIFT) #define MCU_SHARED_ZONE_SIZE (((0x08000000ULL) >> PAGE_SHIFT) - KBASE_REG_ZONE_MCU_SHARED_BASE) @@ -109,8 +87,6 @@ struct kmem_cache; #define KBASE_REG_ZONE_FIXED_VA_END_64 ((1ULL << 48) >> PAGE_SHIFT) #define KBASE_REG_ZONE_FIXED_VA_END_32 ((1ULL << 44) >> PAGE_SHIFT) -#endif - /** * enum kbase_memory_zone - Kbase memory zone identifier * @SAME_VA_ZONE: Memory zone for allocations where the GPU and CPU VA coincide. @@ -142,17 +118,11 @@ enum kbase_memory_zone { SAME_VA_ZONE, CUSTOM_VA_ZONE, EXEC_VA_ZONE, -#if IS_ENABLED(MALI_USE_CSF) EXEC_FIXED_VA_ZONE, FIXED_VA_ZONE, MCU_SHARED_ZONE, -#endif MEMORY_ZONE_MAX, -#if IS_ENABLED(MALI_USE_CSF) CONTEXT_ZONE_MAX = FIXED_VA_ZONE + 1 -#else - CONTEXT_ZONE_MAX = EXEC_VA_ZONE + 1 -#endif }; /** @@ -196,7 +166,7 @@ unsigned long kbase_zone_to_bits(enum kbase_memory_zone zone); enum kbase_memory_zone kbase_bits_to_zone(unsigned long zone_bits); /** - * kbase_mem_zone_get_name - Get the string name for a given memory zone + * kbase_reg_zone_get_name - Get the string name for a given memory zone * @zone: Memory zone identifier * * Return: string for valid memory zone, NULL otherwise @@ -212,11 +182,7 @@ char *kbase_reg_zone_get_name(enum kbase_memory_zone zone); */ static inline bool kbase_is_ctx_reg_zone(enum kbase_memory_zone zone) { -#if MALI_USE_CSF return !(zone == MCU_SHARED_ZONE); -#else - return true; -#endif } /** diff --git a/drivers/gpu/arm/valhall/mali_kbase_softjobs.c b/drivers/gpu/arm/valhall/mali_kbase_softjobs.c index 9f060f42d8dd..df66b3b81609 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_softjobs.c +++ b/drivers/gpu/arm/valhall/mali_kbase_softjobs.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -41,830 +40,6 @@ #include #include -#if !MALI_USE_CSF - -/** - * struct kbase_external_resource_list - Structure which describes a list of external - * resources. This structure is used for the processing of - * EXT_RES_MAP and EXT_RES_UNMAP softjobs, instead of ioctl - * structure 'base_external_resource_list'. This is done to - * avoid UBSAN falsely detecting that an out of bound access - * is going to be made for ext_res[1] array, defined inside - * 'base_external_resource_list', when number of external - * resources to be processed are more than 1. - * - * @count: The number of external resources. - * @ext_res: Pointer to an array of external resources. - */ -struct kbase_external_resource_list { - u64 count; - struct base_external_resource *ext_res; -}; - -/** - * DOC: This file implements the logic behind software only jobs that are - * executed within the driver rather than being handed over to the GPU. - */ - -static void kbasep_add_waiting_soft_job(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - unsigned long lflags; - - spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); - list_add_tail(&katom->queue, &kctx->waiting_soft_jobs); - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); -} - -void kbasep_remove_waiting_soft_job(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - unsigned long lflags; - - spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); - list_del(&katom->queue); - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); -} - -static void kbasep_add_waiting_with_timeout(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - - /* Record the start time of this atom so we could cancel it at - * the right time. - */ - katom->start_timestamp = ktime_get_raw(); - - /* Add the atom to the waiting list before the timer is - * (re)started to make sure that it gets processed. - */ - kbasep_add_waiting_soft_job(katom); - - /* Schedule timeout of this atom after a period if it is not active */ - if (!timer_pending(&kctx->soft_job_timeout)) { - unsigned int timeout_ms = - (unsigned int)atomic_read(&kctx->kbdev->js_data.soft_job_timeout_ms); - mod_timer(&kctx->soft_job_timeout, jiffies + msecs_to_jiffies(timeout_ms)); - } -} - -static int kbasep_read_soft_event_status(struct kbase_context *kctx, u64 evt, unsigned char *status) -{ - unsigned char *mapped_evt; - struct kbase_vmap_struct map; - - mapped_evt = kbase_vmap_prot(kctx, evt, sizeof(*mapped_evt), KBASE_REG_CPU_RD, &map); - if (!mapped_evt) - return -EFAULT; - - *status = *mapped_evt; - - kbase_vunmap(kctx, &map); - - return 0; -} - -static int kbasep_write_soft_event_status(struct kbase_context *kctx, u64 evt, - unsigned char new_status) -{ - unsigned char *mapped_evt; - struct kbase_vmap_struct map; - - if ((new_status != BASE_JD_SOFT_EVENT_SET) && (new_status != BASE_JD_SOFT_EVENT_RESET)) - return -EINVAL; - - mapped_evt = kbase_vmap_prot(kctx, evt, sizeof(*mapped_evt), KBASE_REG_CPU_WR, &map); - if (!mapped_evt) - return -EFAULT; - - *mapped_evt = new_status; - - kbase_vunmap(kctx, &map); - - return 0; -} - -static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) -{ - struct kbase_vmap_struct map; - void *user_result; - struct timespec64 ts; - struct base_dump_cpu_gpu_counters data; - u64 system_time = 0ULL; - u64 cycle_counter; - u64 jc = katom->jc; - struct kbase_context *kctx = katom->kctx; - int pm_active_err; - - memset(&data, 0, sizeof(data)); - - /* Take the PM active reference as late as possible - otherwise, it could - * delay suspend until we process the atom (which may be at the end of a - * long chain of dependencies - */ - if (kbase_has_arbiter(kctx->kbdev)) - atomic_inc(&kctx->kbdev->pm.gpu_users_waiting); - pm_active_err = kbase_pm_context_active_handle_suspend( - kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); - if (pm_active_err) { - struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data; - - /* We're suspended - queue this on the list of suspended jobs - * Use dep_item[1], because dep_item[0] was previously in use - * for 'waiting_soft_jobs'. - */ - mutex_lock(&js_devdata->runpool_mutex); - list_add_tail(&katom->dep_item[1], &js_devdata->suspended_soft_jobs_list); - mutex_unlock(&js_devdata->runpool_mutex); - - /* Also adding this to the list of waiting soft job */ - kbasep_add_waiting_soft_job(katom); - - return pm_active_err; - } else if (kbase_has_arbiter(kctx->kbdev)) - atomic_dec(&kctx->kbdev->pm.gpu_users_waiting); - - kbase_backend_get_gpu_time(kctx->kbdev, &cycle_counter, &system_time, &ts); - - kbase_pm_context_idle(kctx->kbdev); - - data.sec = (__u64)ts.tv_sec; - data.usec = ts.tv_nsec / 1000; - data.system_time = system_time; - data.cycle_counter = cycle_counter; - - /* Assume this atom will be cancelled until we know otherwise */ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - /* GPU_WR access is checked on the range for returning the result to - * userspace for the following reasons: - * - security, this is currently how imported user bufs are checked. - * - userspace ddk guaranteed to assume region was mapped as GPU_WR - */ - user_result = kbase_vmap_prot(kctx, jc, sizeof(data), KBASE_REG_GPU_WR, &map); - if (!user_result) - return 0; - - memcpy(user_result, &data, sizeof(data)); - - kbase_vunmap(kctx, &map); - - /* Atom was fine - mark it as done */ - katom->event_code = BASE_JD_EVENT_DONE; - - return 0; -} - -#if IS_ENABLED(CONFIG_SYNC_FILE) -/* Called by the explicit fence mechanism when a fence wait has completed */ -void kbase_soft_event_wait_callback(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - - mutex_lock(&kctx->jctx.lock); - kbasep_remove_waiting_soft_job(katom); - kbase_finish_soft_job(katom); - if (kbase_jd_done_nolock(katom, true)) - kbase_js_sched_all(kctx->kbdev); - mutex_unlock(&kctx->jctx.lock); -} -#endif - -static void kbasep_soft_event_complete_job(struct work_struct *work) -{ - struct kbase_jd_atom *katom = container_of(work, struct kbase_jd_atom, work); - struct kbase_context *kctx = katom->kctx; - int resched; - - mutex_lock(&kctx->jctx.lock); - resched = kbase_jd_done_nolock(katom, true); - mutex_unlock(&kctx->jctx.lock); - - if (resched) - kbase_js_sched_all(kctx->kbdev); -} - -void kbasep_complete_triggered_soft_events(struct kbase_context *kctx, u64 evt) -{ - int cancel_timer = 1; - struct list_head *entry, *tmp; - unsigned long lflags; - - spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); - list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { - struct kbase_jd_atom *katom = list_entry(entry, struct kbase_jd_atom, queue); - - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_EVENT_WAIT: - if (katom->jc == evt) { - list_del(&katom->queue); - - katom->event_code = BASE_JD_EVENT_DONE; - INIT_WORK(&katom->work, kbasep_soft_event_complete_job); - queue_work(kctx->jctx.job_done_wq, &katom->work); - } else { - /* There are still other waiting jobs, we cannot - * cancel the timer yet. - */ - cancel_timer = 0; - } - break; -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG - case BASE_JD_REQ_SOFT_FENCE_WAIT: - /* Keep the timer running if fence debug is enabled and - * there are waiting fence jobs. - */ - cancel_timer = 0; - break; -#endif - } - } - - if (cancel_timer) - del_timer(&kctx->soft_job_timeout); - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); -} - -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG -static void kbase_fence_debug_check_atom(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct device *dev = kctx->kbdev->dev; - int i; - - for (i = 0; i < 2; i++) { - struct kbase_jd_atom *dep; - - list_for_each_entry(dep, &katom->dep_head[i], dep_item[i]) { - if (dep->status == KBASE_JD_ATOM_STATE_UNUSED || - dep->status == KBASE_JD_ATOM_STATE_COMPLETED) - continue; - - if ((dep->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == - BASE_JD_REQ_SOFT_FENCE_TRIGGER) { - /* Found blocked trigger fence. */ - struct kbase_sync_fence_info info; - - if (!kbase_sync_fence_in_info_get(dep, &info)) { - dev_warn(dev, - "\tVictim trigger atom %d fence [%pK] %s: %s\n", - kbase_jd_atom_id(kctx, dep), info.fence, info.name, - kbase_sync_status_string(info.status)); - } - } - - kbase_fence_debug_check_atom(dep); - } - } -} - -static void kbase_fence_debug_wait_timeout(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct device *dev = katom->kctx->kbdev->dev; - int timeout_ms = atomic_read(&kctx->kbdev->js_data.soft_job_timeout_ms); - unsigned long lflags; - struct kbase_sync_fence_info info; - - spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); - - if (kbase_sync_fence_in_info_get(katom, &info)) { - /* Fence must have signaled just after timeout. */ - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); - return; - } - - dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%pK] after %dms\n", kctx->tgid, - kctx->id, kbase_jd_atom_id(kctx, katom), info.fence, timeout_ms); - dev_warn(dev, "\tGuilty fence [%pK] %s: %s\n", info.fence, info.name, - kbase_sync_status_string(info.status)); - - /* Search for blocked trigger atoms */ - kbase_fence_debug_check_atom(katom); - - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); - - kbase_sync_fence_in_dump(katom); -} - -struct kbase_fence_debug_work { - struct kbase_jd_atom *katom; - struct work_struct work; -}; - -static void kbase_fence_debug_wait_timeout_worker(struct work_struct *work) -{ - struct kbase_fence_debug_work *w = container_of(work, struct kbase_fence_debug_work, work); - struct kbase_jd_atom *katom = w->katom; - struct kbase_context *kctx = katom->kctx; - - mutex_lock(&kctx->jctx.lock); - kbase_fence_debug_wait_timeout(katom); - mutex_unlock(&kctx->jctx.lock); - - kfree(w); -} - -static void kbase_fence_debug_timeout(struct kbase_jd_atom *katom) -{ - struct kbase_fence_debug_work *work; - struct kbase_context *kctx = katom->kctx; - - /* Enqueue fence debug worker. Use job_done_wq to get - * debug print ordered with job completion. - */ - work = kzalloc(sizeof(struct kbase_fence_debug_work), GFP_ATOMIC); - /* Ignore allocation failure. */ - if (work) { - work->katom = katom; - INIT_WORK(&work->work, kbase_fence_debug_wait_timeout_worker); - queue_work(kctx->jctx.job_done_wq, &work->work); - } -} -#endif /* CONFIG_MALI_VALHALL_FENCE_DEBUG */ - -void kbasep_soft_job_timeout_worker(struct timer_list *timer) -{ - struct kbase_context *kctx = container_of(timer, struct kbase_context, soft_job_timeout); - u32 timeout_ms = (u32)atomic_read(&kctx->kbdev->js_data.soft_job_timeout_ms); - ktime_t cur_time = ktime_get_raw(); - bool restarting = false; - unsigned long lflags; - struct list_head *entry, *tmp; - - spin_lock_irqsave(&kctx->waiting_soft_jobs_lock, lflags); - list_for_each_safe(entry, tmp, &kctx->waiting_soft_jobs) { - struct kbase_jd_atom *katom = list_entry(entry, struct kbase_jd_atom, queue); - s64 elapsed_time = ktime_to_ms(ktime_sub(cur_time, katom->start_timestamp)); - - if (elapsed_time < (s64)timeout_ms) { - restarting = true; - continue; - } - - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_EVENT_WAIT: - /* Take it out of the list to ensure that it - * will be cancelled in all cases - */ - list_del(&katom->queue); - - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - INIT_WORK(&katom->work, kbasep_soft_event_complete_job); - queue_work(kctx->jctx.job_done_wq, &katom->work); - break; -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG - case BASE_JD_REQ_SOFT_FENCE_WAIT: - kbase_fence_debug_timeout(katom); - break; -#endif - } - } - - if (restarting) - mod_timer(timer, jiffies + msecs_to_jiffies(timeout_ms)); - spin_unlock_irqrestore(&kctx->waiting_soft_jobs_lock, lflags); -} - -static int kbasep_soft_event_wait(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - unsigned char status; - - /* The status of this soft-job is stored in jc */ - if (kbasep_read_soft_event_status(kctx, katom->jc, &status)) { - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - return 0; - } - - if (status == BASE_JD_SOFT_EVENT_SET) - return 0; /* Event already set, nothing to do */ - - kbasep_add_waiting_with_timeout(katom); - - return 1; -} - -static void kbasep_soft_event_update_locked(struct kbase_jd_atom *katom, unsigned char new_status) -{ - /* Complete jobs waiting on the same event */ - struct kbase_context *kctx = katom->kctx; - - if (kbasep_write_soft_event_status(kctx, katom->jc, new_status) != 0) { - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - return; - } - - if (new_status == BASE_JD_SOFT_EVENT_SET) - kbasep_complete_triggered_soft_events(kctx, katom->jc); -} - -/** - * kbase_soft_event_update() - Update soft event state - * @kctx: Pointer to context - * @event: Event to update - * @new_status: New status value of event - * - * Update the event, and wake up any atoms waiting for the event. - * - * Return: 0 on success, a negative error code on failure. - */ -int kbase_soft_event_update(struct kbase_context *kctx, u64 event, unsigned char new_status) -{ - int err = 0; - - mutex_lock(&kctx->jctx.lock); - - if (kbasep_write_soft_event_status(kctx, event, new_status)) { - err = -ENOENT; - goto out; - } - - if (new_status == BASE_JD_SOFT_EVENT_SET) - kbasep_complete_triggered_soft_events(kctx, event); - -out: - mutex_unlock(&kctx->jctx.lock); - - return err; -} - -static void kbasep_soft_event_cancel_job(struct kbase_jd_atom *katom) -{ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - if (kbase_jd_done_nolock(katom, true)) - kbase_js_sched_all(katom->kctx->kbdev); -} - -#if IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST -static void kbase_debug_copy_finish(struct kbase_jd_atom *katom) -{ - struct kbase_debug_copy_buffer *buffers = katom->softjob_data; - unsigned int i; - unsigned int nr = katom->nr_extres; - - if (!buffers) - return; - - kbase_gpu_vm_lock(katom->kctx); - for (i = 0; i < nr; i++) { - uint p; - struct kbase_mem_phy_alloc *gpu_alloc = buffers[i].gpu_alloc; - - if (!buffers[i].pages) - break; - for (p = 0; p < buffers[i].nr_pages; p++) { - struct page *pg = buffers[i].pages[p]; - - if (pg) - put_page(pg); - } - if (buffers[i].is_vmalloc) - vfree(buffers[i].pages); - else - kfree(buffers[i].pages); - if (gpu_alloc) { - switch (gpu_alloc->type) { - case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { - kbase_free_user_buffer(&buffers[i]); - break; - } - default: - /* Nothing to be done. */ - break; - } - kbase_mem_phy_alloc_put(gpu_alloc); - } - } - kbase_gpu_vm_unlock(katom->kctx); - kfree(buffers); - - katom->softjob_data = NULL; -} - -static int kbase_debug_copy_prepare(struct kbase_jd_atom *katom) -{ - struct kbase_debug_copy_buffer *buffers; - struct base_jd_debug_copy_buffer *user_buffers = NULL; - unsigned int i; - unsigned int nr = katom->nr_extres; - int ret = 0; - void __user *user_structs = (void __user *)(uintptr_t)katom->jc; - size_t copy_size; - - if (!user_structs) - return -EINVAL; - - buffers = kcalloc(nr, sizeof(*buffers), GFP_KERNEL); - if (!buffers) { - ret = -ENOMEM; - goto out_cleanup; - } - katom->softjob_data = buffers; - - user_buffers = kmalloc_array(nr, sizeof(*user_buffers), GFP_KERNEL); - - if (!user_buffers) { - ret = -ENOMEM; - goto out_cleanup; - } - - if (check_mul_overflow(sizeof(*user_buffers), (size_t)nr, ©_size)) { - ret = -EINVAL; - goto out_cleanup; - } - - ret = copy_from_user(user_buffers, user_structs, copy_size); - if (ret) { - ret = -EFAULT; - goto out_cleanup; - } - - for (i = 0; i < nr; i++) { - u64 addr = user_buffers[i].address; - u64 page_addr = addr & PAGE_MASK; - u64 end_page_addr = addr + user_buffers[i].size - 1; - u64 last_page_addr = end_page_addr & PAGE_MASK; - size_t nr_pages = (last_page_addr - page_addr) / PAGE_SIZE + 1; - int pinned_pages; - struct kbase_va_region *reg; - struct base_external_resource user_extres; - - if (!addr) - continue; - - if (last_page_addr < page_addr) { - ret = -EINVAL; - goto out_cleanup; - } - - buffers[i].nr_pages = nr_pages; - buffers[i].offset = addr & ~PAGE_MASK; - if (buffers[i].offset >= PAGE_SIZE) { - ret = -EINVAL; - goto out_cleanup; - } - buffers[i].size = user_buffers[i].size; - - if (nr_pages > (KBASE_MEM_PHY_ALLOC_LARGE_THRESHOLD / sizeof(struct page *))) { - buffers[i].is_vmalloc = true; - buffers[i].pages = vzalloc(nr_pages * sizeof(struct page *)); - } else { - buffers[i].is_vmalloc = false; - buffers[i].pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); - } - - if (!buffers[i].pages) { - ret = -ENOMEM; - goto out_cleanup; - } - - pinned_pages = get_user_pages_fast(page_addr, nr_pages, 1, /* Write */ - buffers[i].pages); - if (pinned_pages < 0) { - /* get_user_pages_fast has failed - page array is not - * valid. Don't try to release any pages. - */ - buffers[i].nr_pages = 0; - - ret = pinned_pages; - goto out_cleanup; - } - if ((size_t)pinned_pages != nr_pages) { - /* Adjust number of pages, so that we only attempt to - * release pages in the array that we know are valid. - */ - buffers[i].nr_pages = (unsigned int)pinned_pages; - - ret = -EINVAL; - goto out_cleanup; - } - - user_extres = user_buffers[i].extres; - if (user_extres.ext_resource == 0ULL) { - ret = -EINVAL; - goto out_cleanup; - } - - kbase_gpu_vm_lock(katom->kctx); - reg = kbase_region_tracker_find_region_enclosing_address( - katom->kctx, - user_extres.ext_resource & ~(__u64)BASE_EXT_RES_ACCESS_EXCLUSIVE); - - if (kbase_is_region_invalid_or_free(reg) || reg->gpu_alloc == NULL) { - ret = -EINVAL; - goto out_unlock; - } - - buffers[i].gpu_alloc = kbase_mem_phy_alloc_get(reg->gpu_alloc); - buffers[i].nr_extres_pages = reg->nr_pages; - - if (reg->nr_pages * PAGE_SIZE != buffers[i].size) - dev_warn( - katom->kctx->kbdev->dev, - "Copy buffer is not of same size as the external resource to copy.\n"); - - switch (reg->gpu_alloc->type) { - case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { - struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc; - const unsigned long nr_pages = alloc->imported.user_buf.nr_pages; - const unsigned long start = alloc->imported.user_buf.address; - - if (alloc->imported.user_buf.mm != current->mm) { - ret = -EINVAL; - goto out_unlock; - } - buffers[i].extres_pages = - kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); - if (!buffers[i].extres_pages) { - ret = -ENOMEM; - goto out_unlock; - } - kbase_gpu_vm_unlock(katom->kctx); - ret = get_user_pages_fast(start, nr_pages, 0, buffers[i].extres_pages); - kbase_gpu_vm_lock(katom->kctx); - if (ret != (int)nr_pages) { - /* Adjust number of pages, so that we only - * attempt to release pages in the array that we - * know are valid. - */ - if (ret < 0) - buffers[i].nr_extres_pages = 0; - else - buffers[i].nr_extres_pages = (unsigned int)ret; - - goto out_unlock; - } - ret = 0; - break; - } - default: - /* Nothing to be done. */ - break; - } - kbase_gpu_vm_unlock(katom->kctx); - } - kfree(user_buffers); - - return ret; - -out_unlock: - kbase_gpu_vm_unlock(katom->kctx); - -out_cleanup: - /* Frees allocated memory for kbase_debug_copy_job struct, including - * members, and sets jc to 0 - */ - kbase_debug_copy_finish(katom); - kfree(user_buffers); - - return ret; -} - -#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE -static void *dma_buf_kmap_page(struct kbase_mem_phy_alloc *gpu_alloc, unsigned long page_num, - struct page **page) -{ - struct sg_table *sgt = gpu_alloc->imported.umm.sgt; - struct sg_page_iter sg_iter; - unsigned long page_index = 0; - - if (WARN_ON(gpu_alloc->type != KBASE_MEM_TYPE_IMPORTED_UMM)) - return NULL; - - if (!sgt) - return NULL; - - if (WARN_ON(page_num >= gpu_alloc->nents)) - return NULL; - - for_each_sg_page(sgt->sgl, &sg_iter, sgt->nents, 0) { - if (page_index == page_num) { - *page = sg_page_iter_page(&sg_iter); - - return kbase_kmap(*page); - } - page_index++; - } - - return NULL; -} -#endif - -/** - * kbase_mem_copy_from_extres() - Copy from external resources. - * - * @kctx: kbase context within which the copying is to take place. - * @buf_data: Pointer to the information about external resources: - * pages pertaining to the external resource, number of - * pages to copy. - * - * Return: 0 on success, error code otherwise. - */ -static int kbase_mem_copy_from_extres(struct kbase_context *kctx, - struct kbase_debug_copy_buffer *buf_data) -{ - unsigned int i; - unsigned int target_page_nr = 0; - struct page **pages = buf_data->pages; - u64 offset = buf_data->offset; - size_t extres_size = buf_data->nr_extres_pages * PAGE_SIZE; - size_t to_copy = min(extres_size, buf_data->size); - struct kbase_mem_phy_alloc *gpu_alloc = buf_data->gpu_alloc; - int ret = 0; - size_t dma_to_copy; - - KBASE_DEBUG_ASSERT(pages != NULL); - - kbase_gpu_vm_lock(kctx); - if (!gpu_alloc) { - ret = -EINVAL; - goto out_unlock; - } - - switch (gpu_alloc->type) { - case KBASE_MEM_TYPE_IMPORTED_USER_BUF: { - for (i = 0; i < buf_data->nr_extres_pages && target_page_nr < buf_data->nr_pages; - i++) { - struct page *pg = buf_data->extres_pages[i]; - void *extres_page = kbase_kmap(pg); - if (extres_page) { - ret = kbase_mem_copy_to_pinned_user_pages(pages, extres_page, - &to_copy, - buf_data->nr_pages, - &target_page_nr, offset); - kbase_kunmap(pg, extres_page); - if (ret) - goto out_unlock; - } - } - } break; - case KBASE_MEM_TYPE_IMPORTED_UMM: { - struct dma_buf *dma_buf = gpu_alloc->imported.umm.dma_buf; - - KBASE_DEBUG_ASSERT(dma_buf != NULL); - if (dma_buf->size > buf_data->nr_extres_pages * PAGE_SIZE) - dev_warn(kctx->kbdev->dev, "External resources buffer size mismatch"); - - dma_to_copy = min(dma_buf->size, (size_t)(buf_data->nr_extres_pages * PAGE_SIZE)); - ret = dma_buf_begin_cpu_access(dma_buf, DMA_FROM_DEVICE); - if (ret) - goto out_unlock; - - for (i = 0; i < dma_to_copy / PAGE_SIZE && target_page_nr < buf_data->nr_pages; - i++) { -#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE - struct page *pg; - void *extres_page = dma_buf_kmap_page(gpu_alloc, i, &pg); -#else - void *extres_page = dma_buf_kmap(dma_buf, i); -#endif - if (extres_page) { - ret = kbase_mem_copy_to_pinned_user_pages(pages, extres_page, - &to_copy, - buf_data->nr_pages, - &target_page_nr, offset); - -#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE - kbase_kunmap(pg, extres_page); -#else - dma_buf_kunmap(dma_buf, i, extres_page); -#endif - if (ret) - break; - } - } - dma_buf_end_cpu_access(dma_buf, DMA_FROM_DEVICE); - break; - } - default: - ret = -EINVAL; - } -out_unlock: - kbase_gpu_vm_unlock(kctx); - return ret; -} - -static int kbase_debug_copy(struct kbase_jd_atom *katom) -{ - struct kbase_debug_copy_buffer *buffers = katom->softjob_data; - unsigned int i; - - if (WARN_ON(!buffers)) - return -EINVAL; - - for (i = 0; i < katom->nr_extres; i++) { - int res = kbase_mem_copy_from_extres(katom->kctx, &buffers[i]); - - if (res) - return res; - } - - return 0; -} -#endif /* IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST */ -#endif /* !MALI_USE_CSF */ - #define KBASEP_JIT_ALLOC_GPU_ADDR_ALIGNMENT ((u32)0x7) int kbasep_jit_alloc_validate(struct kbase_context *kctx, struct base_jit_alloc_info *info) @@ -910,817 +85,5 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx, struct base_jit_alloc_ return -EINVAL; #endif -#if !MALI_USE_CSF - /* If BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE is set, heap_info_gpu_addr - * cannot be 0 - */ - if ((info->flags & BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE) && !info->heap_info_gpu_addr) - return -EINVAL; -#endif /* !MALI_USE_CSF */ - return 0; } - -#if !MALI_USE_CSF - -static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) -{ - __user u8 *data = (__user u8 *)(uintptr_t)katom->jc; - struct base_jit_alloc_info *info; - struct kbase_context *kctx = katom->kctx; - struct kbase_device *kbdev = kctx->kbdev; - u32 count; - int ret; - u32 i; - - if (!kbase_mem_allow_alloc(kctx)) { - dev_dbg(kbdev->dev, "Invalid attempt to allocate JIT memory by %s/%d for ctx %d_%d", - current->comm, current->pid, kctx->tgid, kctx->id); - ret = -EINVAL; - goto fail; - } - - /* For backwards compatibility, and to prevent reading more than 1 jit - * info struct on jit version 1 - */ - if (katom->nr_extres == 0) - katom->nr_extres = 1; - count = katom->nr_extres; - - /* Sanity checks */ - if (!data || count > kctx->jit_max_allocations || count > ARRAY_SIZE(kctx->jit_alloc)) { - ret = -EINVAL; - goto fail; - } - - /* Copy the information for safe access and future storage */ - info = kmalloc_array(count, sizeof(*info), GFP_KERNEL); - if (!info) { - ret = -ENOMEM; - goto fail; - } - - katom->softjob_data = info; - - for (i = 0; i < count; i++, info++, data += sizeof(*info)) { - if (copy_from_user(info, data, sizeof(*info)) != 0) { - ret = -EINVAL; - goto free_info; - } - - ret = kbasep_jit_alloc_validate(kctx, info); - if (ret) - goto free_info; - KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITALLOCINFO( - kbdev, katom, info->va_pages, info->commit_pages, info->extension, info->id, - info->bin_id, info->max_allocations, info->flags, info->usage_id); - } - - katom->jit_blocked = false; - - lockdep_assert_held(&kctx->jctx.lock); - list_add_tail(&katom->jit_node, &kctx->jctx.jit_atoms_head); - - /* - * Note: - * The provided info->gpu_alloc_addr isn't validated here as - * userland can cache allocations which means that even - * though the region is valid it doesn't represent the - * same thing it used to. - * - * Complete validation of va_pages, commit_pages and extension - * isn't done here as it will be done during the call to - * kbase_mem_alloc. - */ - return 0; - -free_info: - kfree(katom->softjob_data); - katom->softjob_data = NULL; -fail: - return ret; -} - -static u8 *kbase_jit_free_get_ids(struct kbase_jd_atom *katom) -{ - if (WARN_ON((katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) != BASE_JD_REQ_SOFT_JIT_FREE)) - return NULL; - - return (u8 *)katom->softjob_data; -} - -static void kbase_jit_add_to_pending_alloc_list(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct list_head *target_list_head = NULL; - struct kbase_jd_atom *entry; - - list_for_each_entry(entry, &kctx->jctx.jit_pending_alloc, queue) { - if (katom->age < entry->age) { - target_list_head = &entry->queue; - break; - } - } - - if (target_list_head == NULL) - target_list_head = &kctx->jctx.jit_pending_alloc; - - list_add_tail(&katom->queue, target_list_head); -} - -static int kbase_jit_allocate_process(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct kbase_device *kbdev = kctx->kbdev; - struct base_jit_alloc_info *info; - struct kbase_va_region *reg; - struct kbase_vmap_struct mapping; - u64 *ptr, new_addr; - u32 count = katom->nr_extres; - u32 i; - bool ignore_pressure_limit = false; - - trace_sysgraph(SGR_SUBMIT, kctx->id, kbase_jd_atom_id(kctx, katom)); - - if (katom->jit_blocked) { - list_del(&katom->queue); - katom->jit_blocked = false; - } - - info = katom->softjob_data; - if (WARN_ON(!info)) { - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return 0; - } - - for (i = 0; i < count; i++, info++) { - /* The JIT ID is still in use so fail the allocation */ - if (kctx->jit_alloc[info->id]) { - katom->event_code = BASE_JD_EVENT_MEM_GROWTH_FAILED; - return 0; - } - } - -#if MALI_JIT_PRESSURE_LIMIT_BASE - /* - * If this is the only JIT_ALLOC atom in-flight or if JIT pressure limit - * is disabled at the context scope, then bypass JIT pressure limit - * logic in kbase_jit_allocate(). - */ - if (!kbase_ctx_flag(kctx, KCTX_JPL_ENABLED) || (kctx->jit_current_allocations == 0)) { - ignore_pressure_limit = true; - } -#else - ignore_pressure_limit = true; -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ - - for (i = 0, info = katom->softjob_data; i < count; i++, info++) { - if (kctx->jit_alloc[info->id]) { - /* The JIT ID is duplicated in this atom. Roll back - * previous allocations and fail. - */ - u32 j; - - info = katom->softjob_data; - for (j = 0; j < i; j++, info++) { - kbase_jit_free(kctx, kctx->jit_alloc[info->id]); - kctx->jit_alloc[info->id] = KBASE_RESERVED_REG_JIT_ALLOC; - } - - katom->event_code = BASE_JD_EVENT_MEM_GROWTH_FAILED; - return 0; - } - - /* Create a JIT allocation */ - reg = kbase_jit_allocate(kctx, info, ignore_pressure_limit); - if (!reg) { - struct kbase_jd_atom *jit_atom; - bool can_block = false; - - lockdep_assert_held(&kctx->jctx.lock); - - list_for_each_entry(jit_atom, &kctx->jctx.jit_atoms_head, jit_node) { - if (jit_atom == katom) - break; - - if ((jit_atom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) == - BASE_JD_REQ_SOFT_JIT_FREE) { - u8 *free_ids = kbase_jit_free_get_ids(jit_atom); - - if (free_ids && *free_ids && kctx->jit_alloc[*free_ids]) { - /* A JIT free which is active and - * submitted before this atom - */ - can_block = true; - break; - } - } - } - - if (!can_block) { - /* Mark the failed allocation as well as the - * other un-attempted allocations in the set, - * so we know they are in use even if the - * allocation itself failed. - */ - for (; i < count; i++, info++) { - kctx->jit_alloc[info->id] = KBASE_RESERVED_REG_JIT_ALLOC; - } - - katom->event_code = BASE_JD_EVENT_MEM_GROWTH_FAILED; - dev_warn_ratelimited(kbdev->dev, - "JIT alloc softjob failed: atom id %d\n", - kbase_jd_atom_id(kctx, katom)); - return 0; - } - - /* There are pending frees for an active allocation - * so we should wait to see whether they free the - * memory. Add to the list of atoms for which JIT - * allocation is pending. - */ - kbase_jit_add_to_pending_alloc_list(katom); - katom->jit_blocked = true; - - /* Rollback, the whole set will be re-attempted */ - while (i-- > 0) { - info--; - kbase_jit_free(kctx, kctx->jit_alloc[info->id]); - kctx->jit_alloc[info->id] = NULL; - } - - return 1; - } - - /* Bind it to the user provided ID. */ - kctx->jit_alloc[info->id] = reg; - } - - for (i = 0, info = katom->softjob_data; i < count; i++, info++) { - u64 entry_mmu_flags = 0; - /* - * Write the address of the JIT allocation to the user provided - * GPU allocation. - */ - ptr = kbase_vmap_prot(kctx, info->gpu_alloc_addr, sizeof(*ptr), KBASE_REG_CPU_WR, - &mapping); - if (!ptr) { - /* - * Leave the allocations "live" as the JIT free atom - * will be submitted anyway. - */ - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return 0; - } - - reg = kctx->jit_alloc[info->id]; - new_addr = reg->start_pfn << PAGE_SHIFT; - *ptr = new_addr; - -#if defined(CONFIG_MALI_VECTOR_DUMP) - /* - * Retrieve the mmu flags for JIT allocation - * only if dumping is enabled - */ - entry_mmu_flags = kbase_mmu_create_ate(kbdev, (struct tagged_addr){ 0 }, reg->flags, - MIDGARD_MMU_BOTTOMLEVEL, kctx->jit_group_id); -#endif - - KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT(kbdev, katom, info->gpu_alloc_addr, new_addr, - info->flags, entry_mmu_flags, info->id, - info->commit_pages, info->extension, - info->va_pages); - kbase_vunmap(kctx, &mapping); - - kbase_trace_jit_report_gpu_mem(kctx, reg, KBASE_JIT_REPORT_ON_ALLOC_OR_FREE); - } - - katom->event_code = BASE_JD_EVENT_DONE; - - return 0; -} - -static void kbase_jit_allocate_finish(struct kbase_jd_atom *katom) -{ - struct base_jit_alloc_info *info; - - lockdep_assert_held(&katom->kctx->jctx.lock); - - if (WARN_ON(!katom->softjob_data)) - return; - - /* Remove atom from jit_atoms_head list */ - list_del(&katom->jit_node); - - if (katom->jit_blocked) { - list_del(&katom->queue); - katom->jit_blocked = false; - } - - info = katom->softjob_data; - /* Free the info structure */ - kfree(info); -} - -static int kbase_jit_free_prepare(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - struct kbase_device *kbdev = kctx->kbdev; - __user void *data = (__user void *)(uintptr_t)katom->jc; - u8 *ids; - u32 count = MAX(katom->nr_extres, 1); - u32 i; - int ret; - size_t copy_size; - - /* Sanity checks */ - if (count > ARRAY_SIZE(kctx->jit_alloc)) { - ret = -EINVAL; - goto fail; - } - - /* Copy the information for safe access and future storage */ - ids = kmalloc_array(count, sizeof(*ids), GFP_KERNEL); - if (!ids) { - ret = -ENOMEM; - goto fail; - } - - lockdep_assert_held(&kctx->jctx.lock); - katom->softjob_data = ids; - - /* For backwards compatibility */ - if (katom->nr_extres) { - /* Fail the job if there is no list of ids */ - if (!data) { - ret = -EINVAL; - goto free_info; - } - if (check_mul_overflow(sizeof(*ids), (size_t)count, ©_size)) { - ret = -EINVAL; - goto free_info; - } - - if (copy_from_user(ids, data, copy_size) != 0) { - ret = -EINVAL; - goto free_info; - } - } else { - katom->nr_extres = 1; - *ids = (u8)katom->jc; - } - for (i = 0; i < count; i++) - KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITFREEINFO(kbdev, katom, ids[i]); - - list_add_tail(&katom->jit_node, &kctx->jctx.jit_atoms_head); - - return 0; - -free_info: - kfree(katom->softjob_data); - katom->softjob_data = NULL; -fail: - return ret; -} - -static void kbase_jit_free_process(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - u8 *ids = kbase_jit_free_get_ids(katom); - u32 count = katom->nr_extres; - u32 i; - - if (ids == NULL) { - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return; - } - - for (i = 0; i < count; i++, ids++) { - /* - * If the ID is zero or it is not in use yet then fail the job. - */ - if ((*ids == 0) || (kctx->jit_alloc[*ids] == NULL)) { - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - return; - } - } -} - -static void kbasep_jit_finish_worker(struct work_struct *work) -{ - struct kbase_jd_atom *katom = container_of(work, struct kbase_jd_atom, work); - struct kbase_context *kctx = katom->kctx; - int resched; - - mutex_lock(&kctx->jctx.lock); - kbase_finish_soft_job(katom); - resched = kbase_jd_done_nolock(katom, true); - mutex_unlock(&kctx->jctx.lock); - - if (resched) - kbase_js_sched_all(kctx->kbdev); -} - -void kbase_jit_retry_pending_alloc(struct kbase_context *kctx) -{ - LIST_HEAD(jit_pending_alloc_list); - struct list_head *i, *tmp; - - list_splice_tail_init(&kctx->jctx.jit_pending_alloc, &jit_pending_alloc_list); - - list_for_each_safe(i, tmp, &jit_pending_alloc_list) { - struct kbase_jd_atom *pending_atom = list_entry(i, struct kbase_jd_atom, queue); - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kctx->kbdev, pending_atom); - kbase_kinstr_jm_atom_sw_start(pending_atom); - if (kbase_jit_allocate_process(pending_atom) == 0) { - /* Atom has completed */ - INIT_WORK(&pending_atom->work, kbasep_jit_finish_worker); - queue_work(kctx->jctx.job_done_wq, &pending_atom->work); - } - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kctx->kbdev, pending_atom); - kbase_kinstr_jm_atom_sw_stop(pending_atom); - } -} - -static void kbase_jit_free_finish(struct kbase_jd_atom *katom) -{ - struct kbase_context *kctx = katom->kctx; - u8 *ids; - size_t j; - - lockdep_assert_held(&kctx->jctx.lock); - - ids = kbase_jit_free_get_ids(katom); - if (WARN_ON(ids == NULL)) - return; - - /* Remove this atom from the jit_atoms_head list */ - list_del(&katom->jit_node); - - for (j = 0; j != katom->nr_extres; ++j) { - if ((ids[j] != 0) && (kctx->jit_alloc[ids[j]] != NULL)) { - /* - * If the ID is valid but the allocation request failed - * still succeed this soft job but don't try and free - * the allocation. - */ - if (kctx->jit_alloc[ids[j]] != KBASE_RESERVED_REG_JIT_ALLOC) { - KBASE_TLSTREAM_TL_JIT_USEDPAGES( - kctx->kbdev, kctx->jit_alloc[ids[j]]->gpu_alloc->nents, - ids[j]); - kbase_jit_free(kctx, kctx->jit_alloc[ids[j]]); - } - kctx->jit_alloc[ids[j]] = NULL; - } - } - /* Free the list of ids */ - kfree(ids); - - kbase_jit_retry_pending_alloc(kctx); -} - -static int kbase_ext_res_prepare(struct kbase_jd_atom *katom) -{ - __user struct base_external_resource_list *user_ext_res; - struct kbase_external_resource_list *ext_res; - u64 count = 0; - size_t copy_size; - - user_ext_res = (__user struct base_external_resource_list *)(uintptr_t)katom->jc; - - /* Fail the job if there is no info structure */ - if (!user_ext_res) - return -EINVAL; - - if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0) - return -EINVAL; - - /* Is the number of external resources in range? */ - if (!count || count > BASE_EXT_RES_COUNT_MAX) - return -EINVAL; - - /* Copy the information for safe access and future storage */ - copy_size = sizeof(struct base_external_resource) * count; - ext_res = kmalloc(sizeof(*ext_res) + copy_size, GFP_KERNEL); - if (!ext_res) - return -ENOMEM; - - ext_res->count = count; - ext_res->ext_res = (struct base_external_resource *)(ext_res + 1); - if (copy_from_user(ext_res->ext_res, user_ext_res->ext_res, copy_size) != 0) { - kfree(ext_res); - return -EINVAL; - } - - katom->softjob_data = ext_res; - - return 0; -} - -static void kbase_ext_res_process(struct kbase_jd_atom *katom, bool map) -{ - struct kbase_external_resource_list *ext_res; - uint64_t i; - bool failed = false; - - ext_res = katom->softjob_data; - if (!ext_res) - goto failed_jc; - - kbase_gpu_vm_lock(katom->kctx); - - for (i = 0; i < ext_res->count; i++) { - u64 gpu_addr; - - gpu_addr = ext_res->ext_res[i].ext_resource & ~(__u64)BASE_EXT_RES_ACCESS_EXCLUSIVE; - if (map) { - if (!kbase_sticky_resource_acquire(katom->kctx, gpu_addr, NULL)) - goto failed_loop; - } else { - if (!kbase_sticky_resource_release_force(katom->kctx, NULL, gpu_addr)) - failed = true; - } - } - - /* - * In the case of unmap we continue unmapping other resources in the - * case of failure but will always report failure if _any_ unmap - * request fails. - */ - if (failed) - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - else - katom->event_code = BASE_JD_EVENT_DONE; - - kbase_gpu_vm_unlock(katom->kctx); - - return; - -failed_loop: - while (i > 0) { - u64 const gpu_addr = ext_res->ext_res[i - 1].ext_resource & - ~(__u64)BASE_EXT_RES_ACCESS_EXCLUSIVE; - - kbase_sticky_resource_release_force(katom->kctx, NULL, gpu_addr); - - --i; - } - - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - kbase_gpu_vm_unlock(katom->kctx); - -failed_jc: - return; -} - -static void kbase_ext_res_finish(struct kbase_jd_atom *katom) -{ - struct kbase_external_resource_list *ext_res; - - ext_res = katom->softjob_data; - /* Free the info structure */ - kfree(ext_res); -} - -int kbase_process_soft_job(struct kbase_jd_atom *katom) -{ - int ret = 0; - struct kbase_context *kctx = katom->kctx; - struct kbase_device *kbdev = kctx->kbdev; - - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kbdev, katom); - kbase_kinstr_jm_atom_sw_start(katom); - - trace_sysgraph(SGR_SUBMIT, kctx->id, kbase_jd_atom_id(kctx, katom)); - - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: - ret = kbase_dump_cpu_gpu_time(katom); - break; - -#if IS_ENABLED(CONFIG_SYNC_FILE) - case BASE_JD_REQ_SOFT_FENCE_TRIGGER: - katom->event_code = kbase_sync_fence_out_trigger( - katom, katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); - break; - case BASE_JD_REQ_SOFT_FENCE_WAIT: { - ret = kbase_sync_fence_in_wait(katom); - - if (ret == 1) { -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG - kbasep_add_waiting_with_timeout(katom); -#else - kbasep_add_waiting_soft_job(katom); -#endif - } - break; - } -#endif - case BASE_JD_REQ_SOFT_EVENT_WAIT: - ret = kbasep_soft_event_wait(katom); - break; - case BASE_JD_REQ_SOFT_EVENT_SET: - kbasep_soft_event_update_locked(katom, BASE_JD_SOFT_EVENT_SET); - break; - case BASE_JD_REQ_SOFT_EVENT_RESET: - kbasep_soft_event_update_locked(katom, BASE_JD_SOFT_EVENT_RESET); - break; -#if IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST - case BASE_JD_REQ_SOFT_DEBUG_COPY: { - int res = kbase_debug_copy(katom); - - if (res) - katom->event_code = BASE_JD_EVENT_JOB_INVALID; - break; - } -#endif /* IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST */ - case BASE_JD_REQ_SOFT_JIT_ALLOC: - ret = kbase_jit_allocate_process(katom); - break; - case BASE_JD_REQ_SOFT_JIT_FREE: - kbase_jit_free_process(katom); - break; - case BASE_JD_REQ_SOFT_EXT_RES_MAP: - kbase_ext_res_process(katom, true); - break; - case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: - kbase_ext_res_process(katom, false); - break; - } - - /* Atom is complete */ - KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kbdev, katom); - kbase_kinstr_jm_atom_sw_stop(katom); - return ret; -} - -void kbase_cancel_soft_job(struct kbase_jd_atom *katom) -{ - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { -#if IS_ENABLED(CONFIG_SYNC_FILE) - case BASE_JD_REQ_SOFT_FENCE_WAIT: - kbase_sync_fence_in_cancel_wait(katom); - break; -#endif - case BASE_JD_REQ_SOFT_EVENT_WAIT: - kbasep_soft_event_cancel_job(katom); - break; - default: - /* This soft-job doesn't support cancellation! */ - KBASE_DEBUG_ASSERT(0); - } -} - -int kbase_prepare_soft_job(struct kbase_jd_atom *katom) -{ - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: { - if (!IS_ALIGNED(katom->jc, cache_line_size())) - return -EINVAL; - } break; -#if IS_ENABLED(CONFIG_SYNC_FILE) - case BASE_JD_REQ_SOFT_FENCE_TRIGGER: { - struct base_fence fence; - int fd; - - if (copy_from_user(&fence, (__user void *)(uintptr_t)katom->jc, sizeof(fence)) != 0) - return -EINVAL; - - fd = kbase_sync_fence_out_create(katom, fence.basep.stream_fd); - if (fd < 0) - return -EINVAL; - - fence.basep.fd = fd; - if (copy_to_user((__user void *)(uintptr_t)katom->jc, &fence, sizeof(fence)) != 0) { - kbase_sync_fence_out_remove(katom); - /* fd should have been closed here, but there's - * no good way of doing that. Since - * copy_to_user() very rarely fails, and the fd - * will get closed on process termination this - * won't be a problem. - */ - fence.basep.fd = -EINVAL; - return -EINVAL; - } - } break; - case BASE_JD_REQ_SOFT_FENCE_WAIT: { - struct base_fence fence; - int ret; - - if (copy_from_user(&fence, (__user void *)(uintptr_t)katom->jc, sizeof(fence)) != 0) - return -EINVAL; - - /* Get a reference to the fence object */ - ret = kbase_sync_fence_in_from_fd(katom, fence.basep.fd); - if (ret < 0) - return ret; - } break; -#endif /* CONFIG_SYNC_FILE */ - case BASE_JD_REQ_SOFT_JIT_ALLOC: - return kbase_jit_allocate_prepare(katom); - case BASE_JD_REQ_SOFT_JIT_FREE: - return kbase_jit_free_prepare(katom); - case BASE_JD_REQ_SOFT_EVENT_WAIT: - case BASE_JD_REQ_SOFT_EVENT_SET: - case BASE_JD_REQ_SOFT_EVENT_RESET: - if (katom->jc == 0) - return -EINVAL; - break; -#if IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST - case BASE_JD_REQ_SOFT_DEBUG_COPY: - return kbase_debug_copy_prepare(katom); -#endif /* IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST */ - case BASE_JD_REQ_SOFT_EXT_RES_MAP: - return kbase_ext_res_prepare(katom); - case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: - return kbase_ext_res_prepare(katom); - default: - /* Unsupported soft-job */ - return -EINVAL; - } - return 0; -} - -void kbase_finish_soft_job(struct kbase_jd_atom *katom) -{ - trace_sysgraph(SGR_COMPLETE, katom->kctx->id, kbase_jd_atom_id(katom->kctx, katom)); - - switch (katom->core_req & BASE_JD_REQ_SOFT_JOB_TYPE) { - case BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME: - /* Nothing to do */ - break; -#if IS_ENABLED(CONFIG_SYNC_FILE) - case BASE_JD_REQ_SOFT_FENCE_TRIGGER: - /* If fence has not yet been signaled, do it now */ - kbase_sync_fence_out_trigger(katom, - katom->event_code == BASE_JD_EVENT_DONE ? 0 : -EFAULT); - break; - case BASE_JD_REQ_SOFT_FENCE_WAIT: - /* Release katom's reference to fence object */ - kbase_sync_fence_in_remove(katom); - break; -#endif /* CONFIG_SYNC_FILE */ -#if IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST - case BASE_JD_REQ_SOFT_DEBUG_COPY: - kbase_debug_copy_finish(katom); - break; -#endif /* IS_ENABLED(CONFIG_MALI_VECTOR_DUMP) || MALI_UNIT_TEST */ - case BASE_JD_REQ_SOFT_JIT_ALLOC: - kbase_jit_allocate_finish(katom); - break; - case BASE_JD_REQ_SOFT_EXT_RES_MAP: - kbase_ext_res_finish(katom); - break; - case BASE_JD_REQ_SOFT_EXT_RES_UNMAP: - kbase_ext_res_finish(katom); - break; - case BASE_JD_REQ_SOFT_JIT_FREE: - kbase_jit_free_finish(katom); - break; - } -} - -void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) -{ - LIST_HEAD(local_suspended_soft_jobs); - struct kbase_jd_atom *tmp_iter; - struct kbase_jd_atom *katom_iter; - struct kbasep_js_device_data *js_devdata; - bool resched = false; - - KBASE_DEBUG_ASSERT(kbdev); - - js_devdata = &kbdev->js_data; - - /* Move out the entire list */ - mutex_lock(&js_devdata->runpool_mutex); - list_splice_init(&js_devdata->suspended_soft_jobs_list, &local_suspended_soft_jobs); - mutex_unlock(&js_devdata->runpool_mutex); - - /* - * Each atom must be detached from the list and ran separately - - * it could be re-added to the old list, but this is unlikely - */ - list_for_each_entry_safe(katom_iter, tmp_iter, &local_suspended_soft_jobs, dep_item[1]) { - struct kbase_context *kctx = katom_iter->kctx; - - mutex_lock(&kctx->jctx.lock); - - /* Remove from the global list */ - list_del(&katom_iter->dep_item[1]); - /* Remove from the context's list of waiting soft jobs */ - kbasep_remove_waiting_soft_job(katom_iter); - - if (kbase_process_soft_job(katom_iter) == 0) { - kbase_finish_soft_job(katom_iter); - resched |= kbase_jd_done_nolock(katom_iter, true); - if (kbase_has_arbiter(kctx->kbdev)) - atomic_dec(&kbdev->pm.gpu_users_waiting); - } - mutex_unlock(&kctx->jctx.lock); - } - - if (resched) - kbase_js_sched_all(kbdev); -} -#endif /* !MALI_USE_CSF */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_sync.h b/drivers/gpu/arm/valhall/mali_kbase_sync.h index 350296c5da12..7a91a36471be 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_sync.h +++ b/drivers/gpu/arm/valhall/mali_kbase_sync.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -36,11 +36,6 @@ #include -#if !MALI_USE_CSF -struct kbase_jd_atom; -struct work_struct; -#endif - /** * struct kbase_sync_fence_info - Information about a fence * @fence: Pointer to fence (type is void*, as underlaying struct can differ) @@ -71,30 +66,6 @@ struct kbase_sync_fence_info { */ int kbase_sync_fence_stream_create(const char *name, int *const out_fd); -#if !MALI_USE_CSF -/** - * kbase_sync_fence_out_create - Create an explicit output fence to specified atom - * - * @katom: Atom to assign the new explicit fence to - * @stream_fd: File descriptor for stream object to create fence on - * - * Return: Valid file descriptor to fence or < 0 on error - */ -int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd); - -/** - * kbase_sync_fence_in_from_fd() - Assigns an existing fence to specified atom - * @katom: Atom to assign the existing explicit fence to - * @fd: File descriptor to an existing fence - * - * Assigns an explicit input fence to atom. - * This can later be waited for by calling @kbase_sync_fence_in_wait - * - * Return: 0 on success, < 0 on error - */ -int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd); -#endif /* !MALI_USE_CSF */ - /** * kbase_sync_fence_validate() - Validate a fd to be a valid fence * @@ -107,78 +78,6 @@ int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd); */ int kbase_sync_fence_validate(int fd); -#if !MALI_USE_CSF -/** - * kbase_sync_fence_out_trigger - Signal explicit output fence attached on katom - * @katom: Atom with an explicit fence to signal - * @result: < 0 means signal with error, 0 >= indicates success - * - * Signal output fence attached on katom and remove the fence from the atom. - * - * Return: The "next" event code for atom, typically JOB_CANCELLED or EVENT_DONE - */ -enum base_jd_event_code kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result); - -/** - * kbase_sync_fence_in_wait() - Wait for explicit input fence to be signaled - * @katom: Atom with explicit fence to wait for - * - * If the fence is already signaled, then 0 is returned, and the caller must - * continue processing of the katom. - * - * If the fence isn't already signaled, then this kbase_sync framework will - * take responsibility to continue the processing once the fence is signaled. - * - * Return: 0 if already signaled, otherwise 1 - */ -int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom); - -/** - * kbase_sync_fence_in_cancel_wait() - Cancel explicit input fence waits - * @katom: Atom to cancel wait for - * - * This function is fully responsible for continuing processing of this atom - * (remove_waiting_soft_job + finish_soft_job + jd_done + js_sched_all) - */ -void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom); - -/** - * kbase_sync_fence_in_remove() - Remove the input fence from the katom - * @katom: Atom to remove explicit input fence for - * - * This will also release the corresponding reference. - */ -void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom); - -/** - * kbase_sync_fence_out_remove() - Remove the output fence from the katom - * @katom: Atom to remove explicit output fence for - * - * This will also release the corresponding reference. - */ -void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom); -#endif /* !MALI_USE_CSF */ - -#if !MALI_USE_CSF -/** - * kbase_sync_fence_in_info_get() - Retrieves information about input fence - * @katom: Atom to get fence information from - * @info: Struct to be filled with fence information - * - * Return: 0 on success, < 0 on error - */ -int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, struct kbase_sync_fence_info *info); - -/** - * kbase_sync_fence_out_info_get() - Retrieves information about output fence - * @katom: Atom to get fence information from - * @info: Struct to be filled with fence information - * - * Return: 0 on success, < 0 on error - */ -int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, struct kbase_sync_fence_info *info); -#endif /* !MALI_USE_CSF */ - #if IS_ENABLED(CONFIG_SYNC_FILE) void kbase_sync_fence_info_get(struct dma_fence *fence, struct kbase_sync_fence_info *info); #endif @@ -191,20 +90,4 @@ void kbase_sync_fence_info_get(struct dma_fence *fence, struct kbase_sync_fence_ */ const char *kbase_sync_status_string(int status); -#if !MALI_USE_CSF -/* - * Internal worker used to continue processing of atom. - */ -void kbase_sync_fence_wait_worker(struct work_struct *data); - -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG -/** - * kbase_sync_fence_in_dump() - Trigger a debug dump of atoms input fence state - * - * @katom: Atom to trigger fence debug dump for - */ -void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom); -#endif -#endif /* !MALI_USE_CSF */ - #endif /* MALI_KBASE_SYNC_H */ diff --git a/drivers/gpu/arm/valhall/mali_kbase_sync_common.c b/drivers/gpu/arm/valhall/mali_kbase_sync_common.c index 5ee7fc3ce72b..05b896f4616f 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_sync_common.c +++ b/drivers/gpu/arm/valhall/mali_kbase_sync_common.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2016, 2018-2021 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -29,16 +29,6 @@ #include "mali_kbase.h" #include "mali_kbase_sync.h" -#if !MALI_USE_CSF -void kbase_sync_fence_wait_worker(struct work_struct *data) -{ - struct kbase_jd_atom *katom; - - katom = container_of(data, struct kbase_jd_atom, work); - kbase_soft_event_wait_callback(katom); -} -#endif /* !MALI_USE_CSF */ - const char *kbase_sync_status_string(int status) { if (status == 0) diff --git a/drivers/gpu/arm/valhall/mali_kbase_sync_file.c b/drivers/gpu/arm/valhall/mali_kbase_sync_file.c index 38cd63d7a15b..940bcd034f58 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_sync_file.c +++ b/drivers/gpu/arm/valhall/mali_kbase_sync_file.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2012-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2012-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -52,66 +52,6 @@ int kbase_sync_fence_stream_create(const char *name, int *const out_fd) return 0; } -#if !MALI_USE_CSF -int kbase_sync_fence_out_create(struct kbase_jd_atom *katom, int stream_fd) -{ - struct dma_fence *fence; - struct sync_file *sync_file; - int fd; - - CSTD_UNUSED(stream_fd); - - fence = kbase_fence_out_new(katom); - if (!fence) - return -ENOMEM; - -#if (KERNEL_VERSION(4, 9, 67) >= LINUX_VERSION_CODE) - /* Take an extra reference to the fence on behalf of the sync_file. - * This is only needed on older kernels where sync_file_create() - * does not take its own reference. This was changed in v4.9.68, - * where sync_file_create() now takes its own reference. - */ - dma_fence_get(fence); -#endif - - /* create a sync_file fd representing the fence */ - sync_file = sync_file_create(fence); - if (!sync_file) { -#if (KERNEL_VERSION(4, 9, 67) >= LINUX_VERSION_CODE) - dma_fence_put(fence); -#endif - kbase_fence_out_remove(katom); - return -ENOMEM; - } - - fd = get_unused_fd_flags(O_CLOEXEC); - if (fd < 0) { - fput(sync_file->file); - kbase_fence_out_remove(katom); - return fd; - } - - fd_install((unsigned int)fd, sync_file->file); - - return fd; -} - -int kbase_sync_fence_in_from_fd(struct kbase_jd_atom *katom, int fd) -{ - struct dma_fence *fence = sync_file_get_fence(fd); - - lockdep_assert_held(&katom->kctx->jctx.lock); - - if (!fence) - return -ENOENT; - - kbase_fence_fence_in_set(katom, fence); - katom->dma_fence.fence_cb_added = false; - - return 0; -} -#endif /* !MALI_USE_CSF */ - int kbase_sync_fence_validate(int fd) { struct dma_fence *fence = sync_file_get_fence(fd); @@ -124,175 +64,6 @@ int kbase_sync_fence_validate(int fd) return 0; } -#if !MALI_USE_CSF -enum base_jd_event_code kbase_sync_fence_out_trigger(struct kbase_jd_atom *katom, int result) -{ - int res; - - if (!kbase_fence_out_is_ours(katom)) { - /* Not our fence */ - return BASE_JD_EVENT_JOB_CANCELLED; - } - - res = kbase_fence_out_signal(katom, result); - if (unlikely(res < 0)) { - dev_warn(katom->kctx->kbdev->dev, "fence_signal() failed with %d\n", res); - } - - kbase_sync_fence_out_remove(katom); - - return (result != 0) ? BASE_JD_EVENT_JOB_CANCELLED : BASE_JD_EVENT_DONE; -} - -static void kbase_fence_wait_callback(struct dma_fence *fence, struct dma_fence_cb *cb) -{ - struct kbase_jd_atom *katom = container_of(cb, struct kbase_jd_atom, dma_fence.fence_cb); - struct kbase_context *kctx = katom->kctx; - - CSTD_UNUSED(fence); - - /* Cancel atom if fence is erroneous */ - if (dma_fence_is_signaled(katom->dma_fence.fence_in) && -#if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE || \ - (KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE && \ - KERNEL_VERSION(4, 9, 68) <= LINUX_VERSION_CODE)) - katom->dma_fence.fence_in->error < 0) -#else - katom->dma_fence.fence_in->status < 0) -#endif - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - /* To prevent a potential deadlock we schedule the work onto the - * job_done_wq workqueue - * - * The issue is that we may signal the timeline while holding - * kctx->jctx.lock and the callbacks are run synchronously from - * sync_timeline_signal. So we simply defer the work. - */ - INIT_WORK(&katom->work, kbase_sync_fence_wait_worker); - queue_work(kctx->jctx.job_done_wq, &katom->work); -} - -int kbase_sync_fence_in_wait(struct kbase_jd_atom *katom) -{ - int err; - struct dma_fence *fence; - - lockdep_assert_held(&katom->kctx->jctx.lock); - - fence = katom->dma_fence.fence_in; - if (!fence) - return 0; /* no input fence to wait for, good to go! */ - - err = dma_fence_add_callback(fence, &katom->dma_fence.fence_cb, kbase_fence_wait_callback); - if (err == -ENOENT) { - int fence_status = dma_fence_get_status(fence); - - if (fence_status == 1) { - /* Fence is already signaled with no error. The completion - * for FENCE_WAIT softjob can be done right away. - */ - return 0; - } - - /* Fence shouldn't be in not signaled state */ - if (!fence_status) { - struct kbase_sync_fence_info info; - - kbase_sync_fence_in_info_get(katom, &info); - - dev_warn(katom->kctx->kbdev->dev, - "Unexpected status for fence %s of ctx:%d_%d atom:%d", info.name, - katom->kctx->tgid, katom->kctx->id, - kbase_jd_atom_id(katom->kctx, katom)); - } - - /* If fence is signaled with an error, then the FENCE_WAIT softjob is - * considered to be failed. - */ - } - - if (unlikely(err)) { - /* We should cause the dependent jobs in the bag to be failed. */ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - /* The completion for FENCE_WAIT softjob can be done right away. */ - return 0; - } - - /* Callback was successfully installed */ - katom->dma_fence.fence_cb_added = true; - - /* Completion to be done later by callback/worker */ - return 1; -} - -void kbase_sync_fence_in_cancel_wait(struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&katom->kctx->jctx.lock); - - if (katom->dma_fence.fence_cb_added) { - if (!dma_fence_remove_callback(katom->dma_fence.fence_in, - &katom->dma_fence.fence_cb)) { - /* The callback is already removed so leave the cleanup - * for kbase_fence_wait_callback. - */ - return; - } - } else { - struct kbase_sync_fence_info info; - - kbase_sync_fence_in_info_get(katom, &info); - dev_warn(katom->kctx->kbdev->dev, - "Callback was not added earlier for fence %s of ctx:%d_%d atom:%d", - info.name, katom->kctx->tgid, katom->kctx->id, - kbase_jd_atom_id(katom->kctx, katom)); - } - - /* Wait was cancelled - zap the atoms */ - katom->event_code = BASE_JD_EVENT_JOB_CANCELLED; - - kbasep_remove_waiting_soft_job(katom); - kbase_finish_soft_job(katom); - - if (kbase_jd_done_nolock(katom, true)) - kbase_js_sched_all(katom->kctx->kbdev); -} - -void kbase_sync_fence_out_remove(struct kbase_jd_atom *katom) -{ - kbase_fence_out_remove(katom); -} - -void kbase_sync_fence_in_remove(struct kbase_jd_atom *katom) -{ - lockdep_assert_held(&katom->kctx->jctx.lock); - - if (katom->dma_fence.fence_cb_added) { - bool removed = dma_fence_remove_callback(katom->dma_fence.fence_in, - &katom->dma_fence.fence_cb); - - /* Here it is expected that the callback should have already been removed - * previously either by kbase_sync_fence_in_cancel_wait() or when the fence - * was signaled and kbase_sync_fence_wait_worker() was called. - */ - if (removed) { - struct kbase_sync_fence_info info; - - kbase_sync_fence_in_info_get(katom, &info); - dev_warn( - katom->kctx->kbdev->dev, - "Callback was not removed earlier for fence %s of ctx:%d_%d atom:%d", - info.name, katom->kctx->tgid, katom->kctx->id, - kbase_jd_atom_id(katom->kctx, katom)); - } - } - - kbase_fence_in_remove(katom); - katom->dma_fence.fence_cb_added = false; -} -#endif /* !MALI_USE_CSF */ - void kbase_sync_fence_info_get(struct dma_fence *fence, struct kbase_sync_fence_info *info) { int status; @@ -318,43 +89,3 @@ void kbase_sync_fence_info_get(struct dma_fence *fence, struct kbase_sync_fence_ scnprintf(info->name, sizeof(info->name), "%llu#%llu", fence->context, fence->seqno); #endif } - -#if !MALI_USE_CSF -int kbase_sync_fence_in_info_get(struct kbase_jd_atom *katom, struct kbase_sync_fence_info *info) -{ - struct dma_fence *fence; - - fence = kbase_fence_in_get(katom); - if (!fence) - return -ENOENT; - - kbase_sync_fence_info_get(fence, info); - - kbase_fence_put(fence); - - return 0; -} - -int kbase_sync_fence_out_info_get(struct kbase_jd_atom *katom, struct kbase_sync_fence_info *info) -{ - struct dma_fence *fence; - - fence = kbase_fence_out_get(katom); - if (!fence) - return -ENOENT; - - kbase_sync_fence_info_get(fence, info); - - kbase_fence_put(fence); - - return 0; -} - -#ifdef CONFIG_MALI_VALHALL_FENCE_DEBUG -void kbase_sync_fence_in_dump(struct kbase_jd_atom *katom) -{ - /* Not implemented */ - CSTD_UNUSED(katom); -} -#endif -#endif /* !MALI_USE_CSF*/ diff --git a/drivers/gpu/arm/valhall/mali_linux_trace.h b/drivers/gpu/arm/valhall/mali_linux_trace.h index 4dd5f437dad2..1b73153f6c9d 100644 --- a/drivers/gpu/arm/valhall/mali_linux_trace.h +++ b/drivers/gpu/arm/valhall/mali_linux_trace.h @@ -137,7 +137,6 @@ TRACE_EVENT(mali_total_alloc_pages_change, TP_PROTO(u32 gpu_id, s64 event_id), __print_symbolic(KBASE_MMU_FAULT_STATUS_ACCESS(status), \ KBASE_MMU_FAULT_ACCESS_SYMBOLIC_STRINGS) -#if MALI_USE_CSF #define KBASE_MMU_FAULT_CODE_VALID(code) \ ((code >= 0xC0 && code <= 0xEB) && (!(code >= 0xC5 && code <= 0xC7)) && \ (!(code >= 0xCC && code <= 0xD8)) && (!(code >= 0xDC && code <= 0xDF)) && \ @@ -148,20 +147,6 @@ TRACE_EVENT(mali_total_alloc_pages_change, TP_PROTO(u32 gpu_id, s64 event_id), { 0xD8, "ACCESS_FLAG_" }, { 0xE0, "ADDRESS_SIZE_FAULT_IN" }, \ { 0xE4, "ADDRESS_SIZE_FAULT_OUT" }, \ { 0xE8, "MEMORY_ATTRIBUTES_FAULT_" }) -#else /* MALI_USE_CSF */ -#define KBASE_MMU_FAULT_CODE_VALID(code) \ - ((code >= 0xC0 && code <= 0xEF) && (!(code >= 0xC5 && code <= 0xC6)) && \ - (!(code >= 0xCC && code <= 0xCF)) && (!(code >= 0xD4 && code <= 0xD7)) && \ - (!(code >= 0xDC && code <= 0xDF))) -#define KBASE_MMU_FAULT_CODE_SYMBOLIC_STRINGS \ - _ENSURE_PARENTHESIS({ 0xC0, "TRANSLATION_FAULT_" }, \ - { 0xC4, "TRANSLATION_FAULT(_7==_IDENTITY)_" }, \ - { 0xC8, "PERMISSION_FAULT_" }, { 0xD0, "TRANSTAB_BUS_FAULT_" }, \ - { 0xD8, "ACCESS_FLAG_" }, { 0xE0, "ADDRESS_SIZE_FAULT_IN" }, \ - { 0xE4, "ADDRESS_SIZE_FAULT_OUT" }, \ - { 0xE8, "MEMORY_ATTRIBUTES_FAULT_" }, \ - { 0xEC, "MEMORY_ATTRIBUTES_NONCACHEABLE_" }) -#endif /* MALI_USE_CSF */ #endif /* __TRACE_MALI_MMU_HELPERS */ /* trace_mali_mmu_page_fault_extra_grow @@ -255,35 +240,6 @@ DEFINE_EVENT_PRINT(mali_jit_softjob_template, mali_jit_free, TP_printk("start=0x%llx va_pages=0x%zx backed_size=0x%zx", __entry->start_addr, __entry->nr_pages, __entry->backed_pages)); -#if !MALI_USE_CSF -#if MALI_JIT_PRESSURE_LIMIT_BASE -/* trace_mali_jit_report - * - * Tracepoint about the GPU data structure read to form a just-in-time memory - * allocation report, and its calculated physical page usage - */ -TRACE_EVENT(mali_jit_report, - TP_PROTO(struct kbase_jd_atom *katom, struct kbase_va_region *reg, unsigned int id_idx, - u64 read_val, u64 used_pages), - TP_ARGS(katom, reg, id_idx, read_val, used_pages), - TP_STRUCT__entry(__field(u64, start_addr) __field(u64, read_val) - __field(u64, used_pages) __field(unsigned long, flags) - __field(u8, id_idx) __field(u8, jit_id)), - TP_fast_assign(__entry->start_addr = ((u64)reg->start_pfn) << PAGE_SHIFT; - __entry->read_val = read_val; __entry->used_pages = used_pages; - __entry->flags = reg->flags; __entry->id_idx = id_idx; - __entry->jit_id = katom->jit_ids[id_idx];), - TP_printk("start=0x%llx jit_ids[%u]=%u read_type='%s' read_val=0x%llx used_pages=%llu", - __entry->start_addr, __entry->id_idx, __entry->jit_id, - __print_symbolic(__entry->flags, { 0, "address" }, - { KBASE_REG_TILER_ALIGN_TOP, "address with align" }, - { KBASE_REG_HEAP_INFO_IS_SIZE, "size" }, - { KBASE_REG_HEAP_INFO_IS_SIZE | KBASE_REG_TILER_ALIGN_TOP, - "size with align (invalid)" }), - __entry->read_val, __entry->used_pages)); -#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ -#endif /* !MALI_USE_CSF */ - TRACE_DEFINE_ENUM(KBASE_JIT_REPORT_ON_ALLOC_OR_FREE); #if MALI_JIT_PRESSURE_LIMIT_BASE /* trace_mali_jit_report_pressure diff --git a/drivers/gpu/arm/valhall/mmu/Kbuild b/drivers/gpu/arm/valhall/mmu/Kbuild index bedae1d67275..ac726539f4b1 100644 --- a/drivers/gpu/arm/valhall/mmu/Kbuild +++ b/drivers/gpu/arm/valhall/mmu/Kbuild @@ -23,13 +23,6 @@ valhall_kbase-y += \ mmu/mali_kbase_mmu_hw_direct.o \ mmu/mali_kbase_mmu_faults_decoder_luts.o \ mmu/mali_kbase_mmu_faults_decoder.o \ - mmu/mali_kbase_mmu_mode_aarch64.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += mmu/backend/mali_kbase_mmu_csf.o \ + mmu/mali_kbase_mmu_mode_aarch64.o \ + mmu/backend/mali_kbase_mmu_csf.o \ mmu/backend/mali_kbase_mmu_faults_decoder_luts_csf.o -else - valhall_kbase-y += mmu/backend/mali_kbase_mmu_jm.o \ - mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.o - -endif diff --git a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.c b/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.c deleted file mode 100644 index a053a93978b5..000000000000 --- a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Base kernel MMU faults decoder for Job Manager GPUs. - */ - -#include - -#define GPU_ID_ARCH_ID_MAJOR_GET(gpu_id) ((gpu_id >> 16) & 0xFF) -#define GPU_ID_ARCH_ID_MINOR_AND_REV_GET(gpu_id) (gpu_id & 0xFFFF) -#define NELEMS(s) (sizeof(s) / sizeof((s)[0])) - -struct decode_lut_element { - u16 arch_minor_rev; - u16 key; - const char *text; -}; - -static const char *decode_lut_element_lookup(u16 arch_minor_rev, u16 key, - struct decode_lut_element *decode_element_lut, - unsigned int lut_len) -{ - struct decode_lut_element *p; - - for (p = decode_element_lut; p < decode_element_lut + lut_len; p++) { - if (p->key == key && - (p->arch_minor_rev == 0xffff || p->arch_minor_rev == arch_minor_rev)) - break; - } - if (p < decode_element_lut + lut_len) - return p->text; - else - return "unknown"; -} - -/* Auto-generated code: DO NOT MODIFY! */ - -static struct decode_lut_element lut_fault_source_jm_t_major_9[] = { - { 0xFFFF, 0, "js" }, - { 0xFFFF, 1, "pcm" }, -}; - -const char *decode_fault_source_jm_t(u16 idx, u32 gpu_id) -{ - u16 min_rev = GPU_ID_ARCH_ID_MINOR_AND_REV_GET(gpu_id); - const char *ret = "unknown"; - - switch (GPU_ID_ARCH_ID_MAJOR_GET(gpu_id)) { - case 9: - ret = decode_lut_element_lookup(min_rev, idx, lut_fault_source_jm_t_major_9, - NELEMS(lut_fault_source_jm_t_major_9)); - break; - } - return ret; -} diff --git a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.h b/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.h deleted file mode 100644 index f686e555d86a..000000000000 --- a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_faults_decoder_luts_jm.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _MALI_KBASE_MMU_FAULTS_DECODER_LUTS_JM_H_ -#define _MALI_KBASE_MMU_FAULTS_DECODER_LUTS_JM_H_ -#include - -/** - * decode_fault_source_jm_t() - Get internal requester of a - * fault in a human readable format. - * - * @idx: Internal requester part of SOURCE_ID field of the fault. - * @gpu_id: GPU id composed of arch_major << 16 | arch_minor << 8 | arch_rev. - * - * Return: Internal requester of a fault in a human readable format for a JM core. - */ -const char *decode_fault_source_jm_t(u16 idx, u32 gpu_id); - -#endif /* _MALI_KBASE_MMU_FAULTS_DECODER_LUTS_JM_H_ */ diff --git a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_jm.c b/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_jm.c deleted file mode 100644 index 2ff0c1c0eae8..000000000000 --- a/drivers/gpu/arm/valhall/mmu/backend/mali_kbase_mmu_jm.c +++ /dev/null @@ -1,418 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/** - * DOC: Base kernel MMU management specific for Job Manager GPU. - */ - -#include -#include -#include -#include -#include -#include -#include - -void kbase_mmu_get_as_setup(struct kbase_mmu_table *mmut, struct kbase_mmu_setup *const setup) -{ - /* Set up the required caching policies at the correct indices - * in the memattr register. - */ - setup->memattr = - (KBASE_MEMATTR_IMPL_DEF_CACHE_POLICY - << (KBASE_MEMATTR_INDEX_IMPL_DEF_CACHE_POLICY * 8)) | - (KBASE_MEMATTR_FORCE_TO_CACHE_ALL << (KBASE_MEMATTR_INDEX_FORCE_TO_CACHE_ALL * 8)) | - (KBASE_MEMATTR_WRITE_ALLOC << (KBASE_MEMATTR_INDEX_WRITE_ALLOC * 8)) | - (KBASE_MEMATTR_AARCH64_OUTER_IMPL_DEF << (KBASE_MEMATTR_INDEX_OUTER_IMPL_DEF * 8)) | - (KBASE_MEMATTR_AARCH64_OUTER_WA << (KBASE_MEMATTR_INDEX_OUTER_WA * 8)) | - (KBASE_MEMATTR_AARCH64_NON_CACHEABLE << (KBASE_MEMATTR_INDEX_NON_CACHEABLE * 8)); - - setup->transtab = (u64)mmut->pgd & AS_TRANSTAB_BASE_MASK; - setup->transcfg = AS_TRANSCFG_MODE_SET(0ULL, AS_TRANSCFG_MODE_AARCH64_4K); -} - -void kbase_gpu_report_bus_fault_and_kill(struct kbase_context *kctx, struct kbase_as *as, - struct kbase_fault *fault) -{ - struct kbase_device *const kbdev = kctx->kbdev; - const u32 status = fault->status; - const u32 exception_type = AS_FAULTSTATUS_EXCEPTION_TYPE_GET(status); - const u32 access_type = AS_FAULTSTATUS_ACCESS_TYPE_GET(status); - const u32 source_id = AS_FAULTSTATUS_SOURCE_ID_GET(status); - unsigned int const as_no = as->number; - unsigned long flags; - const uintptr_t fault_addr = fault->addr; - - /* terminal fault, print info about the fault */ - dev_err(kbdev->dev, - "GPU bus fault in AS%u at PA %pK\n" - "raw fault status: 0x%X\n" - "exception type 0x%X: %s\n" - "access type 0x%X: %s\n" - "source id 0x%X (core_id:utlb:IR 0x%X:0x%X:0x%X): %s, %s\n" - "pid: %d\n", - as_no, (void *)fault_addr, status, exception_type, - kbase_gpu_exception_name(exception_type), access_type, - kbase_gpu_access_type_name(kbdev, access_type), source_id, - FAULT_SOURCE_ID_CORE_ID_GET(source_id), FAULT_SOURCE_ID_UTLB_ID_GET(source_id), - fault_source_id_internal_requester_get(kbdev, source_id), - fault_source_id_core_type_description_get(kbdev, source_id), - fault_source_id_internal_requester_get_str(kbdev, source_id, access_type), - kctx->pid); - - /* switch to UNMAPPED mode, will abort all jobs and stop any hw counter - * dumping AS transaction begin - */ - mutex_lock(&kbdev->mmu_hw_mutex); - - /* Set the MMU into unmapped mode */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_mmu_disable(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - mutex_unlock(&kbdev->mmu_hw_mutex); - /* AS transaction end */ - - kbase_mmu_hw_clear_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); - kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); - -} - -/* - * The caller must ensure it's retained the ctx to prevent it from being - * scheduled out whilst it's being worked on. - */ -void kbase_mmu_report_fault_and_kill(struct kbase_context *kctx, struct kbase_as *as, - const char *reason_str, struct kbase_fault *fault) -{ - unsigned long flags; - struct kbase_device *kbdev = kctx->kbdev; - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - unsigned int as_no = as->number; - - /* Make sure the context was active */ - if (WARN_ON(atomic_read(&kctx->refcount) <= 0)) - return; - - if (!kbase_ctx_flag(kctx, KCTX_PAGE_FAULT_REPORT_SKIP)) { - /* decode the fault status */ - const u32 status = fault->status; - const u32 exception_type = AS_FAULTSTATUS_EXCEPTION_TYPE_GET(status); - const u32 access_type = AS_FAULTSTATUS_ACCESS_TYPE_GET(status); - const u32 source_id = AS_FAULTSTATUS_SOURCE_ID_GET(status); - /* terminal fault, print info about the fault */ - if (kbdev->gpu_props.gpu_id.product_model < GPU_ID_MODEL_MAKE(9, 0)) { - dev_err(kbdev->dev, - "Unhandled Page fault in AS%u at VA 0x%016llX\n" - "Reason: %s\n" - "raw fault status: 0x%X\n" - "exception type 0x%X: %s\n" - "access type 0x%X: %s\n" - "pid: %d\n", - as_no, fault->addr, reason_str, status, exception_type, - kbase_gpu_exception_name(exception_type), access_type, - kbase_gpu_access_type_name(kbdev, status), kctx->pid); - } else { - dev_err(kbdev->dev, - "Unhandled Page fault in AS%u at VA 0x%016llX\n" - "Reason: %s\n" - "raw fault status: 0x%X\n" - "exception type 0x%X: %s\n" - "access type 0x%X: %s\n" - "source id 0x%X (core_id:utlb:IR 0x%X:0x%X:0x%X): %s, %s\n" - "pid: %d\n", - as_no, fault->addr, reason_str, status, exception_type, - kbase_gpu_exception_name(exception_type), access_type, - kbase_gpu_access_type_name(kbdev, status), source_id, - FAULT_SOURCE_ID_CORE_ID_GET(source_id), - FAULT_SOURCE_ID_UTLB_ID_GET(source_id), - fault_source_id_internal_requester_get(kbdev, source_id), - fault_source_id_core_type_description_get(kbdev, source_id), - fault_source_id_internal_requester_get_str(kbdev, source_id, - access_type), - kctx->pid); - } - } - - /* hardware counters dump fault handling */ - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - if ((kbdev->hwcnt.kctx) && (kbdev->hwcnt.kctx->as_nr == as_no) && - (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING)) { - if ((fault->addr >= kbdev->hwcnt.addr) && - (fault->addr < (kbdev->hwcnt.addr + kbdev->hwcnt.addr_bytes))) - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_FAULT; - } - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - - /* Stop the kctx from submitting more jobs and cause it to be scheduled - * out/rescheduled - this will occur on releasing the context's refcount - */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbasep_js_clear_submit_allowed(js_devdata, kctx); - - /* Kill any running jobs from the context. Submit is disallowed, so no - * more jobs from this context can appear in the job slots from this - * point on - */ - kbase_backend_jm_kill_running_jobs_from_kctx(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - /* AS transaction begin */ - mutex_lock(&kbdev->mmu_hw_mutex); - - /* switch to UNMAPPED mode, will abort all jobs and stop - * any hw counter dumping - */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_mmu_disable(kctx); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - - mutex_unlock(&kbdev->mmu_hw_mutex); - - /* AS transaction end */ - /* Clear down the fault */ - kbase_mmu_hw_clear_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); - kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); - -} - -/** - * kbase_mmu_interrupt_process() - Process a bus or page fault. - * @kbdev: The kbase_device the fault happened on - * @kctx: The kbase_context for the faulting address space if one was - * found. - * @as: The address space that has the fault - * @fault: Data relating to the fault - * - * This function will process a fault on a specific address space - */ -static void kbase_mmu_interrupt_process(struct kbase_device *kbdev, struct kbase_context *kctx, - struct kbase_as *as, struct kbase_fault *fault) -{ - unsigned long flags; - - lockdep_assert_held(&kbdev->hwaccess_lock); - - dev_dbg(kbdev->dev, "Entering %s kctx %pK, as %pK\n", __func__, (void *)kctx, (void *)as); - - if (!kctx) { - if (kbase_as_has_bus_fault(as, fault)) { - dev_warn( - kbdev->dev, - "Bus error in AS%u at PA 0x%pK with no context present! Spurious IRQ or SW Design Error?\n", - as->number, (void *)(uintptr_t)fault->addr); - } else { - dev_warn( - kbdev->dev, - "Page fault in AS%u at VA 0x%016llx with no context present! Spurious IRQ or SW Design Error?\n", - as->number, fault->addr); - } - /* Since no ctx was found, the MMU must be disabled. */ - WARN_ON(as->current_setup.transtab); - - if (kbase_as_has_bus_fault(as, fault)) { - kbase_mmu_hw_clear_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); - kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED); - } else if (kbase_as_has_page_fault(as, fault)) { - kbase_mmu_hw_clear_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); - kbase_mmu_hw_enable_fault(kbdev, as, KBASE_MMU_FAULT_TYPE_PAGE_UNEXPECTED); - } - - return; - } - - if (kbase_as_has_bus_fault(as, fault)) { - struct kbasep_js_device_data *js_devdata = &kbdev->js_data; - - /* - * hw counters dumping in progress, signal the - * other thread that it failed - */ - spin_lock_irqsave(&kbdev->hwcnt.lock, flags); - if ((kbdev->hwcnt.kctx == kctx) && - (kbdev->hwcnt.backend.state == KBASE_INSTR_STATE_DUMPING)) - kbdev->hwcnt.backend.state = KBASE_INSTR_STATE_FAULT; - - spin_unlock_irqrestore(&kbdev->hwcnt.lock, flags); - - /* - * Stop the kctx from submitting more jobs and cause it - * to be scheduled out/rescheduled when all references - * to it are released - */ - kbasep_js_clear_submit_allowed(js_devdata, kctx); - - dev_warn(kbdev->dev, "Bus error in AS%u at PA=0x%pK, IPA=0x%pK\n", as->number, - (void *)(uintptr_t)fault->addr, (void *)(uintptr_t)fault->extra_addr); - - /* - * We need to switch to UNMAPPED mode - but we do this in a - * worker so that we can sleep - */ - WARN_ON(!queue_work(as->pf_wq, &as->work_busfault)); - atomic_inc(&kbdev->faults_pending); - } else { - WARN_ON(!queue_work(as->pf_wq, &as->work_pagefault)); - atomic_inc(&kbdev->faults_pending); - } - - dev_dbg(kbdev->dev, "Leaving %s kctx %pK, as %pK\n", __func__, (void *)kctx, (void *)as); -} - -static void validate_protected_page_fault(struct kbase_device *kbdev) -{ - /* GPUs which support (native) protected mode shall not report page - * fault addresses unless it has protected debug mode and protected - * debug mode is turned on - */ - u32 protected_debug_mode = 0; - - if (kbase_hw_has_feature(kbdev, KBASE_HW_FEATURE_PROTECTED_DEBUG_MODE)) { - protected_debug_mode = kbase_reg_read32(kbdev, GPU_CONTROL_ENUM(GPU_STATUS)) & - GPU_STATUS_GPU_DBG_ENABLED; - } - - if (!protected_debug_mode) { - /* fault_addr should never be reported in protected mode. - * However, we just continue by printing an error message - */ - dev_err(kbdev->dev, "Fault address reported in protected mode\n"); - } -} - -void kbase_mmu_interrupt(struct kbase_device *kbdev, u32 irq_stat) -{ - const int num_as = 16; - const int busfault_shift = MMU_PAGE_FAULT_FLAGS; - const int pf_shift = 0; - const unsigned long as_bit_mask = (1UL << num_as) - 1; - unsigned long flags; - u32 new_mask; - u32 tmp, bf_bits, pf_bits; - - dev_dbg(kbdev->dev, "Entering %s irq_stat %u\n", __func__, irq_stat); - /* bus faults */ - bf_bits = (irq_stat >> busfault_shift) & as_bit_mask; - /* page faults (note: Ignore ASes with both pf and bf) */ - pf_bits = ((irq_stat >> pf_shift) & as_bit_mask) & ~bf_bits; - - if (WARN_ON(kbdev == NULL)) - return; - - /* remember current mask */ - spin_lock_irqsave(&kbdev->mmu_mask_change, flags); - new_mask = kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK)); - /* mask interrupts for now */ - kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), 0); - spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); - - while (bf_bits | pf_bits) { - struct kbase_as *as; - unsigned int as_no; - struct kbase_context *kctx; - struct kbase_fault *fault; - - /* - * the while logic ensures we have a bit set, no need to check - * for not-found here - */ - as_no = (unsigned int)ffs((int)(bf_bits | pf_bits)) - 1; - as = &kbdev->as[as_no]; - - /* find the fault type */ - if (bf_bits & (1UL << as_no)) - fault = &as->bf_data; - else - fault = &as->pf_data; - - /* - * Refcount the kctx ASAP - it shouldn't disappear anyway, since - * Bus/Page faults _should_ only occur whilst jobs are running, - * and a job causing the Bus/Page fault shouldn't complete until - * the MMU is updated - */ - kctx = kbase_ctx_sched_as_to_ctx_refcount(kbdev, as_no); - - /* find faulting address */ - fault->addr = kbase_reg_read64(kbdev, MMU_AS_OFFSET(as_no, FAULTADDRESS)); - /* Mark the fault protected or not */ - fault->protected_mode = kbdev->protected_mode; - - if (kbdev->protected_mode && fault->addr) { - /* check if address reporting is allowed */ - validate_protected_page_fault(kbdev); - } - - /* report the fault to debugfs */ - kbase_as_fault_debugfs_new(kbdev, as_no); - - /* record the fault status */ - fault->status = kbase_reg_read32(kbdev, MMU_AS_OFFSET(as_no, FAULTSTATUS)); - fault->extra_addr = kbase_reg_read64(kbdev, MMU_AS_OFFSET(as_no, FAULTEXTRA)); - - if (kbase_as_has_bus_fault(as, fault)) { - /* Mark bus fault as handled. - * Note that a bus fault is processed first in case - * where both a bus fault and page fault occur. - */ - bf_bits &= ~(1UL << as_no); - - /* remove the queued BF (and PF) from the mask */ - new_mask &= ~(MMU_BUS_ERROR(as_no) | MMU_PAGE_FAULT(as_no)); - } else { - /* Mark page fault as handled */ - pf_bits &= ~(1UL << as_no); - - /* remove the queued PF from the mask */ - new_mask &= ~MMU_PAGE_FAULT(as_no); - } - - /* Process the interrupt for this address space */ - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); - kbase_mmu_interrupt_process(kbdev, kctx, as, fault); - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - } - - /* reenable interrupts */ - spin_lock_irqsave(&kbdev->mmu_mask_change, flags); - tmp = kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK)); - new_mask |= tmp; - kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), new_mask); - spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); - - dev_dbg(kbdev->dev, "Leaving %s irq_stat %u\n", __func__, irq_stat); -} - -int kbase_mmu_as_init(struct kbase_device *kbdev, unsigned int i) -{ - kbdev->as[i].number = i; - kbdev->as[i].bf_data.addr = 0ULL; - kbdev->as[i].pf_data.addr = 0ULL; - - kbdev->as[i].pf_wq = alloc_workqueue("mali_mmu%u", 0, 0, i); - if (!kbdev->as[i].pf_wq) - return -ENOMEM; - - INIT_WORK(&kbdev->as[i].work_pagefault, kbase_mmu_page_fault_worker); - INIT_WORK(&kbdev->as[i].work_busfault, kbase_mmu_bus_fault_worker); - - return 0; -} diff --git a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.c b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.c index 2e06ec90442e..7db1dfdc6d10 100644 --- a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.c +++ b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -43,9 +43,6 @@ #include #include #include -#if !MALI_USE_CSF -#include -#endif #include #include @@ -323,12 +320,8 @@ static int mmu_insert_pages_no_flush(struct kbase_device *kbdev, struct kbase_mm /* Small wrapper function to factor out GPU-dependent context releasing */ static void release_ctx(struct kbase_device *kbdev, struct kbase_context *kctx) { -#if MALI_USE_CSF CSTD_UNUSED(kbdev); kbase_ctx_sched_release_ctx_lock(kctx); -#else /* MALI_USE_CSF */ - kbasep_js_runpool_release_ctx(kbdev, kctx); -#endif /* MALI_USE_CSF */ } /** @@ -357,7 +350,6 @@ static bool mmu_flush_cache_on_gpu_ctrl(struct kbase_device *kbdev) * * Issue a cache flush physical range command. */ -#if MALI_USE_CSF static void mmu_flush_pa_range(struct kbase_device *kbdev, phys_addr_t phys, size_t nr_bytes, enum kbase_mmu_op_type op) { @@ -378,7 +370,6 @@ static void mmu_flush_pa_range(struct kbase_device *kbdev, phys_addr_t phys, siz if (kbase_gpu_cache_flush_pa_range_and_busy_wait(kbdev, phys, nr_bytes, flush_op)) dev_err(kbdev->dev, "Flush for physical address range did not complete"); } -#endif /** * mmu_invalidate() - Perform an invalidate operation on MMU caches. @@ -500,13 +491,7 @@ static void mmu_flush_invalidate(struct kbase_device *kbdev, struct kbase_contex if (!kctx) { mmu_flush_invalidate_as(kbdev, &kbdev->as[as_nr], op_param); } else { -#if !MALI_USE_CSF - mutex_lock(&kbdev->js_data.queue_mutex); - ctx_is_in_runpool = kbase_ctx_sched_inc_refcount(kctx); - mutex_unlock(&kbdev->js_data.queue_mutex); -#else ctx_is_in_runpool = kbase_ctx_sched_inc_refcount_if_as_valid(kctx); -#endif /* !MALI_USE_CSF */ if (ctx_is_in_runpool) { KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); @@ -682,6 +667,12 @@ static bool kbase_mmu_handle_isolated_pgd_page(struct kbase_device *kbdev, return page_is_isolated; } +static struct kbase_mem_pool *kbase_mmu_get_pgd_pool(struct kbase_device *kbdev, + struct kbase_mmu_table *mmut) +{ + return (mmut->kctx) ? &mmut->kctx->pgd_mem_pool : &kbdev->pgd_mem_pool; +} + /** * kbase_mmu_free_pgd() - Free memory of the page directory * @@ -718,7 +709,7 @@ static void kbase_mmu_free_pgd(struct kbase_device *kbdev, struct kbase_mmu_tabl page_is_isolated = kbase_mmu_handle_isolated_pgd_page(kbdev, mmut, p); if (likely(!page_is_isolated)) { - kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, true); + kbase_mem_pool_free(kbase_mmu_get_pgd_pool(kbdev, mmut), p, true); kbase_mmu_account_freed_pgd(kbdev, mmut); } } @@ -810,82 +801,12 @@ static size_t reg_grow_calc_extra_pages(struct kbase_device *kbdev, struct kbase */ remainder = minimum_extra % multiple; -#if !MALI_USE_CSF - if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) { - /* multiple is based from the top of the initial commit, which - * has been allocated in such a way that (start_pfn + - * initial_commit) is already aligned to multiple. Hence the - * pfn for the end of committed memory will also be aligned to - * multiple - */ - size_t initial_commit = reg->initial_commit; - - if (fault_rel_pfn < initial_commit) { - /* this case is just to catch in case it's been - * recommitted by userspace to be smaller than the - * initial commit - */ - minimum_extra = initial_commit - reg_current_size; - remainder = 0; - } else { - /* same as calculating - * (fault_rel_pfn - initial_commit + 1) - */ - size_t pages_after_initial = - minimum_extra + reg_current_size - initial_commit; - - remainder = pages_after_initial % multiple; - } - } -#endif /* !MALI_USE_CSF */ - if (remainder == 0) return minimum_extra; return minimum_extra + multiple - remainder; } -/** - * estimate_pool_space_required - Determine how much a pool should be grown by to support a future - * allocation - * @pool: The memory pool to check, including its linked pools - * @pages_required: Number of small pages require for the pool to support a future allocation - * - * The value returned is accounting for the size of @pool and the size of each memory pool linked to - * @pool. Hence, the caller should use @pool and (if not already satisfied) all its linked pools to - * allocate from. - * - * Note: this is only an estimate, because even during the calculation the memory pool(s) involved - * can be updated to be larger or smaller. Hence, the result is only a guide as to whether an - * allocation could succeed, or an estimate of the correct amount to grow the pool by. The caller - * should keep attempting an allocation and then re-growing with a new value queried form this - * function until the allocation succeeds. - * - * Return: an estimate of the amount of extra small pages in @pool that are required to satisfy an - * allocation, or 0 if @pool (including its linked pools) is likely to already satisfy the - * allocation. - */ -static size_t estimate_pool_space_required(struct kbase_mem_pool *pool, const size_t pages_required) -{ - size_t pages_still_required; - - for (pages_still_required = pages_required; pool != NULL && pages_still_required; - pool = pool->next_pool) { - size_t pool_size_small; - - kbase_mem_pool_lock(pool); - - pool_size_small = kbase_mem_pool_size(pool) << pool->order; - if (pool_size_small >= pages_still_required) - pages_still_required = 0; - else - pages_still_required -= pool_size_small; - - kbase_mem_pool_unlock(pool); - } - return pages_still_required; -} - /** * page_fault_try_alloc - Try to allocate memory from a context pool * @kctx: Context pointer @@ -898,11 +819,10 @@ static size_t estimate_pool_space_required(struct kbase_mem_pool *pool, const si * @fallback_to_small: Whether fallback to small pages or not * @prealloc_sas: Pointer to kbase_sub_alloc structures * - * This function will try to allocate as many pages as possible from the context pool, then if - * required will try to allocate the remaining pages from the device pool. + * This function will try to allocate as many pages as possible from the pool * - * This function will not allocate any new memory beyond that is already present in the context or - * device pools. This is because it is intended to be called whilst the thread has acquired the + * This function will not allocate any new memory beyond that is already present in the context. + * This is because it is intended to be called whilst the thread has acquired the * region list lock with kbase_gpu_vm_lock(), and a large enough memory allocation whilst that is * held could invoke the OoM killer and cause an effective deadlock with kbase_cpu_vm_close(). * @@ -915,152 +835,91 @@ static bool page_fault_try_alloc(struct kbase_context *kctx, struct kbase_va_reg size_t new_pages, size_t *pages_to_grow, bool *grow_2mb_pool, bool fallback_to_small, struct kbase_sub_alloc **prealloc_sas) { - size_t total_gpu_pages_alloced = 0; - size_t total_cpu_pages_alloced = 0; - struct kbase_mem_pool *pool, *root_pool; + size_t gpu_pages_alloced = 0; + size_t cpu_pages_alloced = 0; + struct kbase_mem_pool *pool; bool alloc_failed = false; - size_t pages_still_required; - size_t total_mempools_free_small = 0; + size_t pool_size_small; + size_t pages_to_alloc_small_per_alloc; + struct tagged_addr *gpu_pages; lockdep_assert_held(&kctx->reg_lock); lockdep_assert_held(&kctx->mem_partials_lock); - if (WARN_ON(region->gpu_alloc->group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) { - /* Do not try to grow the memory pool */ - *pages_to_grow = 0; + *pages_to_grow = 0; + + if (WARN_ON(region->gpu_alloc->group_id >= MEMORY_GROUP_MANAGER_NR_GROUPS)) return false; - } if (kbase_is_large_pages_enabled() && new_pages >= NUM_PAGES_IN_2MB_LARGE_PAGE && !fallback_to_small) { - root_pool = &kctx->mem_pools.large[region->gpu_alloc->group_id]; + pool = &kctx->mem_pools.large[region->gpu_alloc->group_id]; *grow_2mb_pool = true; } else { - root_pool = &kctx->mem_pools.small[region->gpu_alloc->group_id]; + pool = &kctx->mem_pools.small[region->gpu_alloc->group_id]; *grow_2mb_pool = false; } + pages_to_alloc_small_per_alloc = new_pages; if (region->gpu_alloc != region->cpu_alloc) - new_pages *= 2; + new_pages <<= 1; + kbase_mem_pool_lock(pool); /* Determine how many pages are in the pools before trying to allocate. * Don't attempt to allocate & free if the allocation can't succeed. */ - pages_still_required = estimate_pool_space_required(root_pool, new_pages); - - if (pages_still_required) { + pool_size_small = kbase_mem_pool_size(pool) << pool->order; + if (pool_size_small < new_pages) { /* Insufficient pages in pools. Don't try to allocate - just * request a grow. */ - *pages_to_grow = pages_still_required; - + *pages_to_grow = new_pages - pool_size_small; + kbase_mem_pool_unlock(pool); return false; } - /* Since we're not holding any of the mempool locks, the amount of memory in the pools may - * change between the above estimate and the actual allocation. - */ - pages_still_required = new_pages; - for (pool = root_pool; pool != NULL && pages_still_required; pool = pool->next_pool) { - size_t pool_size_small; - size_t pages_to_alloc_small; - size_t pages_to_alloc_small_per_alloc; + gpu_pages = kbase_alloc_phy_pages_helper_locked( + region->gpu_alloc, pool, pages_to_alloc_small_per_alloc, &prealloc_sas[0]); - kbase_mem_pool_lock(pool); + if (!gpu_pages) + alloc_failed = true; + else + gpu_pages_alloced = pages_to_alloc_small_per_alloc; - /* Allocate as much as possible from this pool*/ - pool_size_small = kbase_mem_pool_size(pool) << pool->order; - total_mempools_free_small += pool_size_small; - pages_to_alloc_small = MIN(pages_still_required, pool_size_small); - if (region->gpu_alloc == region->cpu_alloc) - pages_to_alloc_small_per_alloc = pages_to_alloc_small; + if (!alloc_failed && region->gpu_alloc != region->cpu_alloc) { + struct tagged_addr *cpu_pages = kbase_alloc_phy_pages_helper_locked( + region->cpu_alloc, pool, pages_to_alloc_small_per_alloc, &prealloc_sas[1]); + + if (!cpu_pages) + alloc_failed = true; else - pages_to_alloc_small_per_alloc = pages_to_alloc_small >> 1; - - if (pages_to_alloc_small) { - struct tagged_addr *gpu_pages = kbase_alloc_phy_pages_helper_locked( - region->gpu_alloc, pool, pages_to_alloc_small_per_alloc, - &prealloc_sas[0]); - - if (!gpu_pages) - alloc_failed = true; - else - total_gpu_pages_alloced += pages_to_alloc_small_per_alloc; - - if (!alloc_failed && region->gpu_alloc != region->cpu_alloc) { - struct tagged_addr *cpu_pages = kbase_alloc_phy_pages_helper_locked( - region->cpu_alloc, pool, pages_to_alloc_small_per_alloc, - &prealloc_sas[1]); - - if (!cpu_pages) - alloc_failed = true; - else - total_cpu_pages_alloced += pages_to_alloc_small_per_alloc; - } - } - - kbase_mem_pool_unlock(pool); - - if (alloc_failed) { - WARN_ON(!pages_still_required); - WARN_ON(pages_to_alloc_small >= pages_still_required); - WARN_ON(pages_to_alloc_small_per_alloc >= pages_still_required); - break; - } - - pages_still_required -= pages_to_alloc_small; + cpu_pages_alloced = pages_to_alloc_small_per_alloc; } - if (pages_still_required) { + kbase_mem_pool_unlock(pool); + + if (alloc_failed) { /* Allocation was unsuccessful. We have dropped the mem_pool lock after allocation, * so must in any case use kbase_free_phy_pages_helper() rather than * kbase_free_phy_pages_helper_locked() */ - if (total_gpu_pages_alloced > 0) - kbase_free_phy_pages_helper(region->gpu_alloc, total_gpu_pages_alloced); - if (region->gpu_alloc != region->cpu_alloc && total_cpu_pages_alloced > 0) - kbase_free_phy_pages_helper(region->cpu_alloc, total_cpu_pages_alloced); - - if (alloc_failed) { - /* Note that in allocating from the above memory pools, we always ensure - * never to request more than is available in each pool with the pool's - * lock held. Hence failing to allocate in such situations would be unusual - * and we should cancel the growth instead (as re-growing the memory pool - * might not fix the situation) - */ - dev_warn( - kctx->kbdev->dev, - "Page allocation failure of %zu pages: managed %zu pages, mempool (inc linked pools) had %zu pages available", - new_pages, total_gpu_pages_alloced + total_cpu_pages_alloced, - total_mempools_free_small); - *pages_to_grow = 0; - } else { - /* Tell the caller to try to grow the memory pool - * - * Freeing pages above may have spilled or returned them to the OS, so we - * have to take into account how many are still in the pool before giving a - * new estimate for growth required of the pool. We can just re-estimate a - * new value. - */ - pages_still_required = estimate_pool_space_required(root_pool, new_pages); - if (pages_still_required) { - *pages_to_grow = pages_still_required; - } else { - /* It's possible another thread could've grown the pool to be just - * big enough after we rolled back the allocation. Request at least - * one more page to ensure the caller doesn't fail the growth by - * conflating it with the alloc_failed case above - */ - *pages_to_grow = 1u; - } - } + if (gpu_pages_alloced > 0) + kbase_free_phy_pages_helper(region->gpu_alloc, gpu_pages_alloced); + if (region->gpu_alloc != region->cpu_alloc && cpu_pages_alloced > 0) + kbase_free_phy_pages_helper(region->cpu_alloc, cpu_pages_alloced); + /* Failing to allocate in such situation is unusual, + * because the pool was supposed to have enough memory pages, + * and we should cancel the growth as re-growing the memory pool + * might not fix the situation. + */ + dev_warn( + kctx->kbdev->dev, + "Page allocation failure of %zu pages: managed %zu pages, mempool had %zu pages available", + new_pages, gpu_pages_alloced + cpu_pages_alloced, pool_size_small); return false; } - /* Allocation was successful. No pages to grow, return success. */ - *pages_to_grow = 0; - return true; } @@ -1116,9 +975,6 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) KBASE_DEBUG_ASSERT(kctx->kbdev == kbdev); #if MALI_JIT_PRESSURE_LIMIT_BASE -#if !MALI_USE_CSF - mutex_lock(&kctx->jctx.lock); -#endif #endif /* check if we still have GPU */ @@ -1145,10 +1001,6 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_3: fallthrough; case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_4: -#if !MALI_USE_CSF - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSLATION_FAULT_IDENTITY: -#endif /* need to check against the region to handle this one */ break; @@ -1162,23 +1014,6 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) kbase_mmu_report_fault_and_kill(kctx, faulting_as, "Permission failure", fault); goto fault_done; -#if !MALI_USE_CSF - case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_0: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_1: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_2: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_TRANSTAB_BUS_FAULT_3: - kbase_mmu_report_fault_and_kill(kctx, faulting_as, "Translation table bus fault", - fault); - goto fault_done; -#endif - -#if !MALI_USE_CSF - case AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_0: - fallthrough; -#endif case AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_1: fallthrough; case AS_FAULTSTATUS_EXCEPTION_TYPE_ACCESS_FLAG_2: @@ -1188,19 +1023,8 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) dev_warn(kbdev->dev, "Access flag unexpectedly set"); goto fault_done; -#if MALI_USE_CSF case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN: fallthrough; -#else - case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN0: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN1: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN2: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_IN3: - fallthrough; -#endif case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT0: fallthrough; case AS_FAULTSTATUS_EXCEPTION_TYPE_ADDRESS_SIZE_FAULT_OUT1: @@ -1218,16 +1042,6 @@ void kbase_mmu_page_fault_worker(struct work_struct *data) case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_2: fallthrough; case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_FAULT_3: -#if !MALI_USE_CSF - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_0: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_1: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_2: - fallthrough; - case AS_FAULTSTATUS_EXCEPTION_TYPE_MEMORY_ATTRIBUTE_NONCACHEABLE_3: -#endif kbase_mmu_report_fault_and_kill(kctx, faulting_as, "Memory attributes fault", fault); goto fault_done; @@ -1557,9 +1371,6 @@ fault_done: kbase_jit_done_phys_increase(kctx, pages_trimmed); kbase_gpu_vm_unlock(kctx); } -#if !MALI_USE_CSF - mutex_unlock(&kctx->jctx.lock); -#endif #endif for (i = 0; i != ARRAY_SIZE(prealloc_sas); ++i) @@ -1592,6 +1403,7 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, struct kbase_ u64 *page; struct page *p; phys_addr_t pgd; + struct kbase_mem_pool *pgd_mem_pool = kbase_mmu_get_pgd_pool(kbdev, mmut); lockdep_assert_held(&mmut->mmu_lock); @@ -1601,7 +1413,7 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, struct kbase_ return pgd; #endif - p = kbase_mem_pool_alloc(&kbdev->mem_pools.small[mmut->group_id]); + p = kbase_mem_pool_alloc(pgd_mem_pool); if (!p) return KBASE_INVALID_PHYSICAL_ADDRESS; @@ -1648,7 +1460,7 @@ static phys_addr_t kbase_mmu_alloc_pgd(struct kbase_device *kbdev, struct kbase_ return pgd; alloc_free: - kbase_mem_pool_free(&kbdev->mem_pools.small[mmut->group_id], p, false); + kbase_mem_pool_free(pgd_mem_pool, p, false); return KBASE_INVALID_PHYSICAL_ADDRESS; } @@ -1940,11 +1752,7 @@ static void mmu_flush_invalidate_insert_pages(struct kbase_device *kbdev, op_param.kctx_id = mmut->kctx ? mmut->kctx->id : 0xFFFFFFFF; op_param.flush_skip_levels = pgd_level_to_skip_flush(dirty_pgds); -#if MALI_USE_CSF as_nr = mmut->kctx ? mmut->kctx->as_nr : MCU_AS_NR; -#else - WARN_ON(!mmut->kctx); -#endif /* MMU cache flush strategy depends on whether GPU control commands for * flushing physical address ranges are supported. The new physical pages @@ -2150,6 +1958,7 @@ static int mmu_insert_alloc_pgds(struct kbase_device *kbdev, struct kbase_mmu_ta { int err = 0; int i; + struct kbase_mem_pool *pgd_mem_pool = kbase_mmu_get_pgd_pool(kbdev, mmut); lockdep_assert_held(&mmut->mmu_lock); @@ -2162,8 +1971,7 @@ static int mmu_insert_alloc_pgds(struct kbase_device *kbdev, struct kbase_mmu_ta if (new_pgds[i] != KBASE_INVALID_PHYSICAL_ADDRESS) break; mutex_unlock(&mmut->mmu_lock); - err = kbase_mem_pool_grow(&kbdev->mem_pools.small[mmut->group_id], - (size_t)level_high, NULL); + err = kbase_mem_pool_grow(pgd_mem_pool, (size_t)level_high, NULL); mutex_lock(&mmut->mmu_lock); if (err) { dev_err(kbdev->dev, "%s: kbase_mem_pool_grow() returned error %d", @@ -2410,6 +2218,10 @@ static void kbase_mmu_progress_migration_on_insert(struct tagged_addr phys, if (!kbase_is_page_migration_enabled()) return; + /* Metadata not created */ + if (!page_md) + return; + spin_lock(&page_md->migrate_lock); /* If no GPU va region is given: the metadata provided are @@ -2490,10 +2302,15 @@ u64 kbase_mmu_create_ate(struct kbase_device *const kbdev, struct tagged_addr co { u64 entry; unsigned int pte_flags = 0; + const bool cpu_access = flags & (KBASE_REG_CPU_RD | KBASE_REG_CPU_WR); kbdev->mmu_mode->entry_set_ate(&entry, phy, flags, level); - if ((flags & KBASE_REG_GPU_CACHED) && !(flags & KBASE_REG_CPU_CACHED)) + /* Address-Table Entries (ATEs) that are GPU-cached but CPU uncached are flagged as a + * Mismatched Memory Attribute (MMA) violation, as per A5.3.2 of the AMBA protocol + * specification. Depending on the system, these might need special handling: + */ + if ((flags & KBASE_REG_GPU_CACHED) && cpu_access && !(flags & KBASE_REG_CPU_CACHED)) pte_flags |= BIT(MMA_VIOLATION); return kbdev->mgm_dev->ops.mgm_update_gpu_pte(kbdev->mgm_dev, (unsigned int)group_id, @@ -2844,9 +2661,6 @@ KBASE_EXPORT_TEST_API(kbase_mmu_update); void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr) { lockdep_assert_held(&kbdev->hwaccess_lock); -#if !MALI_USE_CSF - lockdep_assert_held(&kbdev->mmu_hw_mutex); -#endif kbdev->mmu_mode->disable_as(kbdev, as_nr); } @@ -2881,7 +2695,6 @@ void kbase_mmu_disable(struct kbase_context *kctx) op_param.kctx_id = kctx->id; op_param.mmu_sync_info = mmu_sync_info; -#if MALI_USE_CSF /* 0xF value used to prevent skipping of any levels when flushing */ if (mmu_flush_cache_on_gpu_ctrl(kbdev)) op_param.flush_skip_levels = pgd_level_to_skip_flush(0xF); @@ -2916,36 +2729,6 @@ void kbase_mmu_disable(struct kbase_context *kctx) dev_err(kbdev->dev, "Failed to unlock AS %d for ctx %d_%d", kctx->as_nr, kctx->tgid, kctx->id); } -#else - lockdep_assert_held(&kctx->kbdev->mmu_hw_mutex); - - CSTD_UNUSED(lock_err); - - /* - * The address space is being disabled, drain all knowledge of it out - * from the caches as pages and page tables might be freed after this. - * - * The job scheduler code will already be holding the locks and context - * so just do the flush. - */ - flush_err = kbase_mmu_hw_do_flush(kbdev, &kbdev->as[kctx->as_nr], &op_param); - if (flush_err) { - dev_err(kbdev->dev, - "Flush for GPU page table update did not complete to disable AS %d for ctx %d_%d", - kctx->as_nr, kctx->tgid, kctx->id); - /* GPU reset would have been triggered by the flush function */ - } - - kbdev->mmu_mode->disable_as(kbdev, kctx->as_nr); - - /* - * JM GPUs has some L1 read only caches that need to be invalidated - * with START_FLUSH configuration. Purge the MMU disabled kctx from - * the slot_rb tracking field so such invalidation is performed when - * a new katom is executed on the affected slots. - */ - kbase_backend_slot_kctx_purge_locked(kbdev, kctx); -#endif } KBASE_EXPORT_TEST_API(kbase_mmu_disable); @@ -3049,9 +2832,7 @@ static void mmu_flush_invalidate_teardown_pages(struct kbase_device *kbdev, } else if (op_param->op == KBASE_MMU_OP_FLUSH_MEM) { /* Full cache flush through the GPU_CONTROL */ mmu_flush_invalidate_on_gpu_ctrl(kbdev, kctx, as_nr, op_param); - } -#if MALI_USE_CSF - else { + } else { /* Partial GPU cache flush of the pages that were unmapped */ unsigned long irq_flags; unsigned int i; @@ -3067,10 +2848,6 @@ static void mmu_flush_invalidate_teardown_pages(struct kbase_device *kbdev, spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); } } -#else - CSTD_UNUSED(phys); - CSTD_UNUSED(phys_page_nr); -#endif } static int kbase_mmu_teardown_pgd_pages(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, @@ -3506,13 +3283,6 @@ static int kbase_mmu_update_pages_common(struct kbase_device *kbdev, struct kbas const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; int as_nr; -#if !MALI_USE_CSF - if (unlikely(kctx == NULL)) - return -EINVAL; - - as_nr = kctx->as_nr; - mmut = &kctx->mmu; -#else if (kctx) { mmut = &kctx->mmu; as_nr = kctx->as_nr; @@ -3520,7 +3290,6 @@ static int kbase_mmu_update_pages_common(struct kbase_device *kbdev, struct kbas mmut = &kbdev->csf.mcu_mmu; as_nr = MCU_AS_NR; } -#endif err = kbase_mmu_update_pages_no_flush(kbdev, mmut, vpfn, phys, nr, flags, group_id, &dirty_pgds); @@ -3551,13 +3320,11 @@ int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, struct tagged_a return kbase_mmu_update_pages_common(kctx->kbdev, kctx, vpfn, phys, nr, flags, group_id); } -#if MALI_USE_CSF int kbase_mmu_update_csf_mcu_pages(struct kbase_device *kbdev, u64 vpfn, struct tagged_addr *phys, size_t nr, unsigned long flags, int const group_id) { return kbase_mmu_update_pages_common(kbdev, NULL, vpfn, phys, nr, flags, group_id); } -#endif /* MALI_USE_CSF */ static void mmu_page_migration_transaction_begin(struct kbase_device *kbdev) { @@ -3753,13 +3520,11 @@ static int mmu_migrate_pgd_sub_page(phys_addr_t old_pgd_phys, phys_addr_t new_pg ret = kbase_mmu_hw_do_lock(kbdev, as, &op_param); if (!ret) { -#if MALI_USE_CSF if (mmu_flush_cache_on_gpu_ctrl(kbdev)) ret = kbase_gpu_cache_flush_pa_range_and_busy_wait( kbdev, old_pgd_phys, GPU_PAGE_SIZE, GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC); else -#endif ret = kbase_gpu_cache_flush_and_busy_wait( kbdev, GPU_COMMAND_CACHE_CLN_INV_L2_LSC); } @@ -4159,13 +3924,11 @@ int kbase_mmu_migrate_data_page(struct tagged_addr old_phys, struct tagged_addr ret = kbase_mmu_hw_do_lock(kbdev, as, &op_param); if (!ret) { -#if MALI_USE_CSF if (mmu_flush_cache_on_gpu_ctrl(kbdev)) ret = kbase_gpu_cache_flush_pa_range_and_busy_wait( kbdev, as_phys_addr_t(old_phys), PAGE_SIZE, GPU_COMMAND_FLUSH_PA_RANGE_CLN_INV_L2_LSC); else -#endif ret = kbase_gpu_cache_flush_and_busy_wait( kbdev, GPU_COMMAND_CACHE_CLN_INV_L2_LSC); } @@ -4411,9 +4174,10 @@ int kbase_mmu_init(struct kbase_device *const kbdev, struct kbase_mmu_table *con */ while (mmut->pgd == KBASE_INVALID_PHYSICAL_ADDRESS) { int err; + struct kbase_mem_pool *pgd_mem_pool = kbase_mmu_get_pgd_pool(kbdev, mmut); - err = kbase_mem_pool_grow(&kbdev->mem_pools.small[mmut->group_id], - MIDGARD_MMU_BOTTOMLEVEL, kctx ? kctx->task : NULL); + err = kbase_mem_pool_grow(pgd_mem_pool, MIDGARD_MMU_BOTTOMLEVEL, + kctx ? kctx->task : NULL); if (err) { kbase_mmu_term(kbdev, mmut); return -ENOMEM; @@ -4454,7 +4218,6 @@ void kbase_mmu_as_term(struct kbase_device *kbdev, unsigned int i) void kbase_mmu_flush_pa_range(struct kbase_device *kbdev, struct kbase_context *kctx, phys_addr_t phys, size_t size, enum kbase_mmu_op_type flush_op) { -#if MALI_USE_CSF unsigned long irq_flags; spin_lock_irqsave(&kbdev->hwaccess_lock, irq_flags); @@ -4462,13 +4225,6 @@ void kbase_mmu_flush_pa_range(struct kbase_device *kbdev, struct kbase_context * kbdev->pm.backend.gpu_ready && (!kctx || kctx->as_nr >= 0)) mmu_flush_pa_range(kbdev, phys, size, KBASE_MMU_OP_FLUSH_PT); spin_unlock_irqrestore(&kbdev->hwaccess_lock, irq_flags); -#else - CSTD_UNUSED(kbdev); - CSTD_UNUSED(kctx); - CSTD_UNUSED(phys); - CSTD_UNUSED(size); - CSTD_UNUSED(flush_op); -#endif } #ifdef CONFIG_MALI_VECTOR_DUMP @@ -4656,22 +4412,11 @@ void kbase_mmu_bus_fault_worker(struct work_struct *data) return; } -#if MALI_USE_CSF /* Before the GPU power off, wait is done for the completion of * in-flight MMU fault work items. So GPU is expected to remain * powered up whilst the bus fault handling is being done. */ kbase_gpu_report_bus_fault_and_kill(kctx, faulting_as, fault); -#else - /* NOTE: If GPU already powered off for suspend, - * we don't need to switch to unmapped - */ - if (!kbase_pm_context_active_handle_suspend(kbdev, - KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE)) { - kbase_gpu_report_bus_fault_and_kill(kctx, faulting_as, fault); - kbase_pm_context_idle(kbdev); - } -#endif release_ctx(kbdev, kctx); diff --git a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.h b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.h index f0a418002247..c952346efa21 100644 --- a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.h +++ b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu.h @@ -215,7 +215,6 @@ int kbase_mmu_teardown_imported_pages(struct kbase_device *kbdev, struct kbase_m int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, struct tagged_addr *phys, size_t nr, unsigned long flags, int const group_id); -#if MALI_USE_CSF /** * kbase_mmu_update_csf_mcu_pages - Update MCU mappings with changes of phys and flags * @@ -233,7 +232,6 @@ int kbase_mmu_update_pages(struct kbase_context *kctx, u64 vpfn, struct tagged_a */ int kbase_mmu_update_csf_mcu_pages(struct kbase_device *kbdev, u64 vpfn, struct tagged_addr *phys, size_t nr, unsigned long flags, int const group_id); -#endif /** * kbase_mmu_migrate_data_page - Migrate GPU mappings and content of data pages between memory pages diff --git a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_faults_decoder.c b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_faults_decoder.c index 548d88cf216e..16057a29bb14 100644 --- a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_faults_decoder.c +++ b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_faults_decoder.c @@ -25,11 +25,7 @@ #include #include -#if MALI_USE_CSF #include -#else -#include -#endif #include #include @@ -76,7 +72,6 @@ const char *fault_source_id_internal_requester_get_str(struct kbase_device *kbde } else return "Load/store cache"; } else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "tiler")) { -#if MALI_USE_CSF if (utlb_id == 0) { if (access_type == AS_FAULTSTATUS_ACCESS_TYPE_READ) return decode_fault_source_tiler_r_t( @@ -86,25 +81,14 @@ const char *fault_source_id_internal_requester_get_str(struct kbase_device *kbde ir, kbdev->gpu_props.gpu_id.arch_id); } else return "The polygon list writer. No further details."; -#else - return (utlb_id == 0) ? "Anything other than the polygon list writer" : - "The polygon list writer"; -#endif - } -#if MALI_USE_CSF - else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "csf")) { + } else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "csf")) { if (access_type == AS_FAULTSTATUS_ACCESS_TYPE_READ) return decode_fault_source_csf_r_t(ir, kbdev->gpu_props.gpu_id.arch_id); else return decode_fault_source_csf_w_t(ir, kbdev->gpu_props.gpu_id.arch_id); - } -#else - else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "jm")) - return decode_fault_source_jm_t(ir, kbdev->gpu_props.gpu_id.arch_id); -#endif - else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "I2c") || - !strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "memsys") || - !strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "mmu")) { + } else if (!strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "I2c") || + !strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "memsys") || + !strcmp(source_id_enc_core_type_get_str(kbdev, source_id), "mmu")) { return "Not used"; } diff --git a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_hw_direct.c b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_hw_direct.c index e531444ccb24..6051550b1ef7 100644 --- a/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_hw_direct.c +++ b/drivers/gpu/arm/valhall/mmu/mali_kbase_mmu_hw_direct.c @@ -29,7 +29,6 @@ #include #include -#if MALI_USE_CSF /** * mmu_has_flush_skip_pgd_levels() - Check if the GPU has the feature * AS_LOCKADDR_FLUSH_SKIP_LEVELS @@ -45,7 +44,6 @@ static bool mmu_has_flush_skip_pgd_levels(struct kbase_gpu_props const *gpu_prop { return gpu_props->gpu_id.arch_id >= GPU_ID_ARCH_MAKE(12, 0, 4); } -#endif /** * lock_region() - Generate lockaddr to lock memory region in MMU @@ -145,11 +143,9 @@ static int lock_region(struct kbase_gpu_props const *gpu_props, u64 *lockaddr, *lockaddr = lockaddr_base & ~((1ull << lockaddr_size_log2) - 1); *lockaddr |= lockaddr_size_log2 - 1; -#if MALI_USE_CSF if (mmu_has_flush_skip_pgd_levels(gpu_props)) *lockaddr = AS_LOCKADDR_FLUSH_SKIP_LEVELS_SET(*lockaddr, op_param->flush_skip_levels); -#endif return 0; } @@ -210,7 +206,6 @@ static int write_cmd(struct kbase_device *kbdev, unsigned int as_nr, u32 cmd) return status; } -#if MALI_USE_CSF static int wait_l2_power_trans_complete(struct kbase_device *kbdev) { u32 val; @@ -316,7 +311,6 @@ static int apply_hw_issue_GPU2019_3901_wa(struct kbase_device *kbdev, u32 *mmu_c return ret; } #endif /* !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) */ -#endif /* MALI_USE_CSF */ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as) { @@ -324,9 +318,6 @@ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as) u64 transcfg = 0; lockdep_assert_held(&kbdev->hwaccess_lock); -#if !MALI_USE_CSF - lockdep_assert_held(&kbdev->mmu_hw_mutex); -#endif transcfg = current_setup->transcfg; @@ -343,18 +334,19 @@ void kbase_mmu_hw_configure(struct kbase_device *kbdev, struct kbase_as *as) transcfg = AS_TRANSCFG_PTW_SH_SET(transcfg, AS_TRANSCFG_PTW_SH_OUTER_SHAREABLE); } + kbase_reg_write64(kbdev, MMU_AS_OFFSET(as->number, TRANSCFG), transcfg); kbase_reg_write64(kbdev, MMU_AS_OFFSET(as->number, TRANSTAB), current_setup->transtab); kbase_reg_write64(kbdev, MMU_AS_OFFSET(as->number, MEMATTR), current_setup->memattr); KBASE_TLSTREAM_TL_ATTRIB_AS_CONFIG(kbdev, as, current_setup->transtab, current_setup->memattr, transcfg); + KBASE_TLSTREAM_JD_AS_INFO(kbdev, as->number, current_setup->transtab, + current_setup->memattr, transcfg); write_cmd(kbdev, as->number, AS_COMMAND_COMMAND_UPDATE); -#if MALI_USE_CSF /* Wait for UPDATE command to complete */ wait_ready(kbdev, as->number); -#endif } /** @@ -465,6 +457,7 @@ int kbase_mmu_hw_do_unlock_no_addr(struct kbase_device *kbdev, struct kbase_as * if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) return -EINVAL; + ret = write_cmd(kbdev, as->number, AS_COMMAND_COMMAND_UNLOCK); /* Wait for UNLOCK command to complete */ @@ -491,6 +484,7 @@ int kbase_mmu_hw_do_unlock(struct kbase_device *kbdev, struct kbase_as *as, if (WARN_ON(kbdev == NULL) || WARN_ON(as == NULL)) return -EINVAL; + ret = mmu_hw_set_lock_addr(kbdev, as->number, &lock_addr, op_param); if (!ret) @@ -528,7 +522,7 @@ int kbase_mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, if (ret) return ret; -#if MALI_USE_CSF && !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) +#if !IS_ENABLED(CONFIG_MALI_VALHALL_NO_MALI) /* WA for the KBASE_HW_ISSUE_GPU2019_3901. */ if (kbase_hw_has_issue(kbdev, KBASE_HW_ISSUE_GPU2019_3901) && mmu_cmd == AS_COMMAND_COMMAND_FLUSH_MEM) { @@ -553,12 +547,10 @@ int kbase_mmu_hw_do_flush(struct kbase_device *kbdev, struct kbase_as *as, if (likely(!ret)) { mmu_command_instr(kbdev, op_param->kctx_id, mmu_cmd, lock_addr, op_param->mmu_sync_info); -#if MALI_USE_CSF if (flush_op == KBASE_MMU_OP_FLUSH_MEM && kbdev->pm.backend.apply_hw_issue_TITANHW_2938_wa && kbdev->pm.backend.l2_state == KBASE_L2_PEND_OFF) ret = wait_l2_power_trans_complete(kbdev); -#endif } return ret; @@ -587,6 +579,7 @@ int kbase_mmu_hw_do_flush_on_gpu_ctrl(struct kbase_device *kbdev, struct kbase_a if (flush_op == KBASE_MMU_OP_FLUSH_PT) gpu_cmd = GPU_COMMAND_CACHE_CLN_INV_L2; + /* 1. Issue MMU_AS_CONTROL.COMMAND.LOCK operation. */ ret = mmu_hw_do_lock(kbdev, as, op_param); if (ret) @@ -598,14 +591,12 @@ int kbase_mmu_hw_do_flush_on_gpu_ctrl(struct kbase_device *kbdev, struct kbase_a /* 3. Issue MMU_AS_CONTROL.COMMAND.UNLOCK operation. */ ret2 = kbase_mmu_hw_do_unlock_no_addr(kbdev, as, op_param); -#if MALI_USE_CSF if (!ret && !ret2) { if (flush_op == KBASE_MMU_OP_FLUSH_MEM && kbdev->pm.backend.apply_hw_issue_TITANHW_2938_wa && kbdev->pm.backend.l2_state == KBASE_L2_PEND_OFF) ret = wait_l2_power_trans_complete(kbdev); } -#endif return ret ?: ret2; } @@ -629,20 +620,14 @@ void kbase_mmu_hw_clear_fault(struct kbase_device *kbdev, struct kbase_as *as, /* Clear the page (and bus fault IRQ as well in case one occurred) */ pf_bf_mask = MMU_PAGE_FAULT(as->number); -#if !MALI_USE_CSF - if (type == KBASE_MMU_FAULT_TYPE_BUS || type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED) - pf_bf_mask |= MMU_BUS_ERROR(as->number); -#endif kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_CLEAR), pf_bf_mask); -#if MALI_USE_CSF /* For valid page faults, this function is called just before unblocking the MMU (which * would in turn unblock the MCU firmware) and so this is an opportune location to * update the page fault counter value in firmware visible memory. */ if (likely(type == KBASE_MMU_FAULT_TYPE_PAGE) && kbdev->csf.page_fault_cnt_ptr) *kbdev->csf.page_fault_cnt_ptr = ++kbdev->csf.page_fault_cnt; -#endif unlock: spin_unlock_irqrestore(&kbdev->mmu_mask_change, flags); @@ -670,10 +655,6 @@ void kbase_mmu_hw_enable_fault(struct kbase_device *kbdev, struct kbase_as *as, irq_mask = kbase_reg_read32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK)) | MMU_PAGE_FAULT(as->number); -#if !MALI_USE_CSF - if (type == KBASE_MMU_FAULT_TYPE_BUS || type == KBASE_MMU_FAULT_TYPE_BUS_UNEXPECTED) - irq_mask |= MMU_BUS_ERROR(as->number); -#endif kbase_reg_write32(kbdev, MMU_CONTROL_ENUM(IRQ_MASK), irq_mask); unlock: diff --git a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_clk_rate_trace.c b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_clk_rate_trace.c index f0995a4cb22e..b3a9331b1c75 100644 --- a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_clk_rate_trace.c +++ b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_clk_rate_trace.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -24,19 +24,15 @@ #include #include "mali_kbase_config_platform.h" -#if MALI_USE_CSF #include -#endif static void *enumerate_gpu_clk(struct kbase_device *kbdev, unsigned int index) { if (index >= kbdev->nr_clocks) return NULL; -#if MALI_USE_CSF if (of_machine_is_compatible("arm,juno")) WARN_ON(kbdev->nr_clocks != 1); -#endif return kbdev->clocks[index]; } @@ -44,7 +40,6 @@ static void *enumerate_gpu_clk(struct kbase_device *kbdev, unsigned int index) static unsigned long get_gpu_clk_rate(struct kbase_device *kbdev, void *gpu_clk_handle) { CSTD_UNUSED(kbdev); -#if MALI_USE_CSF /* On Juno fpga platforms, the GPU clock rate is reported as 600 MHZ at * the boot time. Then after the first call to kbase_devfreq_target() * the clock rate is reported as 450 MHZ and the frequency does not @@ -60,7 +55,6 @@ static unsigned long get_gpu_clk_rate(struct kbase_device *kbdev, void *gpu_clk_ */ if (of_machine_is_compatible("arm,juno")) return arch_timer_get_cntfrq(); -#endif return clk_get_rate((struct clk *)gpu_clk_handle); } @@ -79,11 +73,9 @@ static int gpu_clk_notifier_register(struct kbase_device *kbdev, void *gpu_clk_h sizeof(((struct kbase_gpu_clk_notifier_data *)0)->gpu_clk_handle), "mismatch in the size of clk member"); -#if MALI_USE_CSF /* Frequency is fixed on Juno platforms */ if (of_machine_is_compatible("arm,juno")) return 0; -#endif return clk_notifier_register((struct clk *)gpu_clk_handle, nb); } @@ -93,10 +85,8 @@ static void gpu_clk_notifier_unregister(struct kbase_device *kbdev, void *gpu_cl { CSTD_UNUSED(kbdev); -#if MALI_USE_CSF if (of_machine_is_compatible("arm,juno")) return; -#endif clk_notifier_unregister((struct clk *)gpu_clk_handle, nb); } diff --git a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_config_devicetree.c b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_config_devicetree.c index 7c07f4f96f56..02bcc94d9d61 100644 --- a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_config_devicetree.c +++ b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_config_devicetree.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -42,12 +42,7 @@ void kbase_platform_unregister(void) #endif #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation) -#else -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]) -#endif { return 1; } diff --git a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_runtime_pm.c b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_runtime_pm.c index b580bfee0078..ef060fabdbaf 100644 --- a/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_runtime_pm.c +++ b/drivers/gpu/arm/valhall/platform/devicetree/mali_kbase_runtime_pm.c @@ -60,7 +60,15 @@ static void disable_gpu_power_control(struct kbase_device *kbdev) ; else if (__clk_is_enabled(kbdev->clocks[i])) { clk_disable_unprepare(kbdev->clocks[i]); - WARN_ON(__clk_is_enabled(kbdev->clocks[i])); + if (__clk_is_enabled(kbdev->clocks[i])) + /* + * Clock won't be disabled when: + * 1. the clock_count for clock[i] is not reaching 0. + * 2. the clocks[i] is fixed-clock. + * Printing logs just for debugging purpose. + */ + dev_dbg(kbdev->dev, "%s Clock %d (%s) is not disabled.\n", __func__, + i, __clk_get_name(kbdev->clocks[i])); } } @@ -77,15 +85,12 @@ static void disable_gpu_power_control(struct kbase_device *kbdev) static int pm_callback_power_on(struct kbase_device *kbdev) { - int ret = 1; /* Assume GPU has been powered off */ - int error; unsigned long flags; dev_dbg(kbdev->dev, "%s %pK\n", __func__, (void *)kbdev->dev->pm_domain); spin_lock_irqsave(&kbdev->hwaccess_lock, flags); WARN_ON(kbase_io_is_gpu_powered(kbdev)); -#if MALI_USE_CSF if (likely(kbdev->csf.firmware_inited)) { WARN_ON(!kbdev->pm.active_count); WARN_ON(kbdev->pm.runtime_active); @@ -93,27 +98,8 @@ static int pm_callback_power_on(struct kbase_device *kbdev) spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); enable_gpu_power_control(kbdev); - CSTD_UNUSED(error); -#else - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); -#ifdef KBASE_PM_RUNTIME - error = pm_runtime_get_sync(kbdev->dev); - if (error == 1) { - /* - * Let core know that the chip has not been - * powered off, so we can save on re-initialization. - */ - ret = 0; - } - dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error); -#else - enable_gpu_power_control(kbdev); -#endif /* KBASE_PM_RUNTIME */ - -#endif /* MALI_USE_CSF */ - - return ret; + return 1; } static void pm_callback_power_off(struct kbase_device *kbdev) @@ -124,37 +110,26 @@ static void pm_callback_power_off(struct kbase_device *kbdev) spin_lock_irqsave(&kbdev->hwaccess_lock, flags); WARN_ON(kbase_io_is_gpu_powered(kbdev)); -#if MALI_USE_CSF if (likely(kbdev->csf.firmware_inited)) { -#ifdef CONFIG_MALI_VALHALL_DEBUG - WARN_ON(kbase_csf_scheduler_get_nr_active_csgs(kbdev)); -#endif + if (IS_ENABLED(CONFIG_MALI_VALHALL_DEBUG)) + WARN_ON(kbase_csf_scheduler_get_nr_active_csgs(kbdev) && + !kbase_io_is_aw_removed(kbdev)); WARN_ON(kbdev->pm.backend.mcu_state != KBASE_MCU_OFF); } spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); /* Power down the GPU immediately */ disable_gpu_power_control(kbdev); -#else /* MALI_USE_CSF */ - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); - -#ifdef KBASE_PM_RUNTIME - pm_runtime_mark_last_busy(kbdev->dev); - pm_runtime_put_autosuspend(kbdev->dev); -#else - /* Power down the GPU immediately as runtime PM is disabled */ - disable_gpu_power_control(kbdev); -#endif -#endif /* MALI_USE_CSF */ } -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) static void pm_callback_runtime_gpu_active(struct kbase_device *kbdev) { unsigned long flags; int error; lockdep_assert_held(&kbdev->pm.lock); + if (!IS_ENABLED(CONFIG_PM)) + return; spin_lock_irqsave(&kbdev->hwaccess_lock, flags); WARN_ON(!kbase_io_is_gpu_powered(kbdev)); @@ -179,6 +154,8 @@ static void pm_callback_runtime_gpu_idle(struct kbase_device *kbdev) unsigned long flags; lockdep_assert_held(&kbdev->pm.lock); + if (!IS_ENABLED(CONFIG_PM)) + return; dev_dbg(kbdev->dev, "%s", __func__); @@ -193,14 +170,14 @@ static void pm_callback_runtime_gpu_idle(struct kbase_device *kbdev) pm_runtime_put_autosuspend(kbdev->dev); kbdev->pm.runtime_active = false; } -#endif -#ifdef KBASE_PM_RUNTIME static int kbase_device_runtime_init(struct kbase_device *kbdev) { int ret = 0; dev_dbg(kbdev->dev, "%s\n", __func__); + if (!IS_ENABLED(CONFIG_PM)) + return 0; pm_runtime_set_autosuspend_delay(kbdev->dev, AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(kbdev->dev); @@ -211,11 +188,14 @@ static int kbase_device_runtime_init(struct kbase_device *kbdev) if (!pm_runtime_enabled(kbdev->dev)) { dev_warn(kbdev->dev, "pm_runtime not enabled"); ret = -EINVAL; - } else if (atomic_read(&kbdev->dev->power.usage_count)) { + } +#if IS_ENABLED(CONFIG_PM) + else if (atomic_read(&kbdev->dev->power.usage_count)) { dev_warn(kbdev->dev, "%s: Device runtime usage count unexpectedly non zero %d", __func__, atomic_read(&kbdev->dev->power.usage_count)); ret = -EINVAL; } +#endif return ret; } @@ -223,32 +203,26 @@ static int kbase_device_runtime_init(struct kbase_device *kbdev) static void kbase_device_runtime_disable(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); - + if (!IS_ENABLED(CONFIG_PM)) + return; +#if IS_ENABLED(CONFIG_PM) if (atomic_read(&kbdev->dev->power.usage_count)) dev_warn(kbdev->dev, "%s: Device runtime usage count unexpectedly non zero %d", __func__, atomic_read(&kbdev->dev->power.usage_count)); - +#endif pm_runtime_disable(kbdev->dev); } -#endif /* KBASE_PM_RUNTIME */ static int pm_callback_runtime_on(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); -#if !MALI_USE_CSF - enable_gpu_power_control(kbdev); -#endif return 0; } static void pm_callback_runtime_off(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); - -#if !MALI_USE_CSF - disable_gpu_power_control(kbdev); -#endif } static void pm_callback_resume(struct kbase_device *kbdev) @@ -269,23 +243,10 @@ struct kbase_pm_callback_conf pm_callbacks = { .power_off_callback = pm_callback_power_off, .power_suspend_callback = pm_callback_suspend, .power_resume_callback = pm_callback_resume, -#ifdef KBASE_PM_RUNTIME .power_runtime_init_callback = kbase_device_runtime_init, .power_runtime_term_callback = kbase_device_runtime_disable, .power_runtime_on_callback = pm_callback_runtime_on, .power_runtime_off_callback = pm_callback_runtime_off, -#else /* KBASE_PM_RUNTIME */ - .power_runtime_init_callback = NULL, - .power_runtime_term_callback = NULL, - .power_runtime_on_callback = NULL, - .power_runtime_off_callback = NULL, -#endif /* KBASE_PM_RUNTIME */ - -#if MALI_USE_CSF && defined(KBASE_PM_RUNTIME) .power_runtime_gpu_idle_callback = pm_callback_runtime_gpu_idle, .power_runtime_gpu_active_callback = pm_callback_runtime_gpu_active, -#else - .power_runtime_gpu_idle_callback = NULL, - .power_runtime_gpu_active_callback = NULL, -#endif }; diff --git a/drivers/gpu/arm/valhall/platform/meson/mali_kbase_config_meson.c b/drivers/gpu/arm/valhall/platform/meson/mali_kbase_config_meson.c index 7c07f4f96f56..02bcc94d9d61 100644 --- a/drivers/gpu/arm/valhall/platform/meson/mali_kbase_config_meson.c +++ b/drivers/gpu/arm/valhall/platform/meson/mali_kbase_config_meson.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -42,12 +42,7 @@ void kbase_platform_unregister(void) #endif #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation) -#else -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]) -#endif { return 1; } diff --git a/drivers/gpu/arm/valhall/platform/meson/mali_kbase_runtime_pm.c b/drivers/gpu/arm/valhall/platform/meson/mali_kbase_runtime_pm.c index bd3b4b5e2aa3..e51e251c8380 100644 --- a/drivers/gpu/arm/valhall/platform/meson/mali_kbase_runtime_pm.c +++ b/drivers/gpu/arm/valhall/platform/meson/mali_kbase_runtime_pm.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -126,7 +126,15 @@ static void disable_gpu_power_control(struct kbase_device *kbdev) ; else if (__clk_is_enabled(kbdev->clocks[i])) { clk_disable_unprepare(kbdev->clocks[i]); - WARN_ON(__clk_is_enabled(kbdev->clocks[i])); + if (__clk_is_enabled(kbdev->clocks[i])) + /* + * Clock won't be disabled when: + * 1. the clock_count for clock[i] is not reaching 0. + * 2. the clocks[i] is fixed-clock. + * Printing logs just for debugging purpose. + */ + dev_dbg(kbdev->dev, "%s Clock %d (%s) is not disabled.\n", __func__, + i, __clk_get_name(kbdev->clocks[i])); } } @@ -147,19 +155,18 @@ static int pm_callback_power_on(struct kbase_device *kbdev) dev_dbg(kbdev->dev, "%s %pK\n", __func__, (void *)kbdev->dev->pm_domain); -#ifdef KBASE_PM_RUNTIME - error = pm_runtime_get_sync(kbdev->dev); - if (error == 1) { - /* - * Let core know that the chip has not been - * powered off, so we can save on re-initialization. - */ - ret = 0; - } - dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error); -#else - enable_gpu_power_control(kbdev); -#endif + if (IS_ENABLED(CONFIG_PM)) { + error = pm_runtime_get_sync(kbdev->dev); + if (error == 1) { + /* + * Let core know that the chip has not been + * powered off, so we can save on re-initialization. + */ + ret = 0; + } + dev_dbg(kbdev->dev, "pm_runtime_get_sync returned %d\n", error); + } else + enable_gpu_power_control(kbdev); return ret; } @@ -168,21 +175,22 @@ static void pm_callback_power_off(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); -#ifdef KBASE_PM_RUNTIME - pm_runtime_mark_last_busy(kbdev->dev); - pm_runtime_put_autosuspend(kbdev->dev); -#else - /* Power down the GPU immediately as runtime PM is disabled */ - disable_gpu_power_control(kbdev); -#endif + if (IS_ENABLED(CONFIG_PM)) { + pm_runtime_mark_last_busy(kbdev->dev); + pm_runtime_put_autosuspend(kbdev->dev); + } else { + /* Power down the GPU immediately as runtime PM is disabled */ + disable_gpu_power_control(kbdev); + } } -#ifdef KBASE_PM_RUNTIME static int kbase_device_runtime_init(struct kbase_device *kbdev) { int ret = 0; dev_dbg(kbdev->dev, "%s\n", __func__); + if (!IS_ENABLED(CONFIG_PM)) + return 0; pm_runtime_set_autosuspend_delay(kbdev->dev, AUTO_SUSPEND_DELAY); pm_runtime_use_autosuspend(kbdev->dev); @@ -193,11 +201,14 @@ static int kbase_device_runtime_init(struct kbase_device *kbdev) if (!pm_runtime_enabled(kbdev->dev)) { dev_warn(kbdev->dev, "pm_runtime not enabled"); ret = -EINVAL; - } else if (atomic_read(&kbdev->dev->power.usage_count)) { + } +#if IS_ENABLED(CONFIG_PM) + else if (atomic_read(&kbdev->dev->power.usage_count)) { dev_warn(kbdev->dev, "%s: Device runtime usage count unexpectedly non zero %d", __func__, atomic_read(&kbdev->dev->power.usage_count)); ret = -EINVAL; } +#endif /* allocate resources for reset */ if (!ret) @@ -209,28 +220,32 @@ static int kbase_device_runtime_init(struct kbase_device *kbdev) static void kbase_device_runtime_disable(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); + if (!IS_ENABLED(CONFIG_PM)) + return; +#if IS_ENABLED(CONFIG_PM) if (atomic_read(&kbdev->dev->power.usage_count)) dev_warn(kbdev->dev, "%s: Device runtime usage count unexpectedly non zero %d", __func__, atomic_read(&kbdev->dev->power.usage_count)); +#endif pm_runtime_disable(kbdev->dev); } -#endif /* KBASE_PM_RUNTIME */ static int pm_callback_runtime_on(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); + if (IS_ENABLED(CONFIG_PM)) + enable_gpu_power_control(kbdev); - enable_gpu_power_control(kbdev); return 0; } static void pm_callback_runtime_off(struct kbase_device *kbdev) { dev_dbg(kbdev->dev, "%s\n", __func__); - - disable_gpu_power_control(kbdev); + if (IS_ENABLED(CONFIG_PM)) + disable_gpu_power_control(kbdev); } static void pm_callback_resume(struct kbase_device *kbdev) @@ -251,15 +266,8 @@ struct kbase_pm_callback_conf pm_callbacks = { .power_suspend_callback = pm_callback_suspend, .power_resume_callback = pm_callback_resume, .soft_reset_callback = pm_callback_soft_reset, -#ifdef KBASE_PM_RUNTIME .power_runtime_init_callback = kbase_device_runtime_init, .power_runtime_term_callback = kbase_device_runtime_disable, .power_runtime_on_callback = pm_callback_runtime_on, .power_runtime_off_callback = pm_callback_runtime_off, -#else /* KBASE_PM_RUNTIME */ - .power_runtime_init_callback = NULL, - .power_runtime_term_callback = NULL, - .power_runtime_on_callback = NULL, - .power_runtime_off_callback = NULL, -#endif /* KBASE_PM_RUNTIME */ }; diff --git a/drivers/gpu/arm/valhall/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/valhall/platform/rk/mali_kbase_config_rk.c index f87a6f50503a..628be3a40c86 100755 --- a/drivers/gpu/arm/valhall/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/valhall/platform/rk/mali_kbase_config_rk.c @@ -18,9 +18,7 @@ #include #include -#if MALI_USE_CSF #include -#endif #include #include diff --git a/drivers/gpu/arm/valhall/platform/vexpress/mali_kbase_config_vexpress.c b/drivers/gpu/arm/valhall/platform/vexpress/mali_kbase_config_vexpress.c index c655aa62b526..e1bfe2f26f77 100644 --- a/drivers/gpu/arm/valhall/platform/vexpress/mali_kbase_config_vexpress.c +++ b/drivers/gpu/arm/valhall/platform/vexpress/mali_kbase_config_vexpress.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -63,12 +63,7 @@ struct kbase_platform_config *kbase_get_platform_config(void) } #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation) -#else -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]) -#endif { return 1; } diff --git a/drivers/gpu/arm/valhall/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c b/drivers/gpu/arm/valhall/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c index d8a566d9d3c0..45ddda005d11 100644 --- a/drivers/gpu/arm/valhall/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c +++ b/drivers/gpu/arm/valhall/platform/vexpress_1xv7_a57/mali_kbase_config_vexpress.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -62,12 +62,7 @@ struct kbase_platform_config *kbase_get_platform_config(void) } #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation) -#else -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]) -#endif { return 1; } diff --git a/drivers/gpu/arm/valhall/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c b/drivers/gpu/arm/valhall/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c index 63e990cdf6cf..3285277ccfb0 100644 --- a/drivers/gpu/arm/valhall/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c +++ b/drivers/gpu/arm/valhall/platform/vexpress_6xvirtex7_10mhz/mali_kbase_config_vexpress.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -62,12 +62,7 @@ struct kbase_platform_config *kbase_get_platform_config(void) } #ifdef CONFIG_MALI_VALHALL_DVFS -#if MALI_USE_CSF int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation) -#else -int kbase_platform_dvfs_event(struct kbase_device *kbdev, u32 utilisation, u32 util_gl_share, - u32 util_cl_share[2]) -#endif { return 1; } diff --git a/drivers/gpu/arm/valhall/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c b/drivers/gpu/arm/valhall/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c index 0598d4397e2a..1939e3f3de48 100644 --- a/drivers/gpu/arm/valhall/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c +++ b/drivers/gpu/arm/valhall/tests/mali_kutf_clk_rate_trace/kernel/mali_kutf_clk_rate_trace_test.c @@ -176,9 +176,6 @@ static void kutf_set_pm_ctx_active(struct kutf_context *context) kbase_pm_context_active(data->kbdev); kbase_pm_wait_for_desired_state(data->kbdev); -#if !MALI_USE_CSF - kbase_pm_request_gpu_cycle_counter(data->kbdev); -#endif } static void kutf_set_pm_ctx_idle(struct kutf_context *context) @@ -187,9 +184,6 @@ static void kutf_set_pm_ctx_idle(struct kutf_context *context) if (WARN_ON(data->pm_ctx_cnt > 0)) return; -#if !MALI_USE_CSF - kbase_pm_release_gpu_cycle_counter(data->kbdev); -#endif kbase_pm_context_idle(data->kbdev); } diff --git a/drivers/gpu/arm/valhall/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c b/drivers/gpu/arm/valhall/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c index 6a143bb01616..4f7d781c0589 100644 --- a/drivers/gpu/arm/valhall/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c +++ b/drivers/gpu/arm/valhall/tests/mali_kutf_irq_test/mali_kutf_irq_test_main.c @@ -85,7 +85,6 @@ static irqreturn_t kbase_gpu_irq_custom_handler(int irq, void *data) u64 tval; bool has_test_irq = val & test_irq; -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { status_reg_enum = HOST_POWER_ENUM(PWR_IRQ_STATUS); clear_reg_enum = HOST_POWER_ENUM(PWR_IRQ_CLEAR); @@ -93,7 +92,6 @@ static irqreturn_t kbase_gpu_irq_custom_handler(int irq, void *data) val = kbase_reg_read32(kbdev, status_reg_enum); has_test_irq = val & test_irq; } -#endif if (has_test_irq) { tval = ktime_get_real_ns(); @@ -201,12 +199,10 @@ static void mali_kutf_irq_latency(struct kutf_context *context) triggered = false; /* Trigger fake IRQ */ -#if MALI_USE_CSF if (kbdev->pm.backend.has_host_pwr_iface) { reg_enum = HOST_POWER_ENUM(PWR_IRQ_RAWSTAT); test_irq = PWR_IRQ_POWER_CHANGED_SINGLE; } -#endif kbase_reg_write32(kbdev, reg_enum, test_irq); if (wait_event_timeout(wait, triggered, IRQ_TIMEOUT) == 0) { diff --git a/drivers/gpu/arm/valhall/thirdparty/mali_kbase_mmap.c b/drivers/gpu/arm/valhall/thirdparty/mali_kbase_mmap.c index 162f82e5493a..8a71ed685de4 100644 --- a/drivers/gpu/arm/valhall/thirdparty/mali_kbase_mmap.c +++ b/drivers/gpu/arm/valhall/thirdparty/mali_kbase_mmap.c @@ -487,21 +487,6 @@ unsigned long kbase_context_get_unmapped_area(struct kbase_context *const kctx, align_mask = align_offset - 1; is_shader_code = true; } -#if !MALI_USE_CSF - } else if (reg->flags & KBASE_REG_TILER_ALIGN_TOP) { - unsigned long extension_bytes = - (unsigned long)(reg->extension << PAGE_SHIFT); - /* kbase_check_alloc_sizes() already satisfies - * these checks, but they're here to avoid - * maintenance hazards due to the assumptions - * involved - */ - WARN_ON(reg->extension > (ULONG_MAX >> PAGE_SHIFT)); - WARN_ON(reg->initial_commit > (ULONG_MAX >> PAGE_SHIFT)); - WARN_ON(!is_power_of_2(extension_bytes)); - align_mask = extension_bytes - 1; - align_offset = extension_bytes - (reg->initial_commit << PAGE_SHIFT); -#endif /* !MALI_USE_CSF */ } else if (reg->flags & KBASE_REG_GPU_VA_SAME_4GB_PAGE) { is_same_4gb_page = true; } diff --git a/drivers/gpu/arm/valhall/tl/Kbuild b/drivers/gpu/arm/valhall/tl/Kbuild index 35c3fabfc609..3dce47d3c0de 100644 --- a/drivers/gpu/arm/valhall/tl/Kbuild +++ b/drivers/gpu/arm/valhall/tl/Kbuild @@ -22,11 +22,6 @@ valhall_kbase-y += \ tl/mali_kbase_timeline.o \ tl/mali_kbase_timeline_io.o \ tl/mali_kbase_tlstream.o \ - tl/mali_kbase_tracepoints.o + tl/mali_kbase_tracepoints.o \ + tl/backend/mali_kbase_timeline_csf.o - -ifeq ($(CONFIG_MALI_VALHALL_CSF_SUPPORT),y) - valhall_kbase-y += tl/backend/mali_kbase_timeline_csf.o -else - valhall_kbase-y += tl/backend/mali_kbase_timeline_jm.o -endif diff --git a/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_csf.c b/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_csf.c index 8c65b62ae46d..60880d1cff13 100644 --- a/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_csf.c +++ b/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_csf.c @@ -33,12 +33,10 @@ void kbase_create_timeline_objects(struct kbase_device *kbdev) struct kbase_timeline *timeline = kbdev->timeline; struct kbase_tlstream *summary = &kbdev->timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]; u32 const num_sb_entries = kbdev->gpu_props.gpu_id.arch_major >= 11 ? 16 : 8; - u32 const supports_gpu_sleep = -#ifdef KBASE_PM_RUNTIME - test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, &kbdev->pm.backend.gpu_sleep_allowed); -#else - false; -#endif /* KBASE_PM_RUNTIME */ + u32 const supports_gpu_sleep = IS_ENABLED(CONFIG_PM) ? + test_bit(KBASE_GPU_SUPPORTS_GPU_SLEEP, + &kbdev->pm.backend.gpu_sleep_allowed) : + false; /* Summarize the Address Space objects. */ for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) diff --git a/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_jm.c b/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_jm.c deleted file mode 100644 index 3e9e6e864125..000000000000 --- a/drivers/gpu/arm/valhall/tl/backend/mali_kbase_timeline_jm.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note -/* - * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#include -#include -#include - -#include - -void kbase_create_timeline_objects(struct kbase_device *kbdev) -{ - unsigned int lpu_id; - int as_nr; - struct kbase_context *kctx; - struct kbase_timeline *timeline = kbdev->timeline; - struct kbase_tlstream *summary = &timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]; - - /* Summarize the LPU objects. */ - for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { - void *lpu = &kbdev->gpu_props.js_features[lpu_id]; - - __kbase_tlstream_tl_new_lpu(summary, lpu, lpu_id, 0); - } - - /* Summarize the Address Space objects. */ - for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) - __kbase_tlstream_tl_new_as(summary, &kbdev->as[as_nr], (u32)as_nr); - - /* Create GPU object and make it retain all LPUs and address spaces. */ - __kbase_tlstream_tl_new_gpu(summary, kbdev, kbdev->id, kbdev->gpu_props.num_cores); - - for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { - void *lpu = &kbdev->gpu_props.js_features[lpu_id]; - __kbase_tlstream_tl_lifelink_lpu_gpu(summary, lpu, kbdev); - } - - for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) - __kbase_tlstream_tl_lifelink_as_gpu(summary, &kbdev->as[as_nr], kbdev); - - /* Lock the context list, to ensure no changes to the list are made - * while we're summarizing the contexts and their contents. - */ - mutex_lock(&timeline->tl_kctx_list_lock); - - /* For each context in the device... */ - list_for_each_entry(kctx, &timeline->tl_kctx_list, tl_kctx_list_node) { - /* Summarize the context itself */ - __kbase_tlstream_tl_new_ctx(summary, kctx, kctx->id, (u32)(kctx->tgid)); - } - - /* Reset body stream buffers while holding the kctx lock. - * This ensures we can't fire both summary and normal tracepoints for - * the same objects. - * If we weren't holding the lock, it's possible that the summarized - * objects could have been created, destroyed, or used after we - * constructed the summary stream tracepoints, but before we reset - * the body stream, resulting in losing those object event tracepoints. - */ - kbase_timeline_streams_body_reset(timeline); - - mutex_unlock(&timeline->tl_kctx_list_lock); - - /* Static object are placed into summary packet that needs to be - * transmitted first. Flush all streams to make it available to - * user space. - */ - kbase_timeline_streams_flush(timeline); -} diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline.c b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline.c index 96f780945a4b..22de4c8a7e9a 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline.c +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline.c @@ -94,9 +94,8 @@ static void kbasep_timeline_autoflush_timer_callback(struct timer_list *timer) int kbase_timeline_init(struct kbase_timeline **timeline, atomic_t *timeline_flags) { struct kbase_timeline *result; -#if MALI_USE_CSF struct kbase_tlstream *csffw_stream; -#endif + int i; if (!timeline || !timeline_flags) return -EINVAL; @@ -109,6 +108,9 @@ int kbase_timeline_init(struct kbase_timeline **timeline, atomic_t *timeline_fla mutex_init(&result->streams_buf_lock); init_waitqueue_head(&result->event_queue); + for (i = 0; i < TL_STREAM_TYPE_COUNT; i++) + spin_lock_init(&result->streams[i].lock); + /* Initialize the kctx list */ mutex_init(&result->tl_kctx_list_lock); INIT_LIST_HEAD(&result->tl_kctx_list); @@ -118,10 +120,8 @@ int kbase_timeline_init(struct kbase_timeline **timeline, atomic_t *timeline_fla kbase_timer_setup(&result->autoflush_timer, kbasep_timeline_autoflush_timer_callback); result->timeline_flags = timeline_flags; -#if MALI_USE_CSF csffw_stream = &result->streams[TL_STREAM_TYPE_CSFFW]; kbase_csf_tl_reader_init(&result->csf_tl_reader, csffw_stream); -#endif *timeline = result; return 0; @@ -134,9 +134,7 @@ void kbase_timeline_term(struct kbase_timeline *timeline) if (!timeline) return; -#if MALI_USE_CSF kbase_csf_tl_reader_term(&timeline->csf_tl_reader); -#endif WARN_ON(!list_empty(&timeline->tl_kctx_list)); @@ -208,7 +206,6 @@ int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags) if (atomic_cmpxchg(timeline->timeline_flags, 0, (int)timeline_flags)) return -EBUSY; -#if MALI_USE_CSF if (flags & BASE_TLSTREAM_ENABLE_CSFFW_TRACEPOINTS) { err = kbase_csf_tl_reader_start(&timeline->csf_tl_reader, kbdev); if (err) { @@ -216,7 +213,6 @@ int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags) return err; } } -#endif /* Reset and initialize header streams. */ kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_OBJ_SUMMARY]); @@ -224,18 +220,6 @@ int kbase_timeline_acquire(struct kbase_device *kbdev, u32 flags) timeline->obj_header_btc = obj_desc_header_size; timeline->aux_header_btc = aux_desc_header_size; -#if !MALI_USE_CSF - /* If job dumping is enabled, readjust the software event's - * timeout as the default value of 3 seconds is often - * insufficient. - */ - if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { - dev_info(kbdev->dev, - "Job dumping is enabled, readjusting the software event's timeout\n"); - atomic_set(&kbdev->js_data.soft_job_timeout_ms, 1800000); - } -#endif /* !MALI_USE_CSF */ - /* Summary stream was cleared during acquire. * Create static timeline objects that will be * read by client. @@ -285,9 +269,7 @@ void kbase_timeline_release(struct kbase_timeline *timeline) if (time_to_sleep > 0) msleep_interruptible(time_to_sleep); -#if MALI_USE_CSF kbase_csf_tl_reader_stop(&timeline->csf_tl_reader); -#endif /* Stop autoflush timer before releasing access to streams. */ atomic_set(&timeline->autoflush_timer_active, 0); @@ -305,14 +287,12 @@ int kbase_timeline_streams_flush(struct kbase_timeline *timeline) if (WARN_ON(!timeline)) return -EINVAL; -#if MALI_USE_CSF { int ret = kbase_csf_tl_reader_flush_buffer(&timeline->csf_tl_reader); if (ret > 0) has_bytes = true; } -#endif for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) { nbytes = kbase_tlstream_flush_stream(&timeline->streams[stype]); @@ -326,9 +306,7 @@ void kbase_timeline_streams_body_reset(struct kbase_timeline *timeline) { kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_OBJ]); kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_AUX]); -#if MALI_USE_CSF kbase_tlstream_reset(&timeline->streams[TL_STREAM_TYPE_CSFFW]); -#endif } void kbase_timeline_pre_kbase_context_destroy(struct kbase_context *kctx) @@ -370,9 +348,7 @@ void kbase_timeline_post_kbase_context_create(struct kbase_context *kctx) * never in parallel with it. If fired in parallel, we could get * duplicate creation tracepoints. */ -#if MALI_USE_CSF KBASE_TLSTREAM_TL_KBASE_NEW_CTX(kbdev, kctx->id, kbdev->id); -#endif /* Trace with the AOM tracepoint even in CSF for dumping */ KBASE_TLSTREAM_TL_NEW_CTX(kbdev, kctx, kctx->id, 0); @@ -385,9 +361,7 @@ void kbase_timeline_post_kbase_context_destroy(struct kbase_context *kctx) /* Trace with the AOM tracepoint even in CSF for dumping */ KBASE_TLSTREAM_TL_DEL_CTX(kbdev, kctx); -#if MALI_USE_CSF KBASE_TLSTREAM_TL_KBASE_DEL_CTX(kbdev, kctx->id); -#endif /* Flush the timeline stream, so the user can see the termination * tracepoints being fired. diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_io.c b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_io.c index 522fd9e0964a..e3b4b0da17ce 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_io.c +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_io.c @@ -146,11 +146,8 @@ static int kbasep_timeline_io_packet_pending(struct kbase_timeline *timeline, */ static int kbasep_timeline_has_header_data(struct kbase_timeline *timeline) { - return timeline->obj_header_btc || timeline->aux_header_btc -#if MALI_USE_CSF - || timeline->csf_tl_reader.tl_header.btc -#endif - ; + return timeline->obj_header_btc || timeline->aux_header_btc || + timeline->csf_tl_reader.tl_header.btc; } /** @@ -217,12 +214,10 @@ static inline int kbasep_timeline_copy_headers(struct kbase_timeline *timeline, if (copy_stream_header(buffer, size, copy_len, aux_desc_header, aux_desc_header_size, &timeline->aux_header_btc)) return -1; -#if MALI_USE_CSF if (copy_stream_header(buffer, size, copy_len, timeline->csf_tl_reader.tl_header.data, timeline->csf_tl_reader.tl_header.size, &timeline->csf_tl_reader.tl_header.btc)) return -1; -#endif return 0; } diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_priv.h b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_priv.h index 59848ba7bf0f..ddcdc5816ca2 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_priv.h +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_timeline_priv.h @@ -25,10 +25,8 @@ #include #include "mali_kbase_tlstream.h" -#if MALI_USE_CSF #include "csf/mali_kbase_csf_tl_reader.h" #include "csf/mali_kbase_csf_trace_buffer.h" -#endif #include #include @@ -74,9 +72,7 @@ struct kbase_timeline { size_t obj_header_btc; size_t aux_header_btc; ktime_t last_acquire_time; -#if MALI_USE_CSF struct kbase_csf_tl_reader csf_tl_reader; -#endif }; void kbase_create_timeline_objects(struct kbase_device *kbdev); diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.c b/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.c index 117417c30183..1f504e253140 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.c +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2015-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2015-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -120,14 +120,12 @@ static const struct { TL_PACKET_TYPE_BODY, TL_STREAM_ID_KERNEL, }, -#if MALI_USE_CSF { TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_BODY, TL_STREAM_ID_CSFFW, }, -#endif }; void kbase_tlstream_init(struct kbase_tlstream *stream, enum tl_stream_type stream_type, @@ -138,8 +136,6 @@ void kbase_tlstream_init(struct kbase_tlstream *stream, enum tl_stream_type stre KBASE_DEBUG_ASSERT(stream); KBASE_DEBUG_ASSERT(stream_type < TL_STREAM_TYPE_COUNT); - spin_lock_init(&stream->lock); - /* All packets carrying tracepoints shall be numbered. */ if (tl_stream_cfg[stream_type].pkt_type == TL_PACKET_TYPE_BODY) stream->numbered = 1; @@ -219,6 +215,7 @@ char *kbase_tlstream_msgbuf_acquire(struct kbase_tlstream *stream, size_t msg_si size_t wb_size; KBASE_DEBUG_ASSERT(PACKET_SIZE - PACKET_HEADER_SIZE - PACKET_NUMBER_SIZE >= msg_size); + WARN_ON(!stream->buffer); spin_lock_irqsave(&stream->lock, *flags); @@ -259,6 +256,9 @@ size_t kbase_tlstream_flush_stream(struct kbase_tlstream *stream) size_t wb_size; size_t min_size = PACKET_HEADER_SIZE; + if (!stream->buffer) + return 0; + if (stream->numbered) min_size += PACKET_NUMBER_SIZE; diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.h b/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.h index d5745796e8e2..a74f5c044db4 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.h +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_tlstream.h @@ -99,9 +99,7 @@ enum tl_stream_type { TL_STREAM_TYPE_OBJ_SUMMARY = TL_STREAM_TYPE_FIRST, TL_STREAM_TYPE_OBJ, TL_STREAM_TYPE_AUX, -#if MALI_USE_CSF TL_STREAM_TYPE_CSFFW, -#endif TL_STREAM_TYPE_COUNT }; diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.c b/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.c index 2cc556583d8f..a8052716dee8 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.c +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -83,7 +83,7 @@ enum tl_msg_id_obj { KBASE_TL_ATTRIB_ATOM_PRIORITY, KBASE_TL_ATTRIB_ATOM_STATE, KBASE_TL_ATTRIB_ATOM_PRIORITIZED, - KBASE_TL_ATTRIB_ATOM_JIT, + KBASE_JD_AS_INFO, KBASE_TL_KBASE_NEW_DEVICE, KBASE_TL_KBASE_GPUCMDQUEUE_KICK, KBASE_TL_KBASE_DEVICE_PROGRAM_CSG, @@ -354,10 +354,10 @@ enum tl_msg_id_obj { "atom caused priority change", \ "@p", \ "atom") \ - TRACEPOINT_DESC(KBASE_TL_ATTRIB_ATOM_JIT, \ - "jit done for atom", \ - "@pLLILILLL", \ - "atom,edit_addr,new_addr,jit_flags,mem_flags,j_id,com_pgs,extent,va_pgs") \ + TRACEPOINT_DESC(KBASE_JD_AS_INFO, \ + "address space attributes", \ + "@ILLL", \ + "as_nr,transtab,memattr,transcfg") \ TRACEPOINT_DESC(KBASE_TL_KBASE_NEW_DEVICE, \ "New KBase Device", \ "@IIIIIIII", \ @@ -2043,30 +2043,20 @@ void __kbase_tlstream_tl_attrib_atom_prioritized( kbase_tlstream_msgbuf_release(stream, acq_flags); } -void __kbase_tlstream_tl_attrib_atom_jit( +void __kbase_tlstream_jd_as_info( struct kbase_tlstream *stream, - const void *atom, - u64 edit_addr, - u64 new_addr, - u32 jit_flags, - u64 mem_flags, - u32 j_id, - u64 com_pgs, - u64 extent, - u64 va_pgs + u32 as_nr, + u64 transtab, + u64 memattr, + u64 transcfg ) { - const u32 msg_id = KBASE_TL_ATTRIB_ATOM_JIT; + const u32 msg_id = KBASE_JD_AS_INFO; const size_t msg_size = sizeof(msg_id) + sizeof(u64) - + sizeof(atom) - + sizeof(edit_addr) - + sizeof(new_addr) - + sizeof(jit_flags) - + sizeof(mem_flags) - + sizeof(j_id) - + sizeof(com_pgs) - + sizeof(extent) - + sizeof(va_pgs) + + sizeof(as_nr) + + sizeof(transtab) + + sizeof(memattr) + + sizeof(transcfg) ; char *buffer; unsigned long acq_flags; @@ -2077,23 +2067,13 @@ void __kbase_tlstream_tl_attrib_atom_jit( pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_serialize_timestamp(buffer, pos); pos = kbasep_serialize_bytes(buffer, - pos, &atom, sizeof(atom)); + pos, &as_nr, sizeof(as_nr)); pos = kbasep_serialize_bytes(buffer, - pos, &edit_addr, sizeof(edit_addr)); + pos, &transtab, sizeof(transtab)); pos = kbasep_serialize_bytes(buffer, - pos, &new_addr, sizeof(new_addr)); + pos, &memattr, sizeof(memattr)); pos = kbasep_serialize_bytes(buffer, - pos, &jit_flags, sizeof(jit_flags)); - pos = kbasep_serialize_bytes(buffer, - pos, &mem_flags, sizeof(mem_flags)); - pos = kbasep_serialize_bytes(buffer, - pos, &j_id, sizeof(j_id)); - pos = kbasep_serialize_bytes(buffer, - pos, &com_pgs, sizeof(com_pgs)); - pos = kbasep_serialize_bytes(buffer, - pos, &extent, sizeof(extent)); - pos = kbasep_serialize_bytes(buffer, - pos, &va_pgs, sizeof(va_pgs)); + pos, &transcfg, sizeof(transcfg)); kbase_tlstream_msgbuf_release(stream, acq_flags); } diff --git a/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.h b/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.h index 2763866758c0..09678688805f 100644 --- a/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.h +++ b/drivers/gpu/arm/valhall/tl/mali_kbase_tracepoints.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -382,17 +382,12 @@ void __kbase_tlstream_tl_attrib_atom_prioritized( const void *atom ); -void __kbase_tlstream_tl_attrib_atom_jit( +void __kbase_tlstream_jd_as_info( struct kbase_tlstream *stream, - const void *atom, - u64 edit_addr, - u64 new_addr, - u32 jit_flags, - u64 mem_flags, - u32 j_id, - u64 com_pgs, - u64 extent, - u64 va_pgs + u32 as_nr, + u64 transtab, + u64 memattr, + u64 transcfg ); void __kbase_tlstream_tl_kbase_new_device( @@ -1961,45 +1956,30 @@ struct kbase_tlstream; } while (0) /** - * KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT - jit done for atom + * KBASE_TLSTREAM_JD_AS_INFO - address space attributes * * @kbdev: Kbase device - * @atom: Atom identifier - * @edit_addr: Address edited by jit - * @new_addr: Address placed into the edited location - * @jit_flags: Flags specifying the special requirements for the JIT allocation. - * @mem_flags: Flags defining the properties of a memory region - * @j_id: Unique ID provided by the caller, this is used to pair allocation and free requests. - * @com_pgs: The minimum number of physical pages which should back the allocation. - * @extent: Granularity of physical pages to grow the allocation by during a fault. - * @va_pgs: The minimum number of virtual pages required + * @as_nr: Address space number + * @transtab: Configuration of the TRANSTAB register + * @memattr: Configuration of the MEMATTR register + * @transcfg: Configuration of the TRANSCFG register (or zero if not present) */ -#define KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT( \ +#define KBASE_TLSTREAM_JD_AS_INFO( \ kbdev, \ - atom, \ - edit_addr, \ - new_addr, \ - jit_flags, \ - mem_flags, \ - j_id, \ - com_pgs, \ - extent, \ - va_pgs \ + as_nr, \ + transtab, \ + memattr, \ + transcfg \ ) \ do { \ u32 enabled = (u32)atomic_read(&kbdev->timeline_flags); \ if (enabled & BASE_TLSTREAM_JOB_DUMPING_ENABLED) \ - __kbase_tlstream_tl_attrib_atom_jit( \ + __kbase_tlstream_jd_as_info( \ __TL_DISPATCH_STREAM(kbdev, obj), \ - atom, \ - edit_addr, \ - new_addr, \ - jit_flags, \ - mem_flags, \ - j_id, \ - com_pgs, \ - extent, \ - va_pgs \ + as_nr, \ + transtab, \ + memattr, \ + transcfg \ ); \ } while (0) @@ -2016,7 +1996,6 @@ struct kbase_tlstream; * @kbase_device_supports_gpu_sleep: Whether GPU sleep is supported * @kbase_device_has_neural_engine: Whether neural engine is supported */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_NEW_DEVICE( \ kbdev, \ kbase_device_id, \ @@ -2043,20 +2022,6 @@ struct kbase_tlstream; kbase_device_has_neural_engine \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_NEW_DEVICE( \ - kbdev, \ - kbase_device_id, \ - kbase_device_gpu_core_count, \ - kbase_device_max_num_csgs, \ - kbase_device_as_count, \ - kbase_device_sb_entry_count, \ - kbase_device_has_cross_stream_sync, \ - kbase_device_supports_gpu_sleep, \ - kbase_device_has_neural_engine \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_GPUCMDQUEUE_KICK - Kernel receives a request to process new GPU queue instructions @@ -2065,7 +2030,6 @@ struct kbase_tlstream; * @kernel_ctx_id: Unique ID for the KBase Context * @buffer_gpu_addr: Address of the GPU queue's command buffer */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_GPUCMDQUEUE_KICK( \ kbdev, \ kernel_ctx_id, \ @@ -2080,14 +2044,6 @@ struct kbase_tlstream; buffer_gpu_addr \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_GPUCMDQUEUE_KICK( \ - kbdev, \ - kernel_ctx_id, \ - buffer_gpu_addr \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG - CSG is programmed to a slot @@ -2099,7 +2055,6 @@ struct kbase_tlstream; * @kbase_device_csg_slot_index: The index of the slot in the scheduler being programmed * @kbase_device_csg_slot_resuming: Whether the csg is being resumed */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG( \ kbdev, \ kbase_device_id, \ @@ -2120,17 +2075,6 @@ struct kbase_tlstream; kbase_device_csg_slot_resuming \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROGRAM_CSG( \ - kbdev, \ - kbase_device_id, \ - kernel_ctx_id, \ - gpu_cmdq_grp_handle, \ - kbase_device_csg_slot_index, \ - kbase_device_csg_slot_resuming \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG - CSG is deprogrammed from a slot @@ -2139,7 +2083,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @kbase_device_csg_slot_index: The index of the slot in the scheduler whose CSG is being deprogrammed */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG( \ kbdev, \ kbase_device_id, \ @@ -2154,14 +2097,6 @@ struct kbase_tlstream; kbase_device_csg_slot_index \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_DEPROGRAM_CSG( \ - kbdev, \ - kbase_device_id, \ - kbase_device_csg_slot_index \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_PROTM_ENTER_CSG - CSG slot is entering protected mode @@ -2170,7 +2105,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @kbase_device_csg_slot_index: The index of the slot in the scheduler whose CSG has entered PMODE */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROTM_ENTER_CSG( \ kbdev, \ kbase_device_id, \ @@ -2185,14 +2119,6 @@ struct kbase_tlstream; kbase_device_csg_slot_index \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_PROTM_ENTER_CSG( \ - kbdev, \ - kbase_device_id, \ - kbase_device_csg_slot_index \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_HALTING_CSG - CSG is halting @@ -2202,7 +2128,6 @@ struct kbase_tlstream; * @kbase_device_csg_slot_index: The index of the slot in the scheduler whose CSG is being halted * @kbase_device_csg_slot_suspending: Whether the csg is being suspended */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_HALTING_CSG( \ kbdev, \ kbase_device_id, \ @@ -2219,15 +2144,6 @@ struct kbase_tlstream; kbase_device_csg_slot_suspending \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_HALTING_CSG( \ - kbdev, \ - kbase_device_id, \ - kbase_device_csg_slot_index, \ - kbase_device_csg_slot_suspending \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_SUSPEND_CSG - CSG is suspended @@ -2236,7 +2152,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @kbase_device_csg_slot_index: The index of the slot in the scheduler whose CSG is being suspended */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_SUSPEND_CSG( \ kbdev, \ kbase_device_id, \ @@ -2251,14 +2166,6 @@ struct kbase_tlstream; kbase_device_csg_slot_index \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_SUSPEND_CSG( \ - kbdev, \ - kbase_device_id, \ - kbase_device_csg_slot_index \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_CSG_IDLE - KBase device is notified that CSG is idle. @@ -2267,7 +2174,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @kbase_device_csg_slot_index: The index of the slot in the scheduler whose CSG for which we are receiving an idle notification */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_CSG_IDLE( \ kbdev, \ kbase_device_id, \ @@ -2282,14 +2188,6 @@ struct kbase_tlstream; kbase_device_csg_slot_index \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_CSG_IDLE( \ - kbdev, \ - kbase_device_id, \ - kbase_device_csg_slot_index \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_NEW_CTX - New KBase Context @@ -2298,7 +2196,6 @@ struct kbase_tlstream; * @kernel_ctx_id: Unique ID for the KBase Context * @kbase_device_id: The ID of the physical hardware */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_NEW_CTX( \ kbdev, \ kernel_ctx_id, \ @@ -2313,14 +2210,6 @@ struct kbase_tlstream; kbase_device_id \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_NEW_CTX( \ - kbdev, \ - kernel_ctx_id, \ - kbase_device_id \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEL_CTX - Delete KBase Context @@ -2328,7 +2217,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kernel_ctx_id: Unique ID for the KBase Context */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEL_CTX( \ kbdev, \ kernel_ctx_id \ @@ -2341,13 +2229,6 @@ struct kbase_tlstream; kernel_ctx_id \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEL_CTX( \ - kbdev, \ - kernel_ctx_id \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE - New KCPU Queue @@ -2358,7 +2239,6 @@ struct kbase_tlstream; * @kernel_ctx_id: Unique ID for the KBase Context * @kcpuq_num_pending_cmds: Number of commands already enqueued in the KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE( \ kbdev, \ kcpu_queue, \ @@ -2377,16 +2257,6 @@ struct kbase_tlstream; kcpuq_num_pending_cmds \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_NEW_KCPUQUEUE( \ - kbdev, \ - kcpu_queue, \ - kcpu_queue_id, \ - kernel_ctx_id, \ - kcpuq_num_pending_cmds \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE - Delete KCPU Queue @@ -2394,7 +2264,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE( \ kbdev, \ kcpu_queue \ @@ -2407,13 +2276,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEL_KCPUQUEUE( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL - KCPU Queue enqueues Signal on Fence @@ -2422,7 +2284,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @fence: Fence object handle */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL( \ kbdev, \ kcpu_queue, \ @@ -2437,14 +2298,6 @@ struct kbase_tlstream; fence \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_SIGNAL( \ - kbdev, \ - kcpu_queue, \ - fence \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT - KCPU Queue enqueues Wait on Fence @@ -2453,7 +2306,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @fence: Fence object handle */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT( \ kbdev, \ kcpu_queue, \ @@ -2468,14 +2320,6 @@ struct kbase_tlstream; fence \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT( \ - kbdev, \ - kcpu_queue, \ - fence \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT - KCPU Queue enqueues Wait on Cross Queue Sync Object @@ -2486,7 +2330,6 @@ struct kbase_tlstream; * @compare_value: Semaphore value that should be exceeded for the WAIT to pass * @inherit_error: Flag which indicates if the CQS object error state should be inherited by the queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT( \ kbdev, \ kcpu_queue, \ @@ -2505,16 +2348,6 @@ struct kbase_tlstream; inherit_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT( \ - kbdev, \ - kcpu_queue, \ - cqs_obj_gpu_addr, \ - compare_value, \ - inherit_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET - KCPU Queue enqueues Set on Cross Queue Sync Object @@ -2523,7 +2356,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @cqs_obj_gpu_addr: CQS Object GPU pointer */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET( \ kbdev, \ kcpu_queue, \ @@ -2538,14 +2370,6 @@ struct kbase_tlstream; cqs_obj_gpu_addr \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET( \ - kbdev, \ - kcpu_queue, \ - cqs_obj_gpu_addr \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT_OPERATION - KCPU Queue enqueues Wait Operation on Cross Queue Sync Object @@ -2558,7 +2382,6 @@ struct kbase_tlstream; * @data_type: Data type of a CQS Object's value * @inherit_error: Flag which indicates if the CQS object error state should be inherited by the queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT_OPERATION( \ kbdev, \ kcpu_queue, \ @@ -2581,18 +2404,6 @@ struct kbase_tlstream; inherit_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_WAIT_OPERATION( \ - kbdev, \ - kcpu_queue, \ - cqs_obj_gpu_addr, \ - compare_value, \ - condition, \ - data_type, \ - inherit_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET_OPERATION - KCPU Queue enqueues Set Operation on Cross Queue Sync Object @@ -2604,7 +2415,6 @@ struct kbase_tlstream; * @operation: Operation type performed on semaphore value (SET or ADD) * @data_type: Data type of a CQS Object's value */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET_OPERATION( \ kbdev, \ kcpu_queue, \ @@ -2625,17 +2435,6 @@ struct kbase_tlstream; data_type \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_CQS_SET_OPERATION( \ - kbdev, \ - kcpu_queue, \ - cqs_obj_gpu_addr, \ - value, \ - operation, \ - data_type \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT - KCPU Queue enqueues Map Import @@ -2644,7 +2443,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @map_import_buf_gpu_addr: Map import buffer GPU pointer */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT( \ kbdev, \ kcpu_queue, \ @@ -2659,14 +2457,6 @@ struct kbase_tlstream; map_import_buf_gpu_addr \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_MAP_IMPORT( \ - kbdev, \ - kcpu_queue, \ - map_import_buf_gpu_addr \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT - KCPU Queue enqueues Unmap Import @@ -2675,7 +2465,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @map_import_buf_gpu_addr: Map import buffer GPU pointer */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT( \ kbdev, \ kcpu_queue, \ @@ -2690,14 +2479,6 @@ struct kbase_tlstream; map_import_buf_gpu_addr \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT( \ - kbdev, \ - kcpu_queue, \ - map_import_buf_gpu_addr \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE - KCPU Queue enqueues Unmap Import ignoring reference count @@ -2706,7 +2487,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @map_import_buf_gpu_addr: Map import buffer GPU pointer */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE( \ kbdev, \ kcpu_queue, \ @@ -2721,14 +2501,6 @@ struct kbase_tlstream; map_import_buf_gpu_addr \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_UNMAP_IMPORT_FORCE( \ - kbdev, \ - kcpu_queue, \ - map_import_buf_gpu_addr \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC - Begin array of KCPU Queue enqueues JIT Alloc @@ -2736,7 +2508,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ kbdev, \ kcpu_queue \ @@ -2749,13 +2520,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC - Array item of KCPU Queue enqueues JIT Alloc @@ -2772,7 +2536,6 @@ struct kbase_tlstream; * @jit_alloc_flags: Flags specifying the special requirements for the JIT allocation * @jit_alloc_usage_id: A hint about which allocation should be reused. The kernel should attempt to use a previous allocation with the same usage_id */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ kbdev, \ kcpu_queue, \ @@ -2803,22 +2566,6 @@ struct kbase_tlstream; jit_alloc_usage_id \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ - kbdev, \ - kcpu_queue, \ - jit_alloc_gpu_alloc_addr_dest, \ - jit_alloc_va_pages, \ - jit_alloc_commit_pages, \ - jit_alloc_extent, \ - jit_alloc_jit_id, \ - jit_alloc_bin_id, \ - jit_alloc_max_allocations, \ - jit_alloc_flags, \ - jit_alloc_usage_id \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC - End array of KCPU Queue enqueues JIT Alloc @@ -2826,7 +2573,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ kbdev, \ kcpu_queue \ @@ -2839,13 +2585,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_ALLOC( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE - Begin array of KCPU Queue enqueues JIT Free @@ -2853,7 +2592,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE( \ kbdev, \ kcpu_queue \ @@ -2866,13 +2604,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_ENQUEUE_JIT_FREE( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE - Array item of KCPU Queue enqueues JIT Free @@ -2881,7 +2612,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @jit_alloc_jit_id: Unique ID provided by the caller, this is used to pair allocation and free requests. Zero is not a valid value */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE( \ kbdev, \ kcpu_queue, \ @@ -2896,14 +2626,6 @@ struct kbase_tlstream; jit_alloc_jit_id \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_ENQUEUE_JIT_FREE( \ - kbdev, \ - kcpu_queue, \ - jit_alloc_jit_id \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE - End array of KCPU Queue enqueues JIT Free @@ -2911,7 +2633,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE( \ kbdev, \ kcpu_queue \ @@ -2924,13 +2645,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_ENQUEUE_JIT_FREE( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER - KCPU Queue enqueues Error Barrier @@ -2938,7 +2652,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ kbdev, \ kcpu_queue \ @@ -2951,13 +2664,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_ERROR_BARRIER( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND - KCPU Queue enqueues Group Suspend @@ -2967,7 +2673,6 @@ struct kbase_tlstream; * @group_suspend_buf: Pointer to the suspend buffer structure * @gpu_cmdq_grp_handle: GPU Command Queue Group handle which will match userspace */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ kbdev, \ kcpu_queue, \ @@ -2984,15 +2689,6 @@ struct kbase_tlstream; gpu_cmdq_grp_handle \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_ENQUEUE_GROUP_SUSPEND( \ - kbdev, \ - kcpu_queue, \ - group_suspend_buf, \ - gpu_cmdq_grp_handle \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START - KCPU Queue starts a Signal on Fence @@ -3000,7 +2696,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START( \ kbdev, \ kcpu_queue \ @@ -3013,13 +2708,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END - KCPU Queue ends a Signal on Fence @@ -3028,7 +2716,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END( \ kbdev, \ kcpu_queue, \ @@ -3043,14 +2730,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_SIGNAL_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START - KCPU Queue starts a Wait on Fence @@ -3058,7 +2737,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START( \ kbdev, \ kcpu_queue \ @@ -3071,13 +2749,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END - KCPU Queue ends a Wait on Fence @@ -3086,7 +2757,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END( \ kbdev, \ kcpu_queue, \ @@ -3101,14 +2771,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_FENCE_WAIT_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START - KCPU Queue starts a Wait on Cross Queue Sync Object @@ -3116,7 +2778,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START( \ kbdev, \ kcpu_queue \ @@ -3129,13 +2790,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END - KCPU Queue ends a Wait on Cross Queue Sync Object @@ -3144,7 +2798,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END( \ kbdev, \ kcpu_queue, \ @@ -3159,14 +2812,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET - KCPU Queue executes a Set on Cross Queue Sync Object @@ -3175,7 +2820,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET( \ kbdev, \ kcpu_queue, \ @@ -3190,14 +2834,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_START - KCPU Queue starts a Wait Operation on Cross Queue Sync Object @@ -3205,7 +2841,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_START( \ kbdev, \ kcpu_queue \ @@ -3218,13 +2853,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_END - KCPU Queue ends a Wait Operation on Cross Queue Sync Object @@ -3233,7 +2861,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_END( \ kbdev, \ kcpu_queue, \ @@ -3248,14 +2875,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_WAIT_OPERATION_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET_OPERATION - KCPU Queue executes a Set Operation on Cross Queue Sync Object @@ -3264,7 +2883,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET_OPERATION( \ kbdev, \ kcpu_queue, \ @@ -3279,14 +2897,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_CQS_SET_OPERATION( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START - KCPU Queue starts a Map Import @@ -3294,7 +2904,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START( \ kbdev, \ kcpu_queue \ @@ -3307,13 +2916,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END - KCPU Queue ends a Map Import @@ -3322,7 +2924,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END( \ kbdev, \ kcpu_queue, \ @@ -3337,14 +2938,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_MAP_IMPORT_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START - KCPU Queue starts an Unmap Import @@ -3352,7 +2945,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START( \ kbdev, \ kcpu_queue \ @@ -3365,13 +2957,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END - KCPU Queue ends an Unmap Import @@ -3380,7 +2965,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END( \ kbdev, \ kcpu_queue, \ @@ -3395,14 +2979,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START - KCPU Queue starts an Unmap Import ignoring reference count @@ -3410,7 +2986,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START( \ kbdev, \ kcpu_queue \ @@ -3423,13 +2998,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END - KCPU Queue ends an Unmap Import ignoring reference count @@ -3438,7 +3006,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END( \ kbdev, \ kcpu_queue, \ @@ -3453,14 +3020,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_UNMAP_IMPORT_FORCE_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START - KCPU Queue starts an array of JIT Allocs @@ -3468,7 +3027,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START( \ kbdev, \ kcpu_queue \ @@ -3481,13 +3039,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_ALLOC_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END - Begin array of KCPU Queue ends an array of JIT Allocs @@ -3495,7 +3046,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ kbdev, \ kcpu_queue \ @@ -3508,13 +3058,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END - Array item of KCPU Queue ends an array of JIT Allocs @@ -3525,7 +3068,6 @@ struct kbase_tlstream; * @jit_alloc_gpu_alloc_addr: The JIT allocated GPU virtual address * @jit_alloc_mmu_flags: The MMU flags for the JIT allocation */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ kbdev, \ kcpu_queue, \ @@ -3544,16 +3086,6 @@ struct kbase_tlstream; jit_alloc_mmu_flags \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ - kbdev, \ - kcpu_queue, \ - execute_error, \ - jit_alloc_gpu_alloc_addr, \ - jit_alloc_mmu_flags \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END - End array of KCPU Queue ends an array of JIT Allocs @@ -3561,7 +3093,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ kbdev, \ kcpu_queue \ @@ -3574,13 +3105,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_ALLOC_END( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START - KCPU Queue starts an array of JIT Frees @@ -3588,7 +3112,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START( \ kbdev, \ kcpu_queue \ @@ -3601,13 +3124,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_JIT_FREE_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END - Begin array of KCPU Queue ends an array of JIT Frees @@ -3615,7 +3131,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ kbdev, \ kcpu_queue \ @@ -3628,13 +3143,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_BEGIN_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END - Array item of KCPU Queue ends an array of JIT Frees @@ -3644,7 +3152,6 @@ struct kbase_tlstream; * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero * @jit_free_pages_used: The actual number of pages used by the JIT allocation */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ kbdev, \ kcpu_queue, \ @@ -3661,15 +3168,6 @@ struct kbase_tlstream; jit_free_pages_used \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_ITEM_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ - kbdev, \ - kcpu_queue, \ - execute_error, \ - jit_free_pages_used \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END - End array of KCPU Queue ends an array of JIT Frees @@ -3677,7 +3175,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ kbdev, \ kcpu_queue \ @@ -3690,13 +3187,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_ARRAY_END_KCPUQUEUE_EXECUTE_JIT_FREE_END( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER - KCPU Queue executes an Error Barrier @@ -3704,7 +3194,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER( \ kbdev, \ kcpu_queue \ @@ -3717,13 +3206,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_ERROR_BARRIER( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START - KCPU Queue starts a group suspend @@ -3731,7 +3213,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @kcpu_queue: KCPU queue */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START( \ kbdev, \ kcpu_queue \ @@ -3744,13 +3225,6 @@ struct kbase_tlstream; kcpu_queue \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_START( \ - kbdev, \ - kcpu_queue \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END - KCPU Queue ends a group suspend @@ -3759,7 +3233,6 @@ struct kbase_tlstream; * @kcpu_queue: KCPU queue * @execute_error: Non-zero error code if KCPU Queue item completed with error, else zero */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END( \ kbdev, \ kcpu_queue, \ @@ -3774,14 +3247,6 @@ struct kbase_tlstream; execute_error \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_KCPUQUEUE_EXECUTE_GROUP_SUSPEND_END( \ - kbdev, \ - kcpu_queue, \ - execute_error \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_L2_CORE_STATE - KBase device updates L2 Core state @@ -3790,7 +3255,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @new_state: New state */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_L2_CORE_STATE( \ kbdev, \ kbase_device_id, \ @@ -3805,14 +3269,6 @@ struct kbase_tlstream; new_state \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_L2_CORE_STATE( \ - kbdev, \ - kbase_device_id, \ - new_state \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_MCU_STATE - KBase device updates MCU state @@ -3821,7 +3277,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @new_state: New state */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_MCU_STATE( \ kbdev, \ kbase_device_id, \ @@ -3836,14 +3291,6 @@ struct kbase_tlstream; new_state \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_MCU_STATE( \ - kbdev, \ - kbase_device_id, \ - new_state \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_DEVICE_SHADER_CORE_STATE - KBase device updates Shader Core state @@ -3852,7 +3299,6 @@ struct kbase_tlstream; * @kbase_device_id: The ID of the physical hardware * @new_state: New state */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_DEVICE_SHADER_CORE_STATE( \ kbdev, \ kbase_device_id, \ @@ -3867,14 +3313,6 @@ struct kbase_tlstream; new_state \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_DEVICE_SHADER_CORE_STATE( \ - kbdev, \ - kbase_device_id, \ - new_state \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_DISABLING - CSF FW is being disabled @@ -3882,7 +3320,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @csffw_cycle: Cycle number of a CSFFW event */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_DISABLING( \ kbdev, \ csffw_cycle \ @@ -3895,13 +3332,6 @@ struct kbase_tlstream; csffw_cycle \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_DISABLING( \ - kbdev, \ - csffw_cycle \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_OFF - CSF FW is off @@ -3909,7 +3339,6 @@ struct kbase_tlstream; * @kbdev: Kbase device * @csffw_cycle: Cycle number of a CSFFW event */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_OFF( \ kbdev, \ csffw_cycle \ @@ -3922,13 +3351,6 @@ struct kbase_tlstream; csffw_cycle \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_CSFFW_FW_OFF( \ - kbdev, \ - csffw_cycle \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW - An overflow has happened with the CSFFW Timeline stream @@ -3937,7 +3359,6 @@ struct kbase_tlstream; * @csffw_timestamp: Timestamp of a CSFFW event * @csffw_cycle: Cycle number of a CSFFW event */ -#if MALI_USE_CSF #define KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW( \ kbdev, \ csffw_timestamp, \ @@ -3952,14 +3373,6 @@ struct kbase_tlstream; csffw_cycle \ ); \ } while (0) -#else -#define KBASE_TLSTREAM_TL_KBASE_CSFFW_TLSTREAM_OVERFLOW( \ - kbdev, \ - csffw_timestamp, \ - csffw_cycle \ - ) \ - do { } while (0) -#endif /* MALI_USE_CSF */ /** * KBASE_TLSTREAM_AUX_PM_STATE - PM state diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 6b54370d2a2c..28ad360bbb1c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -45,7 +45,7 @@ #include #include -#include "panel-simple.h" +#include "../rockchip/rockchip_drm_drv.h" enum panel_simple_cmd_type { CMD_TYPE_DEFAULT, @@ -219,6 +219,8 @@ struct panel_simple { enum drm_panel_orientation orientation; struct rockchip_panel_notifier panel_notifier; + + struct rockchip_drm_sub_dev sub_dev; }; static inline void panel_simple_msleep(unsigned int msecs) @@ -518,23 +520,29 @@ static int panel_simple_regulator_disable(struct panel_simple *p) return 0; } -int panel_simple_loader_protect(struct drm_panel *panel) +static int panel_simple_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct panel_simple *p = to_panel_simple(panel); + struct panel_simple *p = container_of(sub_dev, struct panel_simple, sub_dev); int err; - err = panel_simple_regulator_enable(p); - if (err < 0) { - dev_err(panel->dev, "failed to enable supply: %d\n", err); - return err; - } + if (on) { + err = panel_simple_regulator_enable(p); + if (err < 0) { + dev_err(p->base.dev, "failed to enable supply: %d\n", err); + return err; + } - p->prepared = true; - p->enabled = true; + p->prepared = true; + p->enabled = true; + } else { + p->enabled = false; + p->prepared = false; + + panel_simple_regulator_disable(p); + } return 0; } -EXPORT_SYMBOL(panel_simple_loader_protect); static int panel_simple_disable(struct drm_panel *panel) { @@ -1001,6 +1009,10 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) drm_panel_add(&panel->base); + panel->sub_dev.of_node = dev->of_node; + panel->sub_dev.loader_protect = panel_simple_loader_protect; + rockchip_drm_register_sub_dev(&panel->sub_dev); + return 0; free_ddc: @@ -1014,6 +1026,8 @@ static void panel_simple_remove(struct device *dev) { struct panel_simple *panel = dev_get_drvdata(dev); + rockchip_drm_unregister_sub_dev(&panel->sub_dev); + drm_panel_remove(&panel->base); drm_panel_disable(&panel->base); drm_panel_unprepare(&panel->base); diff --git a/drivers/gpu/drm/panel/panel-simple.h b/drivers/gpu/drm/panel/panel-simple.h deleted file mode 100644 index a056f357886a..000000000000 --- a/drivers/gpu/drm/panel/panel-simple.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Copyright (c) 2021 Rockchip Electronics Co., Ltd. - * Author: Sandy Huang - */ - -#ifndef PANEL_SIMPLE_H -#define PANEL_SIMPLE_H -#include - -#if IS_REACHABLE(CONFIG_DRM_PANEL_SIMPLE) -int panel_simple_loader_protect(struct drm_panel *panel); -#else -static inline int panel_simple_loader_protect(struct drm_panel *panel) -{ - return 0; -} -#endif -#endif diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 702c24f3a12f..f08cf6605ef2 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -252,9 +252,9 @@ static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, return 0; } -static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int rockchip_dp_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_dp_device *dp = encoder_to_dp(encoder); + struct rockchip_dp_device *dp = container_of(sub_dev, struct rockchip_dp_device, sub_dev); struct analogix_dp_plat_data *plat_data = &dp->plat_data; struct rockchip_dp_device *secondary = NULL; int ret; @@ -262,7 +262,7 @@ static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) if (plat_data->right) { secondary = rockchip_dp_find_by_id(dp->dev->driver, !dp->id); - ret = rockchip_dp_loader_protect(&secondary->encoder.encoder, on); + ret = rockchip_dp_loader_protect(&secondary->sub_dev, on); if (ret) return ret; } @@ -271,7 +271,7 @@ static int rockchip_dp_loader_protect(struct drm_encoder *encoder, bool on) return 0; if (plat_data->panel) - panel_simple_loader_protect(plat_data->panel); + rockchip_drm_panel_loader_protect(plat_data->panel, on); ret = analogix_dp_loader_protect(dp->adp); if (ret) { diff --git a/drivers/gpu/drm/rockchip/dw-dp.c b/drivers/gpu/drm/rockchip/dw-dp.c index c61ebb04bec6..ef2f2615835d 100644 --- a/drivers/gpu/drm/rockchip/dw-dp.c +++ b/drivers/gpu/drm/rockchip/dw-dp.c @@ -3294,6 +3294,8 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on) extcon_set_state_sync(dp->audio->extcon, EXTCON_DISP_DP, true); dw_dp_audio_handle_plugged_change(dp->audio, true); phy_power_on(dp->phy); + link->train.clock_recovered = true; + link->train.channel_equalized = true; } else { phy_power_off(dp->phy); extcon_set_state_sync(dp->audio->extcon, EXTCON_DISP_DP, false); @@ -3306,9 +3308,9 @@ static void _dw_dp_loader_protect(struct dw_dp *dp, bool on) } } -static int dw_dp_loader_protect(struct drm_encoder *encoder, bool on) +static int dw_dp_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct dw_dp *dp = encoder_to_dp(encoder); + struct dw_dp *dp = container_of(sub_dev, struct dw_dp, sub_dev); dp->is_loader_protect = true; _dw_dp_loader_protect(dp, on); @@ -4675,7 +4677,7 @@ static u32 *dw_dp_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, continue; } - if (dw_dp_is_hdr_eotf(dp->eotf_type) && fmt->bpc < 10) + if (dw_dp_is_hdr_eotf(dp->eotf_type) && fmt->bpc < 8) continue; output_fmts[j++] = fmt->bus_format; diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index ddaf11508bc2..111e3d1e594a 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -339,6 +340,7 @@ struct dw_mipi_dsi_rockchip { u16 input_div; u16 feedback_div; u32 format; + u32 mode_flags; struct dw_mipi_dsi *dmd; const struct rockchip_dw_dsi_chip_data *cdata; @@ -347,6 +349,9 @@ struct dw_mipi_dsi_rockchip { struct rockchip_drm_sub_dev sub_dev; struct drm_panel *panel; struct drm_bridge *bridge; + + struct gpio_desc *te_gpio; + bool disable_hold_mode; }; static struct dw_mipi_dsi_rockchip *to_dsi(struct drm_encoder *encoder) @@ -846,6 +851,12 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, if (dsi->id && dsi->cdata->soc_type == RK3399) s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; + if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) { + s->output_flags |= ROCKCHIP_OUTPUT_MIPI_DS_MODE; + s->soft_te = dsi->te_gpio ? true : false; + s->hold_mode = dsi->disable_hold_mode ? false : true; + } + if (dsi->dsc_enable) { s->dsc_enable = 1; s->dsc_sink_cap.version_major = dsi->version_major; @@ -894,13 +905,14 @@ static void dw_mipi_dsi_rockchip_loader_protect(struct dw_mipi_dsi_rockchip *dsi dw_mipi_dsi_rockchip_loader_protect(dsi->slave, on); } -static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int dw_mipi_dsi_rockchip_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, + bool on) { - struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); + struct dw_mipi_dsi_rockchip *dsi = container_of(sub_dev, struct dw_mipi_dsi_rockchip, + sub_dev); if (dsi->panel) - panel_simple_loader_protect(dsi->panel); + rockchip_drm_panel_loader_protect(dsi->panel, on); dw_mipi_dsi_rockchip_loader_protect(dsi, on); @@ -979,6 +991,17 @@ static struct device return NULL; } +static irqreturn_t dw_mipi_dsi_te_irq_handler(int irq, void *dev_id) +{ + struct dw_mipi_dsi_rockchip *dsi = (struct dw_mipi_dsi_rockchip *)dev_id; + struct drm_encoder *encoder = &dsi->encoder; + + if (encoder->crtc) + rockchip_drm_te_handle(encoder->crtc); + + return IRQ_HANDLED; +} + static int dw_mipi_dsi_get_dsc_info_from_sink(struct dw_mipi_dsi_rockchip *dsi, struct drm_panel *panel, struct drm_bridge *bridge) @@ -1003,6 +1026,7 @@ static int dw_mipi_dsi_get_dsc_info_from_sink(struct dw_mipi_dsi_rockchip *dsi, dsi->scrambling_en = of_property_read_bool(np, "scrambling-enable"); dsi->dsc_enable = of_property_read_bool(np, "compressed-data"); dsi->block_pred_enable = of_property_read_bool(np, "blk-pred-enable"); + of_property_read_u32(np, "dsi,flags", &dsi->mode_flags); of_property_read_u32(np, "slice-width", &dsi->slice_width); of_property_read_u32(np, "slice-height", &dsi->slice_height); of_property_read_u32(np, "slice-per-pkt", &dsi->slice_per_pkt); @@ -1502,6 +1526,23 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) return PTR_ERR(dsi->grf_regmap); } + if (device_property_read_bool(dev, "disable-hold-mode")) + dsi->disable_hold_mode = true; + + dsi->te_gpio = devm_gpiod_get_optional(dev, "te", GPIOD_IN); + if (IS_ERR(dsi->te_gpio)) + dsi->te_gpio = NULL; + + if (dsi->te_gpio) { + ret = devm_request_irq(dev, gpiod_to_irq(dsi->te_gpio), + dw_mipi_dsi_te_irq_handler, + IRQF_TRIGGER_RISING, "PANEL-TE", dsi); + if (ret) { + DRM_DEV_ERROR(dev, "failed to request TE IRQ: %d\n", ret); + return ret; + } + } + dsi->dev = dev; dsi->pdata.base = dsi->base; dsi->pdata.max_data_lanes = dsi->cdata->max_data_lanes; diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index 92a19144dbae..8d0d3539b0fb 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -281,6 +281,9 @@ struct dw_mipi_dsi2 { struct gpio_desc *te_gpio; + /* rockchip,split-mode */ + bool split_mode; + /* split with other display interface */ bool dual_connector_split; bool left_display; @@ -1188,13 +1191,12 @@ static void dw_mipi_dsi2_loader_protect(struct dw_mipi_dsi2 *dsi2, bool on) dw_mipi_dsi2_loader_protect(dsi2->slave, on); } -static int dw_mipi_dsi2_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int dw_mipi_dsi2_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder); + struct dw_mipi_dsi2 *dsi2 = container_of(sub_dev, struct dw_mipi_dsi2, sub_dev); if (dsi2->panel) - panel_simple_loader_protect(dsi2->panel); + rockchip_drm_panel_loader_protect(dsi2->panel, on); dw_mipi_dsi2_loader_protect(dsi2, on); @@ -1211,14 +1213,27 @@ dw_mipi_dsi2_encoder_helper_funcs = { static int dw_mipi_dsi2_connector_get_modes(struct drm_connector *connector) { struct dw_mipi_dsi2 *dsi2 = con_to_dsi2(connector); + struct drm_display_info *di = &connector->display_info; + int num_modes = 0; if (dsi2->bridge && (dsi2->bridge->ops & DRM_BRIDGE_OP_MODES)) - return drm_bridge_get_modes(dsi2->bridge, connector); + num_modes = drm_bridge_get_modes(dsi2->bridge, connector); if (dsi2->panel) - return drm_panel_get_modes(dsi2->panel, connector); + num_modes = drm_panel_get_modes(dsi2->panel, connector); - return -EINVAL; + if (!num_modes) + return -EINVAL; + + if (dsi2->split_mode && dsi2->slave) { + struct drm_display_mode *mode; + + di->width_mm *= 2; + list_for_each_entry(mode, &connector->probed_modes, head) + drm_mode_convert_to_split_mode(mode); + } + + return num_modes; } static enum drm_mode_status @@ -1382,7 +1397,8 @@ static struct dw_mipi_dsi2 *dw_mipi_dsi2_find_by_id(struct device_driver *drv, static int dw_mipi_dsi2_dual_channel_probe(struct dw_mipi_dsi2 *dsi2) { - if (of_property_read_bool(dsi2->dev->of_node, "rockchip,dual-channel")) { + if (of_property_read_bool(dsi2->dev->of_node, "rockchip,dual-channel") || + of_property_read_bool(dsi2->dev->of_node, "rockchip,split-mode")) { dsi2->data_swap = of_property_read_bool(dsi2->dev->of_node, "rockchip,data-swap"); @@ -1390,8 +1406,13 @@ static int dw_mipi_dsi2_dual_channel_probe(struct dw_mipi_dsi2 *dsi2) if (!dsi2->slave) return -EPROBE_DEFER; + if (of_property_read_bool(dsi2->dev->of_node, "rockchip,split-mode")) + dsi2->split_mode = true; + dsi2->slave->master = dsi2; - dsi2->lanes /= 2; + + if (!dsi2->split_mode) + dsi2->lanes /= 2; dsi2->slave->auto_calc_mode = dsi2->auto_calc_mode; dsi2->slave->lanes = dsi2->lanes; @@ -1491,7 +1512,7 @@ static int dw_mipi_dsi2_get_dsc_params_from_sink(struct dw_mipi_dsi2 *dsi2, dsi2->pps = pps; - if (dsi2->slave) { + if (dsi2->slave && !dsi2->split_mode) { u16 pic_width = be16_to_cpu(pps->pic_width) / 2; dsi2->pps->pic_width = cpu_to_be16(pic_width); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index f8fe5d93d777..48ac9fe64cc2 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -2153,9 +2153,9 @@ static int _dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_hdmi *hdmi, return 0; } -static int dw_hdmi_rockchip_encoder_loader_protect(struct drm_encoder *encoder, bool on) +static int dw_hdmi_rockchip_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); + struct rockchip_hdmi *hdmi = container_of(sub_dev, struct rockchip_hdmi, sub_dev); struct rockchip_hdmi *secondary; _dw_hdmi_rockchip_encoder_loader_protect(hdmi, on); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index e4f37451323d..a25d4c863130 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -383,7 +383,7 @@ void rockchip_connector_update_vfp_for_vrr(struct drm_crtc *crtc, struct drm_dis mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->state->crtc == crtc) { + if (sub_dev->connector && sub_dev->connector->state->crtc == crtc) { if (sub_dev->update_vfp_for_vrr) sub_dev->update_vfp_for_vrr(sub_dev->connector, mode, vfp); } @@ -433,7 +433,7 @@ int rockchip_drm_get_sub_dev_type(void) mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->encoder) { + if (sub_dev->connector && sub_dev->connector->encoder) { connector_type = sub_dev->connector->connector_type; break; } @@ -452,7 +452,8 @@ u32 rockchip_drm_get_scan_line_time_ns(void) mutex_lock(&rockchip_drm_sub_dev_lock); list_for_each_entry(sub_dev, &rockchip_drm_sub_dev_list, list) { - if (sub_dev->connector->encoder && sub_dev->connector->state->crtc) { + if (sub_dev->connector && sub_dev->connector->encoder && + sub_dev->connector->state->crtc) { mode = &sub_dev->connector->state->crtc->state->adjusted_mode; linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, mode->crtc_clock); break; @@ -1478,6 +1479,9 @@ static int rockchip_drm_create_properties(struct drm_device *dev) private->cubic_lut_size_prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "CUBIC_LUT_SIZE", 0, UINT_MAX); + private->dimming_data_prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, + "DIMMING_DATA", 0); + return drm_mode_create_tv_properties_legacy(dev, 0, NULL); } @@ -1753,6 +1757,21 @@ static void rockchip_drm_error_event_fini(struct drm_device *drm_dev) device_remove_file(drm_dev->dev, &dev_attr_error_event); } +int rockchip_drm_panel_loader_protect(struct drm_panel *panel, bool on) +{ + struct rockchip_drm_sub_dev *sub_dev; + + if (!panel) + return -EINVAL; + + sub_dev = rockchip_drm_get_sub_dev(panel->dev->of_node); + if (sub_dev && sub_dev->loader_protect) + return sub_dev->loader_protect(sub_dev, on); + + return 0; +} +EXPORT_SYMBOL(rockchip_drm_panel_loader_protect); + static int rockchip_drm_bind(struct device *dev) { struct drm_device *drm_dev; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 94f55b45b004..d082e6614116 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -24,8 +25,6 @@ #include -#include "../panel/panel-simple.h" - #include "rockchip_drm_debugfs.h" #define ROCKCHIP_MAX_FB_BUFFER 3 @@ -145,7 +144,7 @@ struct rockchip_drm_sub_dev { struct list_head list; struct drm_connector *connector; struct device_node *of_node; - int (*loader_protect)(struct drm_encoder *encoder, bool on); + int (*loader_protect)(struct rockchip_drm_sub_dev *sub_dev, bool on); void (*update_vfp_for_vrr)(struct drm_connector *connector, struct drm_display_mode *mode, int vfp); }; @@ -275,6 +274,7 @@ struct rockchip_crtc_state { int output_mode; int output_bpc; int output_flags; + int data_map_mode; bool enable_afbc; /** * @splice_mode: enabled when display a hdisplay > 4096 on rk3588 @@ -299,6 +299,8 @@ struct rockchip_crtc_state { */ bool sharp_en; + bool dimming_changed; + struct drm_tv_connector_state *tv_state; int left_margin; int right_margin; @@ -348,6 +350,7 @@ struct rockchip_crtc_state { struct drm_property_blob *post_csc_data; struct drm_property_blob *post_sharp_data; struct drm_property_blob *cubic_lut_data; + struct drm_property_blob *dimming_data; int request_refresh_rate; int max_refresh_rate; @@ -580,6 +583,9 @@ struct rockchip_drm_private { struct drm_property *connector_id_prop; struct drm_property *split_area_prop; + /* private local dimming prop */ + struct drm_property *dimming_data_prop; + const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC]; uint64_t iommu_fault_count; @@ -689,6 +695,7 @@ const char *rockchip_drm_modifier_to_string(uint64_t modifier); void rockchip_drm_reset_iommu_fault_handler_rate_limit(void); void rockchip_drm_send_error_event(struct rockchip_drm_private *priv, enum rockchip_drm_error_event_type event); +int rockchip_drm_panel_loader_protect(struct drm_panel *panel, bool on); __printf(3, 4) void rockchip_drm_dbg(const struct device *dev, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index 7ed21b180606..79ca99660407 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -813,7 +813,7 @@ static int setup_initial_state(struct drm_device *drm_dev, conn_state->best_encoder = rockchip_drm_connector_get_single_encoder(connector); if (set->sub_dev->loader_protect) { - ret = set->sub_dev->loader_protect(conn_state->best_encoder, true); + ret = set->sub_dev->loader_protect(set->sub_dev, true); if (ret) { dev_err(drm_dev->dev, "connector[%s] loader protect failed\n", @@ -979,7 +979,7 @@ error_crtc: priv->crtc_funcs[pipe]->loader_protect(crtc, false, NULL); error_conn: if (set->sub_dev->loader_protect) - set->sub_dev->loader_protect(conn_state->best_encoder, false); + set->sub_dev->loader_protect(set->sub_dev, false); return ret; } @@ -1319,13 +1319,36 @@ static const char *const loader_protect_clocks[] __initconst = { static struct clk **loader_clocks; static int __init rockchip_clocks_loader_protect(void) { + struct device_node *np, *route_np, *route_child_np; int nclocks = ARRAY_SIZE(loader_protect_clocks); struct clk *clk; int i; + int ret = 0; + + /* Check for available route nodes and enable protect only when node is available. */ + np = of_find_compatible_node(NULL, NULL, "rockchip,display-subsystem"); + if (!np || !of_device_is_available(np)) { + ret = -ENODEV; + goto err_np; + } + + route_np = of_get_child_by_name(np, "route"); + if (!route_np) { + ret = -ENODEV; + goto err_route_np; + } + + route_child_np = of_get_next_available_child(route_np, NULL); + if (!route_child_np) { + ret = -ENODEV; + goto err_route_child_np; + } loader_clocks = kcalloc(nclocks, sizeof(void *), GFP_KERNEL); - if (!loader_clocks) - return -ENOMEM; + if (!loader_clocks) { + ret = -ENOMEM; + goto err_route_child_np; + } for (i = 0; i < nclocks; i++) { clk = __clk_lookup(loader_protect_clocks[i]); @@ -1336,7 +1359,14 @@ static int __init rockchip_clocks_loader_protect(void) } } - return 0; +err_route_child_np: + of_node_put(route_child_np); +err_route_np: + of_node_put(route_np); +err_np: + of_node_put(np); + + return ret; } arch_initcall_sync(rockchip_clocks_loader_protect); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c index f42b294a28a1..c91ebf36a30b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_tve.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_tve.c @@ -546,9 +546,9 @@ rockchip_tve_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static int rockchip_tve_encoder_loader_protect(struct drm_encoder *encoder, bool on) +static int rockchip_tve_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_tve *tve = encoder_to_tve(encoder); + struct rockchip_tve *tve = container_of(sub_dev, struct rockchip_tve, sub_dev); int ret; if (on) { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 551194fd3a0e..34f101d3582b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -2209,6 +2209,7 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, { struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, crtc); struct vop *vop = to_vop(crtc); + struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state); int sys_status = drm_crtc_index(crtc) ? SYS_STATUS_LCDC1 : SYS_STATUS_LCDC0; unsigned long status; @@ -2221,6 +2222,10 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, } vop_lock(vop); + if (s->hold_mode) { + VOP_CTRL_SET(vop, edpi_te_en, 0); + VOP_CTRL_SET(vop, edpi_ctrl_mode, 0); + } VOP_CTRL_SET(vop, reg_done_frm, 1); VOP_CTRL_SET(vop, dsp_interlace, 0); drm_crtc_vblank_off(crtc); @@ -3825,8 +3830,24 @@ static void vop_crtc_te_handler(struct drm_crtc *crtc) vop = to_vop(crtc); - if (vop->mcu_timing.mcu_pix_total) + if (vop->mcu_timing.mcu_pix_total) { VOP_CTRL_SET(vop, mcu_frame_st, 1); + } else { + /* + * For software TE mode, we register a gpio IRQ to respond to + * the TE signal from the panel. If the TE signal is detected + * via gpio, a new frame will be sent to the panel for display + * only by controlling the edpi_wms_fs bit. + * + * As the IC design, the VOP will only refresh one new frame + * of image when the ​​edpi_wms_fs​​ bit, which can take effect + * immediately, is first written with ​​1​ and then cleared to 0​​. + * If only written to ​​1​​, it will result in ​​two frames being + * refreshed​​ instead. + */ + VOP_CTRL_SET(vop, edpi_wms_fs, 1); + VOP_CTRL_SET(vop, edpi_wms_fs, 0); + } } #if defined(CONFIG_ROCKCHIP_DRM_DEBUG) @@ -4173,6 +4194,15 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, if (vop->lut_active) vop_crtc_load_lut(crtc); + if (s->data_map_mode != -1) { + if (s->output_if & VOP_OUTPUT_IF_BT1120) + VOP_CTRL_SET(vop, bt1120_data_map_mode, s->data_map_mode); + else if (s->output_if & VOP_OUTPUT_IF_BT656) + VOP_CTRL_SET(vop, bt656_data_map_mode, s->data_map_mode); + else if (vop->mcu_timing.mcu_pix_total) + VOP_CTRL_SET(vop, mcu_data_map_mode, s->data_map_mode); + } + if (vop->mcu_timing.mcu_pix_total) { /* * For RK3576_LITE/RK3506/RV1126B @@ -4267,6 +4297,10 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, VOP_GRF_SET(vop, vo0_grf, grf_mipi_mode, 0); VOP_GRF_SET(vop, vo0_grf, grf_mipi_pin_pol, val); VOP_GRF_SET(vop, vo0_grf, grf_mipi_1to4_en, 1); + if (s->hold_mode) { + VOP_CTRL_SET(vop, edpi_te_en, !s->soft_te); + VOP_CTRL_SET(vop, edpi_ctrl_mode, 1); + } break; case DRM_MODE_CONNECTOR_DisplayPort: VOP_CTRL_SET(vop, dp_dclk_pol, 0); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 5f5ea7ccfcac..87243ee72c93 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -109,13 +109,6 @@ #define ROCKCHIP_DSC_PPS_SIZE_BYTE 88 -enum vop_vp_id { - ROCKCHIP_VOP_VP0 = 0, - ROCKCHIP_VOP_VP1, - ROCKCHIP_VOP_VP2, - ROCKCHIP_VOP_VP3, -}; - enum bcsh_out_mode { BCSH_OUT_MODE_BLACK, BCSH_OUT_MODE_BLUE, @@ -458,18 +451,25 @@ struct vop_ctrl { struct vop_reg mcu_type; struct vop_reg mcu_rw_bypass_port; struct vop_reg mcu_force_rdn; + struct vop_reg mcu_data_map_mode; /* bt1120 */ struct vop_reg bt1120_uv_swap; struct vop_reg bt1120_yc_swap; struct vop_reg bt1120_en; + struct vop_reg bt1120_data_map_mode; /* bt656 */ struct vop_reg bt656_en; + struct vop_reg bt656_data_map_mode; struct vop_reg reg_done_frm; struct vop_reg cfg_done; + struct vop_reg edpi_wms_fs; + struct vop_reg edpi_ctrl_mode; + struct vop_reg edpi_te_en; + /* ebc vop */ struct vop_reg enable; struct vop_reg inf_out_en; @@ -914,6 +914,7 @@ struct vop2_win_regs { struct vop2_video_port_regs { struct vop_reg cfg_done; + struct vop_reg sys_cfg_done; struct vop_reg overlay_mode; struct vop_reg dsp_background; struct vop_reg port_mux; @@ -1234,6 +1235,7 @@ struct vop2_win_data { uint8_t axi_uv_id; uint8_t possible_vp_mask; uint8_t dci_rid_id; + uint8_t reg_done_bit; uint32_t base; enum drm_plane_type type; @@ -1464,6 +1466,7 @@ struct vop_data { struct vop2_ctrl { struct vop_reg cfg_done_en; struct vop_reg wb_cfg_done; + struct vop_reg win_cfg_done; struct vop_reg auto_gating_en; struct vop_reg aclk_pre_auto_gating_en; struct vop_reg dma_finish_mode; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 66bd3c0672f2..2e8022d85c99 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -457,6 +457,7 @@ struct vop2_win { uint8_t axi_uv_id; uint8_t scale_engine_num; uint8_t possible_vp_mask; + uint8_t reg_done_bit; enum drm_plane_type type; unsigned int max_upscale_factor; unsigned int max_downscale_factor; @@ -780,6 +781,11 @@ struct vop2_video_port { * @plane_mask_prop: plane mask interaction with userspace */ struct drm_property *plane_mask_prop; + /** + * @reserved_plane_mask_prop: reserved plane mask interaction with userspace + */ + struct drm_property *reserved_plane_mask_prop; + /** * @feature_prop: crtc feature interaction with userspace */ @@ -834,6 +840,12 @@ struct vop2_video_port { */ int primary_plane_phy_id; + /** + * @reserved_plane_phy_id: reserved plane is used by third party OS, + * reserved plane is always on the top of overlay. + */ + int reserved_plane_phy_id; + struct post_acm acm_info; struct post_csc csc_info; @@ -871,6 +883,11 @@ struct vop2_video_port { * we configure whether sharp is disabled in dts */ bool sharp_disabled; + + /** + * @win_cfg_done_bits: control reg done bit for each win + */ + u32 win_cfg_done_bits; }; struct vop2_extend_pll { @@ -885,6 +902,13 @@ struct vop2_resource { void __iomem *regs; }; +struct vop2_shared_mode_res { + uint32_t shared_mode; + uint32_t vp_mask; + uint32_t plane_mask; + uint32_t axi_id; +}; + struct vop2_err_event { u64 count; unsigned long begin; @@ -899,6 +923,7 @@ struct vop2 { struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; struct vop2_wb wb; struct drm_prop_enum_list *plane_name_list; + struct vop2_shared_mode_res shared_mode_res; bool is_iommu_enabled; bool is_iommu_needed; bool is_enabled; @@ -947,6 +972,7 @@ struct vop2 { unsigned long aclk_current_freq; enum rockchip_drm_vop_aclk_mode aclk_mode; bool merge_irq; + bool enable_reserved_plane; const struct vop2_data *data; /* Number of win that registered as plane, @@ -991,6 +1017,8 @@ struct vop2 { int irq; + int virtual_irq; + /* * Some globle resource are shared between all * the vidoe ports(crtcs), so we need a ref counter here. @@ -1223,6 +1251,17 @@ static inline bool is_vop3(struct vop2 *vop2) return true; } +static inline bool is_used_axi(struct vop2 *vop2, uint32_t axi_id) +{ + if (!vop2->shared_mode_res.shared_mode) + return true; + + if (vop2->shared_mode_res.axi_id == axi_id) + return true; + else + return false; +} + static inline bool vop2_is_dovi_mode(struct vop2_video_port *vp) { return vp->dovi_hdr_mode; @@ -1907,8 +1946,15 @@ static inline void rk3588_vop2_cfg_done(struct drm_crtc *crtc) val |= BIT(vp_data->splice_vp_id) | (BIT(vp_data->splice_vp_id) << 16); rockchip_drm_dbg(vop2->dev, VOP_DEBUG_CFG_DONE, "cfg_done: 0x%x\n", val); + if (vp->reserved_plane_phy_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { + val = vp->win_cfg_done_bits; + VOP_CTRL_SET(vop2, win_cfg_done, val); + VOP_CTRL_SET(vop2, wb_cfg_done, 1); + VOP_MODULE_SET(vop2, vp, sys_cfg_done, 1); + } else { + vop2_writel(vop2, 0, val); + } - vop2_writel(vop2, 0, val); } static inline void vop2_wb_cfg_done(struct vop2_video_port *vp) @@ -2179,6 +2225,8 @@ static void vop2_win_multi_area_disable(struct vop2_win *parent) static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) { struct vop2 *vop2 = win->vop2; + struct vop2_video_port *vp = NULL; + uint32_t vp_id; /* Disable the right splice win */ if (win->splice_win && !skip_splice_win) { @@ -2235,6 +2283,15 @@ static void vop2_win_disable(struct vop2_win *win, bool skip_splice_win) win->pd->vp_mask &= ~win->vp_mask; } } + + vp_id = ffs(win->vp_mask) - 1; + if (vp_id >= ROCKCHIP_MAX_CRTC) { + DRM_ERROR("Unsupported vp_id: %d\n", vp_id); + return; + } + vp = &vop2->vps[vp_id]; + if (vp->reserved_plane_phy_id != ROCKCHIP_VOP2_PHY_ID_INVALID) + vp->win_cfg_done_bits |= BIT(win->reg_done_bit); } if (win->left_win && win->splice_mode_right) { @@ -3297,7 +3354,7 @@ static enum vop_csc_format vop2_convert_csc_mode(enum drm_color_encoding color_e break; default: - DRM_ERROR("Unsuport color_encoding:%d\n", color_encoding); + DRM_ERROR("Unsupported color_encoding:%d\n", color_encoding); } return csc_mode; @@ -3487,6 +3544,23 @@ static void vop2_setup_csc_mode(struct vop2_video_port *vp, } } +static void vop2_axi_disable_irqs(struct vop2 *vop2) +{ + const struct vop2_data *vop2_data = vop2->data; + const struct vop_intr *intr; + uint32_t irqs = BUS_ERROR_INTR | MMU_EN_INTR | WB_UV_FIFO_FULL_INTR | + WB_YRGB_FIFO_FULL_INTR | WB_COMPLETE_INTR; + uint32_t i; + + for (i = 0; i < vop2_data->nr_axi_intr; i++) { + if (is_used_axi(vop2, i) == false) + continue; + intr = &vop2_data->axi_intr[i]; + VOP_INTR_SET_TYPE(vop2, intr, clear, irqs, 1); + VOP_INTR_SET_TYPE(vop2, intr, enable, irqs, 0); + } +} + static void vop2_axi_irqs_enable(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; @@ -3495,6 +3569,8 @@ static void vop2_axi_irqs_enable(struct vop2 *vop2) uint32_t i; for (i = 0; i < vop2_data->nr_axi_intr; i++) { + if (is_used_axi(vop2, i) == false) + continue; intr = &vop2_data->axi_intr[i]; VOP_INTR_SET_TYPE(vop2, intr, clear, irqs, 1); VOP_INTR_SET_TYPE(vop2, intr, enable, irqs, 1); @@ -4234,6 +4310,16 @@ static void vop2_attach_cubic_lut_prop(struct drm_crtc *crtc, unsigned int cubic drm_object_attach_property(&crtc->base, private->cubic_lut_size_prop, cubic_lut_size); } +static bool vop2_skip_shared_vp(struct vop2 *vop2, int id) +{ + return vop2->shared_mode_res.shared_mode && !(vop2->shared_mode_res.vp_mask & BIT(id)); +} + +static bool vop2_skip_shared_plane(struct vop2 *vop2, int id) +{ + return vop2->shared_mode_res.shared_mode && !(vop2->shared_mode_res.plane_mask & BIT(id)); +} + static void vop2_cubic_lut_init(struct vop2 *vop2) { const struct vop2_data *vop2_data = vop2->data; @@ -4243,6 +4329,8 @@ static void vop2_cubic_lut_init(struct vop2 *vop2) int i; for (i = 0; i < vop2_data->nr_vps; i++) { + if (vop2_skip_shared_vp(vop2, i)) + continue; vp = &vop2->vps[i]; crtc = &vp->rockchip_crtc.crtc; if (!crtc->dev) @@ -4627,8 +4715,14 @@ static void vop2_initial(struct drm_crtc *crtc) vop2_mask_write(vop2, 0x700, 0x3, 4, 0, 0, true); if (vop2->version == VOP_VERSION_RK3576) { - /* Default use rkiommu 2.0 for axi0 */ - VOP_CTRL_SET(vop2, rkmmu_v2_en, 1); + /* reserved plane mode will enable iommu bypass for rtos reserved plane display, + * but rkiommu 2.0 can't support iommu bypass function, so use rkiommu 1.0 + * at reserved plane mode by default, others will use rkiommu 2.0 by default. + */ + if (vop2->enable_reserved_plane) + VOP_CTRL_SET(vop2, rkmmu_v2_en, 0); + else /* Default use rkiommu 2.0 for axi0 */ + VOP_CTRL_SET(vop2, rkmmu_v2_en, 1); if (vop2->merge_irq == true) VOP_CTRL_SET(vop2, vp_intr_merge_en, 1); @@ -4756,6 +4850,8 @@ static void vop2_power_domain_off_by_disabled_vp(struct vop2_power_domain *pd) for (i = 0; i < win_num; i++) { phys_id = ffs(module_id_mask) - 1; module_id_mask &= ~BIT(phys_id); + if (vop2_skip_shared_plane(vop2, phys_id)) + continue; win = vop2_find_win_by_phys_id(vop2, phys_id); vp_id = ffs(win->vp_mask) - 1; @@ -4827,6 +4923,10 @@ static void vop2_power_off_all_pd(struct vop2 *vop2) { struct vop2_power_domain *pd, *n; + /* VOP sub PD will be always on and controlled by SCP */ + if (vop2->shared_mode_res.shared_mode) + return; + list_for_each_entry_safe_reverse(pd, n, &vop2->pd_list_head, list) { if (vop2_power_domain_status(pd)) vop2_power_domain_off_by_disabled_vp(pd); @@ -5251,6 +5351,9 @@ static void vop2_disable(struct drm_crtc *crtc) if (--vop2->enable_count > 0) return; + /* Disable axi irq when all vp is disabled */ + vop2_axi_disable_irqs(vop2); + /* * Reset AXI to get a clean state, which is conducive to recovering * from exceptions when enable at next time(such as iommu page fault) @@ -5675,6 +5778,19 @@ static void vop2_crtc_atomic_exit_psr(struct drm_crtc *crtc, struct drm_crtc_sta vop2_crtc_wins_switch_for_psr(crtc, true); } +static void vop2_crtc_disable_irqs(struct drm_crtc *crtc) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + const struct vop_intr *intr = vp_data->intr; + uint32_t irqs = POST_BUF_EMPTY_INTR | FS_FIELD_INTR | LINE_FLAG_INTR | LINE_FLAG1_INTR; + + VOP_INTR_SET_TYPE(vop2, intr, clear, irqs, 1); + VOP_INTR_SET_TYPE(vop2, intr, enable, irqs, 0); +} + static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -5820,6 +5936,7 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc, vop2_dsp_hold_valid_irq_disable(crtc); vop2_dovi_post_disable(crtc); + vop2_crtc_disable_irqs(crtc); vop2_disable(crtc); vop2->active_vp_mask &= ~BIT(vp->id); @@ -7050,6 +7167,7 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s VOP_CLUSTER_SET(vop2, win, frm_reset_en, 1); VOP_CLUSTER_SET(vop2, win, dma_stride_4k_disable, 1); } + vp->win_cfg_done_bits |= BIT(win->reg_done_bit); spin_unlock(&vop2->reg_lock); } @@ -12070,10 +12188,18 @@ static void vop3_setup_layer_sel_for_vp(struct vop2_video_port *vp, struct vop2_win *win; u32 layer_sel = 0; u8 layer_sel_id; - u8 layer_sel_none = 0xff; + u8 layer_sel_none = 0xf; int i; + int nr_layers = vop2->data->nr_layers; - for (i = 0; i < vop2->data->nr_layers; i++) { + if (vp->reserved_plane_phy_id != ROCKCHIP_VOP2_PHY_ID_INVALID) { + /* set reserved layer at the top layer */ + nr_layers -= 1; + win = vop2_find_win_by_phys_id(vop2, vp->reserved_plane_phy_id); + layer_sel = win->layer_sel_id[vp->id] << nr_layers * 4; + } + + for (i = 0; i < nr_layers; i++) { layer_sel_id = layer_sel_none; if (i < vp->nr_layers) { zpos = &vop2_zpos[i]; @@ -12107,9 +12233,9 @@ static void vop2_setup_dly_for_vp(struct vop2_video_port *vp) struct drm_crtc *crtc = &vp->rockchip_crtc.crtc; struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; - u16 hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; - u16 hdisplay = adjusted_mode->crtc_hdisplay; u32 bg_dly = vp_data->pre_scan_max_dly[0]; + u16 hsync_len; + u16 hdisplay; u32 pre_scan_dly; if (vp_data->hdr_table) { @@ -12134,9 +12260,9 @@ static void vop2_setup_dly_for_vp(struct vop2_video_port *vp) if (vp->splice_mode_right) { vcstate = to_rockchip_crtc_state(left_vp->rockchip_crtc.crtc.state); adjusted_mode = &left_vp->rockchip_crtc.crtc.state->adjusted_mode; - hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; - hdisplay = adjusted_mode->crtc_hdisplay; } + hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; + hdisplay = adjusted_mode->crtc_hdisplay; /* * splice mode: hdisplay must roundup as 4 pixel, @@ -12891,7 +13017,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; struct drm_plane *plane; - struct drm_plane_state *pstate, *pstate_max = NULL; + struct drm_plane_state *pstate, *max_yuv_pstate = NULL; struct vop2_plane_state *vpstate; struct post_csc_coef csc_coef = {}; struct post_csc_convert_mode convert_mode = {}; @@ -12899,6 +13025,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st bool acm_enable; bool post_r2y_en = false; bool post_csc_en = false; + bool rgb_limited_plane = false; int range_type; u64 max_yuv_plane = 0, plane_area; enum drm_color_encoding max_yuv_plane_color_encoding = DRM_COLOR_YCBCR_BT601; @@ -12910,13 +13037,17 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st vpstate = to_vop2_plane_state(pstate); dest = &vpstate->dest; + if (!pstate->fb->format->is_yuv && + pstate->color_range != DRM_COLOR_YCBCR_FULL_RANGE) + rgb_limited_plane = true; + if (pstate->fb->format->is_yuv) { plane_area = drm_rect_width(dest) * drm_rect_height(dest); /* find yuv plane with largest area */ if (max_yuv_plane < plane_area) { max_yuv_plane = plane_area; max_yuv_plane_color_encoding = pstate->color_encoding; - pstate_max = pstate; + max_yuv_pstate = pstate; } } } @@ -12951,36 +13082,49 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st if (is_yuv_output(vcstate->bus_format)) convert_mode.is_output_yuv = true; - if (!vcstate->yuv_overlay || vp->has_dci_enabled_win) + if (vp->has_dci_enabled_win) { convert_mode.is_input_full_range = true; - else if (vcstate->yuv_overlay) + } else if (!vcstate->yuv_overlay) { + /* if there are yuv planes, choose max plane's range */ + if (max_yuv_pstate) { + /* Todo RGB limit range plane */ + convert_mode.is_input_full_range = true; + } else { + if (rgb_limited_plane) + convert_mode.is_input_full_range = false; + else + convert_mode.is_input_full_range = true; + } + } else { + /* yuv overlay range is limited */ convert_mode.is_input_full_range = false; - else if (pstate_max) - convert_mode.is_input_full_range = - pstate_max->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; - else - convert_mode.is_input_full_range = - vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; + } convert_mode.is_output_full_range = vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH); - if (post_csc_en) { - convert_mode.output_color_encoding = vcstate->color_encoding; - /* - * When all layers are rgb, the post-csc input color encoding - * is fixed to rgb full, and the value of input_color_encoding - * has no actual utility. - * If there are any yuv planes, value of post-csc input_color_encoding - * selects the value of the yuv plane with the largest area. - */ - if (!pstate_max && !vcstate->yuv_overlay) - convert_mode.intput_color_encoding = vcstate->color_encoding; - else - convert_mode.intput_color_encoding = max_yuv_plane_color_encoding; + convert_mode.output_color_encoding = vcstate->color_encoding; + /* + * When all layers are rgb, the value of input_color_encoding + * has no actual utility, however, the plane csc only supports + * limited range under bt709. Therefore, in this scene, the colorspace + * of plane csc is selected as bt601. The intput_color_encoding + * is consistent with colorspace of plane csc, which is DRM_COLOR_YCBCR_BT601. + * If there are any yuv planes, value of post-csc input_color_encoding + * selects the value of the yuv plane with the largest area. + */ + if (!max_yuv_pstate) + convert_mode.intput_color_encoding = DRM_COLOR_YCBCR_BT601; + else + convert_mode.intput_color_encoding = max_yuv_plane_color_encoding; + if (convert_mode.intput_color_encoding != convert_mode.output_color_encoding || + convert_mode.is_input_full_range != convert_mode.is_output_full_range) + post_csc_en = true; + + if (post_csc_en) { rockchip_calc_post_csc(csc, &csc_coef, &convert_mode); VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00); @@ -13386,6 +13530,7 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_stat spin_lock_irqsave(&vop2->irq_lock, flags); vop2_wb_commit(crtc); vop2_cfg_done(crtc); + vp->win_cfg_done_bits = 0; if (vp->mcu_timing.mcu_pix_total) VOP_MODULE_SET(vop2, vp, mcu_hold_mode, 0); @@ -13493,6 +13638,8 @@ static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) drm_property_blob_get(vcstate->cubic_lut_data); if (vcstate->post_sharp_data) drm_property_blob_get(vcstate->post_sharp_data); + if (vcstate->dimming_data) + drm_property_blob_get(vcstate->dimming_data); __drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base); return &vcstate->base; @@ -13509,6 +13656,7 @@ static void vop2_crtc_destroy_state(struct drm_crtc *crtc, drm_property_blob_put(vcstate->post_csc_data); drm_property_blob_put(vcstate->cubic_lut_data); drm_property_blob_put(vcstate->post_sharp_data); + drm_property_blob_put(vcstate->dimming_data); kfree(vcstate); } @@ -13674,6 +13822,11 @@ static int vop2_crtc_atomic_get_property(struct drm_crtc *crtc, return 0; } + if (property == vp->reserved_plane_mask_prop) { + *val = BIT(vp->reserved_plane_phy_id); + return 0; + } + if (property == vp->hdr_ext_data_prop) { *val = vcstate->hdr_ext_data ? vcstate->hdr_ext_data->base.id : 0; return 0; @@ -13699,6 +13852,11 @@ static int vop2_crtc_atomic_get_property(struct drm_crtc *crtc, return 0; } + if (property == private->dimming_data_prop) { + *val = (vcstate->dimming_data) ? vcstate->dimming_data->base.id : 0; + return 0; + } + DRM_ERROR("failed to get vop2 crtc property: %s\n", property->name); return -EINVAL; @@ -13715,6 +13873,7 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, struct drm_mode_config *mode_config = &drm_dev->mode_config; struct vop2_video_port *vp = to_vop2_video_port(crtc); struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; bool replaced = false; int ret; @@ -13804,6 +13963,14 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, return 0; } + if (property == vp->reserved_plane_mask_prop) { + if (!val || hweight32(val) > 1 || !(val & vop2_data->plane_mask_base)) + vp->reserved_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; + else + vp->reserved_plane_phy_id = ilog2(val); + return 0; + } + if (property == vp->hdr_ext_data_prop) { ret = vop2_atomic_replace_property_blob_from_id(drm_dev, &vcstate->hdr_ext_data, @@ -13850,6 +14017,16 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, return ret; } + if (property == private->dimming_data_prop) { + ret = vop2_atomic_replace_property_blob_from_id(drm_dev, + &vcstate->dimming_data, + val, + -1, -1, + &replaced); + vcstate->dimming_changed |= replaced; + return ret; + } + DRM_ERROR("failed to set vop2 crtc property %s\n", property->name); return -EINVAL; @@ -14067,7 +14244,7 @@ static irqreturn_t vop2_isr(int irq, void *data) size_t vp_max = min_t(size_t, vop2_data->nr_vps, ROCKCHIP_MAX_CRTC); size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM); uint32_t vp_irqs[ROCKCHIP_MAX_CRTC]; - uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; + uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM] = {0}; uint32_t active_irqs; uint32_t wb_irqs; unsigned long flags; @@ -14102,8 +14279,11 @@ static irqreturn_t vop2_isr(int irq, void *data) spin_lock_irqsave(&vop2->irq_lock, flags); for (i = 0; i < vp_max; i++) vp_irqs[i] = vop2_read_and_clear_active_vp_irqs(vop2, i); - for (i = 0; i < axi_max; i++) + for (i = 0; i < axi_max; i++) { + if (is_used_axi(vop2, i) == false) + continue; axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i); + } wb_irqs = vop2_read_and_clear_wb_irqs(vop2); spin_unlock_irqrestore(&vop2->irq_lock, flags); @@ -14175,6 +14355,8 @@ static irqreturn_t vop2_isr(int irq, void *data) } for (i = 0; i < axi_max; i++) { + if (is_used_axi(vop2, i) == false) + continue; active_irqs = axi_irqs[i]; ERROR_HANDLER(BUS_ERROR); @@ -14199,11 +14381,14 @@ static irqreturn_t vop3_sys_isr(int irq, void *data) const struct vop2_data *vop2_data = vop2->data; int ret = IRQ_NONE; size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM); - uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; + uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM] = {0}; uint32_t wb_irqs, active_irqs; unsigned long flags; int i = 0; + if (vop2->shared_mode_res.shared_mode == ROCKCHIP_VOP2_SHARED_MODE_PRIMARY) + irq_set_irqchip_state(vop2->virtual_irq, IRQCHIP_STATE_PENDING, true); + #define SYS_ERROR_HANDLER(x) \ do { \ if (active_irqs & x##_INTR) {\ @@ -14231,8 +14416,11 @@ static irqreturn_t vop3_sys_isr(int irq, void *data) */ spin_lock_irqsave(&vop2->irq_lock, flags); wb_irqs = vop2_read_and_clear_wb_irqs(vop2); - for (i = 0; i < axi_max; i++) + for (i = 0; i < axi_max; i++) { + if (is_used_axi(vop2, i) == false) + continue; axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i); + } spin_unlock_irqrestore(&vop2->irq_lock, flags); if (wb_irqs) { @@ -14243,6 +14431,8 @@ static irqreturn_t vop3_sys_isr(int irq, void *data) } for (i = 0; i < axi_max; i++) { + if (is_used_axi(vop2, i) == false) + continue; active_irqs = axi_irqs[i]; SYS_ERROR_HANDLER(BUS_ERROR); @@ -14436,6 +14626,23 @@ static u32 vop3_esmart_linebuffer_size(struct vop2 *vop2, struct vop2_win *win) return vop2->data->max_output.width; } +static int rk3576_shared_mode_esmart_scale_engine(int phy_id) +{ + switch (phy_id) { + case ROCKCHIP_VOP2_ESMART0: + return 0; + case ROCKCHIP_VOP2_ESMART1: + return 1; + case ROCKCHIP_VOP2_ESMART2: + return 2; + case ROCKCHIP_VOP2_ESMART3: + return 3; + default: + DRM_ERROR("Unsupported phy_id:%d\n", phy_id); + return 0; + } +} + static void vop3_init_esmart_scale_engine(struct vop2 *vop2) { u8 scale_engine_num = 0; @@ -14447,7 +14654,10 @@ static void vop3_init_esmart_scale_engine(struct vop2 *vop2) if (win->parent || vop2_cluster_window(win)) continue; - win->scale_engine_num = scale_engine_num++; + if (vop2->shared_mode_res.shared_mode) + win->scale_engine_num = rk3576_shared_mode_esmart_scale_engine(win->phys_id); + else + win->scale_engine_num = scale_engine_num++; } } @@ -14634,6 +14844,8 @@ static int vop2_gamma_init(struct vop2 *vop2) return 0; for (i = 0; i < vop2_data->nr_vps; i++) { + if (vop2_skip_shared_vp(vop2, i)) + continue; vp = &vop2->vps[i]; crtc = &vp->rockchip_crtc.crtc; if (!crtc->dev) @@ -14673,6 +14885,38 @@ static int vop2_gamma_init(struct vop2 *vop2) return 0; } +static int vop2_crtc_create_reserved_plane_mask_property(struct vop2 *vop2, + struct drm_crtc *crtc) +{ + struct drm_property *prop; + struct vop2_video_port *vp = to_vop2_video_port(crtc); + + static const struct drm_prop_enum_list props[] = { + { ROCKCHIP_VOP2_CLUSTER0, "Cluster0" }, + { ROCKCHIP_VOP2_CLUSTER1, "Cluster1" }, + { ROCKCHIP_VOP2_ESMART0, "Esmart0" }, + { ROCKCHIP_VOP2_ESMART1, "Esmart1" }, + { ROCKCHIP_VOP2_SMART0, "Smart0" }, + { ROCKCHIP_VOP2_SMART1, "Smart1" }, + { ROCKCHIP_VOP2_CLUSTER2, "Cluster2" }, + { ROCKCHIP_VOP2_CLUSTER3, "Cluster3" }, + { ROCKCHIP_VOP2_ESMART2, "Esmart2" }, + { ROCKCHIP_VOP2_ESMART3, "Esmart3" }, + }; + + prop = drm_property_create_bitmask(vop2->drm_dev, 0, "RESERVED_PLANE_MASK", + props, ARRAY_SIZE(props), 0xffffffff); + if (!prop) { + DRM_DEV_ERROR(vop2->dev, "create reserved_plane_mask prop for vp%d failed\n", vp->id); + return -ENOMEM; + } + + vp->reserved_plane_mask_prop = prop; + drm_object_attach_property(&crtc->base, vp->reserved_plane_mask_prop, BIT(vp->reserved_plane_phy_id)); + + return 0; +} + static int vop2_crtc_create_plane_mask_property(struct vop2 *vop2, struct drm_crtc *crtc, uint32_t plane_mask) @@ -14899,6 +15143,8 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) * initial all the vp. */ for (i = 0; i < vop2_data->nr_vps; i++) { + if (vop2_skip_shared_vp(vop2, i)) + continue; vp = &vop2->vps[i]; if (vp->plane_mask) { bootloader_initialized = true; @@ -14921,6 +15167,8 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) primary = NULL; cursor = NULL; + if (vop2_skip_shared_vp(vop2, i)) + continue; /* * make sure that the vp to be registered has at least one connector. */ @@ -15100,6 +15348,7 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) drm_object_attach_property(&crtc->base, private->aclk_prop, 0); drm_object_attach_property(&crtc->base, private->bg_prop, 0); drm_object_attach_property(&crtc->base, private->line_flag_prop, 0); + drm_object_attach_property(&crtc->base, private->dimming_data_prop, 0); if (vp_data->feature & VOP_FEATURE_OVERSCAN) { drm_object_attach_property(&crtc->base, drm_dev->mode_config.tv_left_margin_property, 100); @@ -15117,6 +15366,10 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) */ if (plane_mask && !is_vop3(vop2)) vop2_crtc_create_plane_mask_property(vop2, crtc, plane_mask); + + if (vp->reserved_plane_phy_id != ROCKCHIP_VOP2_PHY_ID_INVALID) + vop2_crtc_create_reserved_plane_mask_property(vop2, crtc); + vop2_crtc_create_feature_property(vop2, crtc); vop2_crtc_create_vrr_property(vop2, crtc); @@ -15315,6 +15568,8 @@ static int vop2_win_init(struct vop2 *vop2) for (i = 0; i < vop2_data->win_size; i++) { const struct vop2_win_data *win_data = &vop2_data->win[i]; + if (vop2_skip_shared_plane(vop2, win_data->phys_id)) + continue; win = &vop2->win[num_wins]; win->name = win_data->name; win->regs = win_data->regs; @@ -15346,6 +15601,7 @@ static int vop2_win_init(struct vop2 *vop2) win->axi_yrgb_id = win_data->axi_yrgb_id; win->axi_uv_id = win_data->axi_uv_id; win->possible_vp_mask = win_data->possible_vp_mask; + win->reg_done_bit = win_data->reg_done_bit; if (win_data->pd_id) win->pd = vop2_find_pd_by_id(vop2, win_data->pd_id); @@ -15502,7 +15758,7 @@ static bool vop2_plane_mask_check(struct vop2 *vop2) struct vop2_video_port *vp; struct vop2_win *win; char *full_plane, *current_plane; - u32 full_plane_mask = 0, plane_mask = 0; + u32 full_plane_mask = 0, plane_mask = 0, plane_mask_base = 0; u32 phys_id; u32 nr_planes; int primary_plane_id; @@ -15568,8 +15824,13 @@ static bool vop2_plane_mask_check(struct vop2 *vop2) if (is_vop3(vop2) && !full_plane_mask) return true; - if (full_plane_mask != vop2_data->plane_mask_base) { - full_plane = vop2_plane_mask_to_string(vop2_data->plane_mask_base); + if (vop2->shared_mode_res.shared_mode) + plane_mask_base = vop2->shared_mode_res.plane_mask; + else + plane_mask_base = vop2_data->plane_mask_base; + + if (full_plane_mask != plane_mask_base) { + full_plane = vop2_plane_mask_to_string(plane_mask_base); current_plane = vop2_plane_mask_to_string(plane_mask); DRM_WARN("all windows should be assigned, full plane mask: %s[0x%x], current plane mask: %s[0x%x]\n", full_plane, vop2_data->plane_mask_base, current_plane, plane_mask); @@ -15957,6 +16218,27 @@ static void vop2_of_get_dsp_lut(struct vop2 *vop2, struct device_node *vp_node, } } +static void vop2_parse_shared_mode_resources(struct vop2 *vop2) +{ + struct device *dev = vop2->dev; + + of_property_read_u32(dev->of_node, "rockchip,shared-mode", + &vop2->shared_mode_res.shared_mode); + if (vop2->shared_mode_res.shared_mode) { + of_property_read_u32(dev->of_node, "rockchip,shared-mode-axi-id", + &vop2->shared_mode_res.axi_id); + of_property_read_u32(dev->of_node, "rockchip,shared-mode-vp-mask", + &vop2->shared_mode_res.vp_mask); + of_property_read_u32(dev->of_node, "rockchip,shared-mode-plane-mask", + &vop2->shared_mode_res.plane_mask); + DRM_DEV_INFO(dev, "Enable shared mode[%d], use axi%d, vp mask:0x%x, plane-mask:0x%x\n", + vop2->shared_mode_res.shared_mode, + vop2->shared_mode_res.axi_id, + vop2->shared_mode_res.vp_mask, + vop2->shared_mode_res.plane_mask); + } +} + static int vop2_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -16007,6 +16289,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) vop2->version == VOP_VERSION_RK3588; dev_set_drvdata(dev, vop2); + vop2_parse_shared_mode_resources(vop2); vop2->support_multi_area = of_property_read_bool(dev->of_node, "support-multi-area"); vop2->disable_afbc_win = of_property_read_bool(dev->of_node, "disable-afbc-win"); @@ -16158,6 +16441,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) for_each_child_of_node(vop_out_node, child) { u32 plane_mask = 0; u32 primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; + u32 reserved_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; u32 vp_id = 0; u32 val = 0; @@ -16165,12 +16449,19 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) of_property_read_u32(child, "rockchip,primary-plane", &primary_plane_phy_id); of_property_read_u32(child, "reg", &vp_id); + if (vop2_skip_shared_vp(vop2, vp_id)) + continue; vop2->vps[vp_id].plane_mask = plane_mask; if (plane_mask) vop2->vps[vp_id].primary_plane_phy_id = primary_plane_phy_id; else vop2->vps[vp_id].primary_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; - + if (!of_property_read_u32(child, "rockchip,reserved-plane", &reserved_plane_phy_id)) { + vop2->vps[vp_id].reserved_plane_phy_id = reserved_plane_phy_id; + vop2->enable_reserved_plane = true; + } else { + vop2->vps[vp_id].reserved_plane_phy_id = ROCKCHIP_VOP2_PHY_ID_INVALID; + } vop2->vps[vp_id].xmirror_en = of_property_read_bool(child, "xmirror-enable"); ret = of_clk_set_defaults(child, false); @@ -16210,6 +16501,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) } for (i = 0; i < vop2->data->nr_vps; i++) { + if (vop2_skip_shared_vp(vop2, i)) + continue; plane_mask_string = vop2_plane_mask_to_string(vop2->vps[i].plane_mask); DRM_DEV_INFO(dev, "vp%d assign plane mask: %s[0x%x], primary plane phy id: %s[%d]\n", i, plane_mask_string, vop2->vps[i].plane_mask, @@ -16261,6 +16554,14 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; + if (vop2->shared_mode_res.shared_mode == ROCKCHIP_VOP2_SHARED_MODE_PRIMARY) { + vop2->virtual_irq = platform_get_irq_byname(pdev, "vop-virtual-irq"); + if (vop2->virtual_irq < 0) { + DRM_DEV_ERROR(dev, "cannot find vop2 virtual_irq: %d\n", vop2->virtual_irq); + return vop2->virtual_irq; + } + } + if (vop2->merge_irq == false) { struct drm_crtc *crtc; char irq_name[12]; @@ -16268,6 +16569,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) drm_for_each_crtc(crtc, drm_dev) { struct vop2_video_port *vp = to_vop2_video_port(crtc); + if (vop2_skip_shared_vp(vop2, vp->id)) + continue; snprintf(irq_name, sizeof(irq_name), "vop-vp%d", vp->id); vp->irq = platform_get_irq_byname(pdev, irq_name); diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 7b1397503805..c9e80fae4827 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -431,13 +431,12 @@ static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) drm_panel_unprepare(lvds->panel); } -static int rockchip_lvds_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_lvds_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_lvds *lvds = encoder_to_lvds(encoder); + struct rockchip_lvds *lvds = container_of(sub_dev, struct rockchip_lvds, sub_dev); if (lvds->panel) - panel_simple_loader_protect(lvds->panel); + rockchip_drm_panel_loader_protect(lvds->panel, on); if (on) { diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 86a53924a7c9..de46f441b323 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -144,6 +144,7 @@ struct rockchip_rgb { u8 id; u32 max_dclk_rate; u32 mcu_pix_total; + int data_map_mode; struct device *dev; struct device_node *np_mcu_panel; struct drm_panel *panel; @@ -391,6 +392,7 @@ rockchip_rgb_encoder_atomic_check(struct drm_encoder *encoder, break; } + s->data_map_mode = rgb->data_map_mode; s->output_type = DRM_MODE_CONNECTOR_DPI; s->bus_flags = info->bus_flags; s->tv_state = &conn_state->tv; @@ -401,10 +403,9 @@ rockchip_rgb_encoder_atomic_check(struct drm_encoder *encoder, return 0; } -static int rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, - bool on) +static int rockchip_rgb_encoder_loader_protect(struct rockchip_drm_sub_dev *sub_dev, bool on) { - struct rockchip_rgb *rgb = encoder_to_rgb(encoder); + struct rockchip_rgb *rgb = container_of(sub_dev, struct rockchip_rgb, sub_dev); if (rgb->np_mcu_panel) { struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(rgb->panel); @@ -416,7 +417,7 @@ static int rockchip_rgb_encoder_loader_protect(struct drm_encoder *encoder, } if (rgb->panel) - panel_simple_loader_protect(rgb->panel); + rockchip_drm_panel_loader_protect(rgb->panel, on); if (on) { phy_init(rgb->phy); @@ -1060,6 +1061,10 @@ static int rockchip_rgb_probe(struct platform_device *pdev) id = 0; rgb->data_sync_bypass = of_property_read_bool(dev->of_node, "rockchip,data-sync-bypass"); + if (of_property_read_u32(dev->of_node, "rockchip,data-map-mode", &rgb->data_map_mode)) + rgb->data_map_mode = -1; + if (rgb->data_map_mode < 0 || rgb->data_map_mode > 3) + rgb->data_map_mode = -1; fwnode_mcu_panel = device_get_named_child_node(dev, "mcu-panel"); if (fwnode_mcu_panel) { diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index f7dd32ef8770..b34820aef8c1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -1022,7 +1022,8 @@ static const struct vop2_wb_data rk3576_vop_wb_data = { }; static const struct vop2_video_port_regs rk3528_vop_vp0_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 0), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 4), .overlay_mode = VOP_REG(RK3528_OVL_PORT0_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0), @@ -1100,7 +1101,8 @@ static const struct vop2_video_port_regs rk3528_vop_vp0_regs = { }; static const struct vop2_video_port_regs rk3528_vop_vp1_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 1), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 5), .overlay_mode = VOP_REG(RK3528_OVL_PORT1_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0), @@ -1236,7 +1238,8 @@ static const struct vop2_video_port_data rk3528_vop_video_ports[] = { }; static const struct vop2_video_port_regs rk3562_vop_vp0_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 0), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 4), .overlay_mode = VOP_REG(RK3528_OVL_PORT0_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0), @@ -1326,6 +1329,7 @@ static const struct vop2_video_port_data rk3562_vop_video_ports[] = { static const struct vop2_video_port_regs rk3568_vop_vp0_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .sys_cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 4), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0x3fffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 0), @@ -1413,6 +1417,7 @@ static const struct vop2_video_port_regs rk3568_vop_vp0_regs = { static const struct vop2_video_port_regs rk3568_vop_vp1_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1), + .sys_cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 5), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 1), .dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0x3fffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 4), @@ -1467,6 +1472,7 @@ static const struct vop2_video_port_regs rk3568_vop_vp1_regs = { static const struct vop2_video_port_regs rk3568_vop_vp2_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2), + .sys_cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 6), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 2), .dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0x3fffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 8), @@ -1559,7 +1565,8 @@ static const struct vop2_video_port_data rk3568_vop_video_ports[] = { }; static const struct vop2_video_port_regs rk3576_vop_vp0_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 0), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 4), .overlay_mode = VOP_REG(RK3528_OVL_PORT0_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0), @@ -1678,7 +1685,8 @@ static const struct vop2_video_port_regs rk3576_vop_vp0_regs = { }; static const struct vop2_video_port_regs rk3576_vop_vp1_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 1), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 5), .overlay_mode = VOP_REG(RK3528_OVL_PORT1_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0), @@ -1769,7 +1777,8 @@ static const struct vop2_video_port_regs rk3576_vop_vp1_regs = { }; static const struct vop2_video_port_regs rk3576_vop_vp2_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 2), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 6), .overlay_mode = VOP_REG(RK3576_OVL_PORT2_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0xffffffff, 0), .out_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0xf, 0), @@ -1935,7 +1944,8 @@ static const struct vop2_video_port_data rk3576_vop_video_ports[] = { }; static const struct vop2_video_port_regs rk3588_vop_vp0_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 0), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 4), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0), .dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0xffffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 0), @@ -2040,7 +2050,8 @@ static const struct vop2_video_port_regs rk3588_vop_vp0_regs = { * same eotf curve with VP1. */ static const struct vop2_video_port_regs rk3588_vop_vp1_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 1), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 5), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 1), .dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0xffffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 4), @@ -2132,7 +2143,8 @@ static const struct vop2_video_port_regs rk3588_vop_vp1_regs = { }; static const struct vop2_video_port_regs rk3588_vop_vp2_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 2), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 6), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 2), .dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0xffffffff, 0), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 8), @@ -2195,7 +2207,8 @@ static const struct vop2_video_port_regs rk3588_vop_vp2_regs = { }; static const struct vop2_video_port_regs rk3588_vop_vp3_regs = { - .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 3), + .cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 3), + .sys_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 7), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 3), .port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 12), .dsp_background = VOP_REG(RK3588_VP3_DSP_BG, 0xffffffff, 0), @@ -3143,6 +3156,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x06, .axi_uv_id = 0x07, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 4, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3172,6 +3186,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x08, .axi_uv_id = 0x09, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 5, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3201,6 +3216,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x0a, .axi_uv_id = 0x0b, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1), + .reg_done_bit = 6, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3230,6 +3246,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x0c, .axi_uv_id = 0x0d, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP1), + .reg_done_bit = 7, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3256,6 +3273,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x02, .axi_uv_id = 0x03, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 0, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 27, 21 }, @@ -3282,6 +3300,7 @@ static const struct vop2_win_data rk3528_vop_win_data[] = { .axi_yrgb_id = 0x04, .axi_uv_id = 0x05, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 0, .max_upscale_factor = 8, .max_downscale_factor = 8, .type = DRM_PLANE_TYPE_OVERLAY, @@ -3325,6 +3344,7 @@ static const struct vop2_win_data rk3562_vop_win_data[] = { .axi_yrgb_id = 0x02, .axi_uv_id = 0x03, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 4, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3352,6 +3372,7 @@ static const struct vop2_win_data rk3562_vop_win_data[] = { .axi_yrgb_id = 0x04, .axi_uv_id = 0x05, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 5, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3379,6 +3400,7 @@ static const struct vop2_win_data rk3562_vop_win_data[] = { .axi_yrgb_id = 0x06, .axi_uv_id = 0x07, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 6, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3406,6 +3428,7 @@ static const struct vop2_win_data rk3562_vop_win_data[] = { .axi_yrgb_id = 0x08, .axi_uv_id = 0x0d, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0), + .reg_done_bit = 7, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 27, 45, 48 }, @@ -3801,6 +3824,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x10, .axi_uv_id = 0x11, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP2), + .reg_done_bit = 4, .max_upscale_factor = 8, .max_downscale_factor = 8, .feature = WIN_FEATURE_MULTI_AREA | WIN_FEATURE_Y2R_13BIT_DEPTH, @@ -3830,6 +3854,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x12, .axi_uv_id = 0x13, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2), + .reg_done_bit = 5, .max_upscale_factor = 8, .max_downscale_factor = 8, .feature = WIN_FEATURE_MULTI_AREA, @@ -3859,6 +3884,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x0a, .axi_uv_id = 0x0b, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP2), + .reg_done_bit = 6, .max_upscale_factor = 8, .max_downscale_factor = 8, .feature = WIN_FEATURE_MULTI_AREA, @@ -3888,6 +3914,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x0c, .axi_uv_id = 0x0d, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2), + .reg_done_bit = 7, .max_upscale_factor = 8, .max_downscale_factor = 8, .feature = WIN_FEATURE_MULTI_AREA, @@ -3914,6 +3941,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_uv_id = 0x0b, .dci_rid_id = 0x4,/* dci axi id length is 4 bits */ .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1), + .reg_done_bit = 0, .max_upscale_factor = 8, .max_downscale_factor = 8, .type = DRM_PLANE_TYPE_OVERLAY, @@ -3940,6 +3968,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x0c, .axi_uv_id = 0x0d, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1), + .reg_done_bit = 0, .max_upscale_factor = 8, .max_downscale_factor = 8, .type = DRM_PLANE_TYPE_OVERLAY, @@ -3966,6 +3995,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x06, .axi_uv_id = 0x07, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1),/* vp0 or vp1 */ + .reg_done_bit = 1, .max_upscale_factor = 8, .max_downscale_factor = 8, .type = DRM_PLANE_TYPE_OVERLAY, @@ -3991,6 +4021,7 @@ static const struct vop2_win_data rk3576_vop_win_data[] = { .axi_yrgb_id = 0x08, .axi_uv_id = 0x09, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1),/* vp0 or vp1 */ + .reg_done_bit = 1, .max_upscale_factor = 8, .max_downscale_factor = 8, .type = DRM_PLANE_TYPE_OVERLAY, @@ -4288,6 +4319,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 3, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 0, .max_upscale_factor = 4, .max_downscale_factor = 4, .dly = { 4, 26, 29, 4, 35, 3, 5 }, @@ -4314,6 +4346,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 5, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 0, .max_upscale_factor = 4, .max_downscale_factor = 4, .type = DRM_PLANE_TYPE_OVERLAY, @@ -4342,6 +4375,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .type = DRM_PLANE_TYPE_OVERLAY, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 1, .max_upscale_factor = 4, .max_downscale_factor = 4, .dly = { 4, 26, 29, 4, 35, 3, 5 }, @@ -4368,6 +4402,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 9, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 1, .max_upscale_factor = 4, .max_downscale_factor = 4, .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB, @@ -4396,6 +4431,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 3, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 2, .max_upscale_factor = 4, .max_downscale_factor = 4, .dly = { 4, 26, 29, 4, 35, 3, 5 }, @@ -4422,6 +4458,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 5, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 2, .max_upscale_factor = 4, .max_downscale_factor = 4, .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB, @@ -4449,6 +4486,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 7, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 3, .max_upscale_factor = 4, .max_downscale_factor = 4, .dly = { 4, 26, 29, 4, 35, 3, 5 }, @@ -4475,6 +4513,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 9, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 3, .max_upscale_factor = 4, .max_downscale_factor = 4, .feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB, @@ -4503,6 +4542,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 0x0b, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 4, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 23, 45, 48, 23, 54, 22, 24 }, @@ -4533,6 +4573,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 0x0b, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 6, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 23, 45, 48, 23, 54, 22, 24 }, @@ -4562,6 +4603,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 0x01, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 5, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 23, 45, 48, 23, 54, 22, 24 }, @@ -4591,6 +4633,7 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { .axi_uv_id = 0x0d, .possible_vp_mask = BIT(ROCKCHIP_VOP_VP0) | BIT(ROCKCHIP_VOP_VP1) | BIT(ROCKCHIP_VOP_VP2) | BIT(ROCKCHIP_VOP_VP3), + .reg_done_bit = 7, .max_upscale_factor = 8, .max_downscale_factor = 8, .dly = { 23, 45, 48, 23, 54, 22, 24 }, @@ -4599,8 +4642,9 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { }; static const struct vop2_ctrl rk3528_vop_ctrl = { - .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), + .cfg_done_en = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 15), .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), + .win_cfg_done = VOP_REG_MASK(RK3588_SYS_WIN_REG_CFG_DONE, 0xffffffff, 0), .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), .aclk_pre_auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 7), .if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28), @@ -4638,6 +4682,7 @@ static const struct vop_grf_ctrl rk3562_sys_grf_ctrl = { static const struct vop2_ctrl rk3562_vop_ctrl = { .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), + .win_cfg_done = VOP_REG_MASK(RK3588_SYS_WIN_REG_CFG_DONE, 0xffffffff, 0), .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), .aclk_pre_auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 7), .if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28), @@ -4748,6 +4793,7 @@ static const struct vop2_ctrl rk3576_vop_ctrl = { .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), .reg_done_frm = VOP_REG_MASK(RK3576_SYS_PORT_CTRL_IMD, 0x7, 0), .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), + .win_cfg_done = VOP_REG_MASK(RK3588_SYS_WIN_REG_CFG_DONE, 0xffffffff, 0), .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), .aclk_pre_auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 7), .version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16), @@ -4882,6 +4928,7 @@ static const struct vop_grf_ctrl rk3588_vo1_grf_ctrl = { static const struct vop2_ctrl rk3588_vop_ctrl = { .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), + .win_cfg_done = VOP_REG_MASK(RK3588_SYS_WIN_REG_CFG_DONE, 0xffffffff, 0), .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), .dma_finish_mode = VOP_REG(RK3588_SYS_VAR_FREQ_CTRL, 0x3, 0), .axi_dma_finish_and_en = VOP_REG(RK3588_SYS_VAR_FREQ_CTRL, 0x1, 2), diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 1c2841d91ea8..707488a8c417 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -323,6 +323,10 @@ static const struct vop_ctrl rk3288_ctrl_data = { .mipi_dclk_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0x1, 31, 3, 2, -1), .mipi_pin_pol = VOP_REG_VER(RK3368_DSP_CTRL1, 0x7, 28, 3, 2, -1), + .edpi_wms_fs = VOP_REG(RK3288_SYS_CTRL, 0x1, 10), + .edpi_ctrl_mode = VOP_REG(RK3288_SYS_CTRL, 0x1, 9), + .edpi_te_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 8), + .dither_down_sel = VOP_REG(RK3288_DSP_CTRL1, 0x1, 4), .dither_down_mode = VOP_REG(RK3288_DSP_CTRL1, 0x1, 3), .dither_down_en = VOP_REG(RK3288_DSP_CTRL1, 0x1, 2), @@ -1629,6 +1633,10 @@ static const struct vop_ctrl px30_ctrl_data = { .mcu_type = VOP_REG(RK3366_LIT_MCU_CTRL, 0x1, 31), .mcu_rw_bypass_port = VOP_REG(RK3366_LIT_MCU_RW_BYPASS_PORT, 0xffffffff, 0), + + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), }; static const struct vop_win_phy px30_win23_data = { @@ -1878,6 +1886,10 @@ static const struct vop_ctrl rv1126_ctrl_data = { 0xffffffff, 0), .bt1120_yc_swap = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 30), .bt1120_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 31), + + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), }; static const struct vop_win_data rv1126_vop_win_data[] = { @@ -1932,6 +1944,9 @@ static const struct vop_ctrl rv1126b_ctrl_data = { .standby = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 1), .dsp_outzero = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 3), .yuv_clip = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 4), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), .global_regdone_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 13), .rgb_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 0), @@ -1946,6 +1961,9 @@ static const struct vop_ctrl rv1126b_ctrl_data = { .bt656_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 6), .mcu_force_rdn = VOP_REG(RV1126B_DSP_CTRL1, 0x1, 21), + .mcu_data_map_mode = VOP_REG(RV1126B_DSP_CTRL1, 0x1, 20), + .bt1120_data_map_mode = VOP_REG(RV1126B_DSP_CTRL1, 0x3, 18), + .bt656_data_map_mode = VOP_REG(RV1126B_DSP_CTRL1, 0x3, 16), .dsp_interlace = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 0), .dither_up_en = VOP_REG(RK3366_LIT_DSP_CTRL2, 0x1, 2), @@ -2156,6 +2174,9 @@ static const struct vop_ctrl rk3506_ctrl_data = { .standby = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 1), .dsp_outzero = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 3), .yuv_clip = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 4), + .edpi_te_en = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 9), + .edpi_ctrl_mode = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 10), + .edpi_wms_fs = VOP_REG(RK3366_LIT_SYS_CTRL2, 0x1, 11), .rgb_en = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x1, 0), .rgb_pin_pol = VOP_REG(RK3366_LIT_DSP_CTRL0, 0x7, 2), diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index fa58867b243e..0e92d434aa64 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1064,6 +1064,7 @@ #define RK3568_VOP2_GLB_CFG_DONE_EN BIT(15) #define RK3568_VERSION_INFO 0x004 #define RK3568_SYS_AUTO_GATING_CTRL 0x008 +#define RK3588_SYS_WIN_REG_CFG_DONE 0x00c #define RK3576_SYS_AXI_HURRY_CTRL0_IMD 0x014 #define RK3576_SYS_AXI_HURRY_CTRL1_IMD 0x018 #define RK3576_SYS_MMU_CTRL_IMD 0x020 diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 3e2b3737401a..135fc4248847 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -639,7 +639,11 @@ static void rk3x_i2c_start_fifo(struct rk3x_i2c *i2c) } /* enable adapter with correct mode, send START condition */ - val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START | REG_CON_CLEAN_DMA; + val |= REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START; + + /* if supports DMA, make sure clean DMA states for current transfer */ + if (i2c->dma_tx && i2c->dma_rx) + val |= REG_CON_CLEAN_DMA; /* if we want to react to NACK, set ACTACK bit */ if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) @@ -2119,11 +2123,7 @@ static int __init rk3x_i2c_driver_init(void) { return platform_driver_register(&rk3x_i2c_driver); } -#ifdef CONFIG_INITCALL_ASYNC -subsys_initcall_sync(rk3x_i2c_driver_init); -#else subsys_initcall(rk3x_i2c_driver_init); -#endif static void __exit rk3x_i2c_driver_exit(void) { diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index dfbe2ee4998b..77c36ee6fb96 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -497,6 +497,9 @@ config TOUCHSCREEN_HYNITRON_CSTXXX To compile this driver as a module, choose M here: the module will be called hynitron-cstxxx. +config TOUCHSCREEN_HYN + tristate "HYN touchscreens support" + config TOUCHSCREEN_ILI210X tristate "Ilitek ILI210X based touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 701bc1952e4b..bde1f93a057b 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_TOUCHSCREEN_GT1X) += gt1x/ obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o +obj-$(CONFIG_TOUCHSCREEN_HYN) += hyn/ obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o obj-$(CONFIG_TOUCHSCREEN_IMAGIS) += imagis.o diff --git a/drivers/input/touchscreen/gt1x/gt1x.c b/drivers/input/touchscreen/gt1x/gt1x.c index 6c98bf0d5b3f..cf4ec401e31c 100644 --- a/drivers/input/touchscreen/gt1x/gt1x.c +++ b/drivers/input/touchscreen/gt1x/gt1x.c @@ -52,7 +52,7 @@ s32 gt1x_i2c_write(u16 addr, u8 *buffer, s32 len) .flags = 0, .addr = gt1x_i2c_client->addr, }; - return _do_i2c_write(&msg, addr, buffer, len); + return gt1x_do_i2c_write(&msg, addr, buffer, len); } /** @@ -75,7 +75,7 @@ s32 gt1x_i2c_read(u16 addr, u8 *buffer, s32 len) .addr = gt1x_i2c_client->addr, .flags = I2C_M_RD} }; - return _do_i2c_read(msgs, addr, buffer, len); + return gt1x_do_i2c_read(msgs, addr, buffer, len); } static spinlock_t irq_lock; @@ -219,7 +219,7 @@ static void gt1x_ts_work_func(struct work_struct *work) s32 ret = 0; u8 point_data[11] = { 0 }; - if (update_info.status) { + if (gt1x_update_info.status) { GTP_DEBUG("Ignore interrupts during fw update."); return; } @@ -795,7 +795,9 @@ static struct i2c_driver gt1x_ts_driver = { #if !defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM) .pm = >1x_ts_pm_ops, #endif +#if !IS_REACHABLE(CONFIG_TOUCHSCREEN_HYN) .probe_type = PROBE_PREFER_ASYNCHRONOUS, +#endif }, }; diff --git a/drivers/input/touchscreen/gt1x/gt1x_extents.c b/drivers/input/touchscreen/gt1x/gt1x_extents.c index ed087d8f0031..f0e91766372d 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_extents.c +++ b/drivers/input/touchscreen/gt1x/gt1x_extents.c @@ -668,7 +668,7 @@ static long gt1x_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int cnt = 30; /* Blocking when firmwaer updating */ - while (cnt-- && update_info.status) { + while (cnt-- && gt1x_update_info.status) { ssleep(1); } /*GTP_DEBUG("IOCTL CMD:%x", cmd);*/ diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.c b/drivers/input/touchscreen/gt1x/gt1x_generic.c index 3840444c0131..bd31f00811a5 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.c +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.c @@ -260,7 +260,7 @@ static ssize_t gt1x_debug_write_proc(struct file *file, const char *buffer, size } if (strcmp(mode_str, "force_update") == 0) { - update_info.force_update = !!mode; + gt1x_update_info.force_update = !!mode; } return gt1x_debug_proc(buf, count); } @@ -360,7 +360,7 @@ parse_cfg_fail1: } #endif -s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) +s32 gt1x_do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) { s32 ret = -1; s32 pos = 0; @@ -400,7 +400,7 @@ s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len) return 0; } -s32 _do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len) +s32 gt1x_do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len) { s32 ret = -1; s32 pos = 0; @@ -519,7 +519,7 @@ s32 gt1x_send_cfg(u8 *config, int cfg_len) s32 retry = 0; u16 checksum = 0; - if (update_info.status) { + if (gt1x_update_info.status) { GTP_DEBUG("Ignore cfg during fw update."); return -1; } @@ -1046,7 +1046,7 @@ void gt1x_power_reset(void) static int rst_flag; s32 i = 0; - if (rst_flag || update_info.status) { + if (rst_flag || gt1x_update_info.status) { return; } GTP_INFO("force_reset_guitar"); @@ -2169,7 +2169,7 @@ int gt1x_suspend(void) u8 buf[1] = { 0 }; #endif - if (update_info.status) { + if (gt1x_update_info.status) { return 0; } #if GTP_SMART_COVER @@ -2238,7 +2238,7 @@ int gt1x_resume(void) { s32 ret = -1; - if (update_info.status) { + if (gt1x_update_info.status) { return 0; } @@ -2354,18 +2354,21 @@ s32 gt1x_init(void) ret = gt1x_get_chip_type(); if (ret != 0) { GTP_ERROR("Get chip type failed!"); + goto init_err; } /* read version information */ ret = gt1x_read_version(>1x_version); if (ret != 0) { GTP_ERROR("Get verision failed!"); + goto init_err; } /* init and send configs */ ret = gt1x_init_panel(); if (ret != 0) { GTP_ERROR("Init panel failed."); + goto init_err; } gt1x_workqueue = create_singlethread_workqueue("gt1x_workthread"); @@ -2403,6 +2406,8 @@ s32 gt1x_init(void) #if GTP_WITH_STYLUS gt1x_pen_init(); #endif + +init_err: if (ret != 0) gt1x_power_switch(SWITCH_OFF); diff --git a/drivers/input/touchscreen/gt1x/gt1x_generic.h b/drivers/input/touchscreen/gt1x/gt1x_generic.h index f73e18283ea7..25c96a449772 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_generic.h +++ b/drivers/input/touchscreen/gt1x/gt1x_generic.h @@ -503,7 +503,7 @@ struct fw_update_info { }; /* Export form gt1x_update.c */ -extern struct fw_update_info update_info; +extern struct fw_update_info gt1x_update_info; extern u8 gt1x_default_FW[]; extern int gt1x_hold_ss51_dsp(void); @@ -527,8 +527,8 @@ extern struct i2c_client *gt1x_i2c_client; extern CHIP_TYPE_T gt1x_chip_type; extern struct gt1x_version_info gt1x_version; -extern s32 _do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len); -extern s32 _do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len); +extern s32 gt1x_do_i2c_read(struct i2c_msg *msgs, u16 addr, u8 *buffer, s32 len); +extern s32 gt1x_do_i2c_write(struct i2c_msg *msg, u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_write(u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_read(u16 addr, u8 *buffer, s32 len); extern s32 gt1x_i2c_read_dbl_check(u16 addr, u8 *buffer, s32 len); diff --git a/drivers/input/touchscreen/gt1x/gt1x_tools.c b/drivers/input/touchscreen/gt1x/gt1x_tools.c index 0f38e988615d..8a11266569c1 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_tools.c +++ b/drivers/input/touchscreen/gt1x/gt1x_tools.c @@ -411,10 +411,10 @@ static ssize_t gt1x_tool_read(struct file *filp, char __user *buffer, size_t cou return -1; } else if (4 == cmd_head.wr) { /* read fw update progress */ - buffer[0] = update_info.progress >> 8; - buffer[1] = update_info.progress & 0xff; - buffer[2] = update_info.max_progress >> 8; - buffer[3] = update_info.max_progress & 0xff; + buffer[0] = gt1x_update_info.progress >> 8; + buffer[1] = gt1x_update_info.progress & 0xff; + buffer[2] = gt1x_update_info.max_progress >> 8; + buffer[3] = gt1x_update_info.max_progress & 0xff; *ppos += 4; return 4; } else if (6 == cmd_head.wr) { diff --git a/drivers/input/touchscreen/gt1x/gt1x_update.c b/drivers/input/touchscreen/gt1x/gt1x_update.c index bd8e41b9fdfa..b7c86863e776 100644 --- a/drivers/input/touchscreen/gt1x/gt1x_update.c +++ b/drivers/input/touchscreen/gt1x/gt1x_update.c @@ -130,7 +130,7 @@ struct fw_info { }; #pragma pack() -struct fw_update_info update_info = { +struct fw_update_info gt1x_update_info = { .status = UPDATE_STATUS_IDLE, .progress = 0, .max_progress = 9, @@ -657,16 +657,16 @@ int gt1x_check_firmware(void) u8 *gt1x_get_fw_data(u32 offset, int length) { int ret; - if (update_info.update_type == UPDATE_TYPE_FILE) { - update_info.fw_file->f_op->llseek(update_info.fw_file, offset, SEEK_SET); - ret = update_info.fw_file->f_op->read(update_info.fw_file, (char *)update_info.buffer, length, &update_info.fw_file->f_pos); + if (gt1x_update_info.update_type == UPDATE_TYPE_FILE) { + gt1x_update_info.fw_file->f_op->llseek(gt1x_update_info.fw_file, offset, SEEK_SET); + ret = gt1x_update_info.fw_file->f_op->read(gt1x_update_info.fw_file, (char *) gt1x_update_info.buffer, length, >1x_update_info.fw_file->f_pos); if (ret < 0) { GTP_ERROR("Read data error!"); return NULL; } - return update_info.buffer; + return gt1x_update_info.buffer; } else { - return &update_info.fw_data[offset]; + return >1x_update_info.fw_data[offset]; } } @@ -678,13 +678,13 @@ int gt1x_update_judge(void) struct gt1x_version_info ver_info; struct gt1x_version_info fw_ver_info; - fw_ver_info.mask_id = (update_info.firmware->target_mask_version[0] << 16) - | (update_info.firmware->target_mask_version[1] << 8) - | (update_info.firmware->target_mask_version[2]); - fw_ver_info.patch_id = (update_info.firmware->version[0] << 16) - | (update_info.firmware->version[1] << 8) - | (update_info.firmware->version[2]); - memcpy(fw_ver_info.product_id, update_info.firmware->pid, 4); + fw_ver_info.mask_id = (gt1x_update_info.firmware->target_mask_version[0] << 16) + | (gt1x_update_info.firmware->target_mask_version[1] << 8) + | (gt1x_update_info.firmware->target_mask_version[2]); + fw_ver_info.patch_id = (gt1x_update_info.firmware->version[0] << 16) + | (gt1x_update_info.firmware->version[1] << 8) + | (gt1x_update_info.firmware->version[2]); + memcpy(fw_ver_info.product_id, gt1x_update_info.firmware->pid, 4); fw_ver_info.product_id[4] = 0; /* check fw status reg */ @@ -737,7 +737,7 @@ _reset: return 0; } #if GTP_DEBUG_ON - if (update_info.force_update) { + if (gt1x_update_info.force_update) { GTP_DEBUG("Debug mode, force update fw."); return 0; } @@ -1201,13 +1201,13 @@ int gt1x_error_erase(void) gt1x_reset_guitar(); - fw = gt1x_get_fw_data(update_info.firmware->subsystem[0].offset, - update_info.firmware->subsystem[0].length); + fw = gt1x_get_fw_data(gt1x_update_info.firmware->subsystem[0].offset, + gt1x_update_info.firmware->subsystem[0].length); if (!fw) { GTP_ERROR("get isp fail"); return ERROR_FW; } - ret = gt1x_run_ss51_isp(fw, update_info.firmware->subsystem[0].length); + ret = gt1x_run_ss51_isp(fw, gt1x_update_info.firmware->subsystem[0].length); if (ret) { GTP_ERROR("run isp fail"); return ERROR_PATH; @@ -1311,7 +1311,7 @@ int gt1x_error_erase(void) void gt1x_leave_update_mode(void) { GTP_DEBUG("Leave FW update mode."); - if (update_info.status != UPDATE_STATUS_ABORT) + if (gt1x_update_info.status != UPDATE_STATUS_ABORT) gt1x_reset_guitar(); #if GTP_CHARGER_SWITCH gt1x_charger_switch(SWITCH_ON); @@ -1319,7 +1319,7 @@ void gt1x_leave_update_mode(void) #if GTP_ESD_PROTECT gt1x_esd_switch(SWITCH_ON); #endif - update_info.status = UPDATE_STATUS_IDLE; + gt1x_update_info.status = UPDATE_STATUS_IDLE; gt1x_irq_enable(); } diff --git a/drivers/input/touchscreen/hyn/Makefile b/drivers/input/touchscreen/hyn/Makefile new file mode 100644 index 000000000000..41c47e120e49 --- /dev/null +++ b/drivers/input/touchscreen/hyn/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_TOUCHSCREEN_HYN) += hynitron_touch.o + +hynitron_touch-objs += hyn_core.o hyn_lib/hyn_i2c.o hyn_lib/hyn_spi.o hyn_lib/hyn_ts_ext.o hyn_lib/hyn_fs_node.o +hynitron_touch-objs += hyn_lib/hyn_tool.o +hynitron_touch-objs += hyn_lib/hyn_gesture.o +hynitron_touch-objs += hyn_lib/hyn_prox.o +hynitron_touch-objs += hyn_chips/hyn_cst66xx.o +hynitron_touch-objs += hyn_chips/hyn_cst3240.o +hynitron_touch-objs += hyn_chips/hyn_cst92xx.o +hynitron_touch-objs += hyn_chips/hyn_cst3xx.o +hynitron_touch-objs += hyn_chips/hyn_cst7xx.o +hynitron_touch-objs += hyn_chips/hyn_cst8xxT.o +hynitron_touch-objs += hyn_chips/hyn_cst226se.o +hynitron_touch-objs += hyn_chips/hyn_cst36xxes.o diff --git a/drivers/input/touchscreen/hyn/hyn_cfg.h b/drivers/input/touchscreen/hyn/hyn_cfg.h new file mode 100644 index 000000000000..c3ed729fa786 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_cfg.h @@ -0,0 +1,60 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_cfg.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 _HYNITRON_CFG_H +#define _HYNITRON_CFG_H + +#define I2C_PORT + +#ifdef I2C_PORT +#define I2C_USE_DMA (1) //0:soft 1:DMA 2:MTK_DMA +#else +#define SPI_MODE (0) +#define SPI_DELAY_CS (10) //us +#define SPI_CLOCK_FREQ (8000000) +#define I2C_USE_DMA (0) +// #define CONFIG_BUS_SPI //default:0 MTK can try define +#endif + +#define HYN_TRANSFER_LIMIT_LEN (2048) //need >= 8 + +#define HYN_POWER_ON_UPDATA (1) //updata + +#ifdef CONFIG_MODULES +#define HYN_GKI_VER (1) //GKI version need enable +#else +#define HYN_GKI_VER (0) //GKI version need enable +#endif +#define HYN_APK_DEBUG_EN (1) + +#define HYN_GESTURE_EN (0) //gesture + +#define HYN_PROX_TYEP (0) //0:disable 1:default 2:mtk_sensor 3:mtk_alps 4:Spread misc + +#define KEY_USED_POS_REPORT (0) + +#define ESD_CHECK_EN (0) + +#define HYN_WAKE_LOCK_EN (0) + +#define HYN_MT_PROTOCOL_B_EN (1) + +//selftest cfg +#define HYN_TP0_TEST_LOG_SAVE (0) + +#define HYN_DRIVER_VERSION "== Hynitron V2.11 20250217 ==" + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst226se_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst226se_fw.h new file mode 100644 index 000000000000..d6aef907a857 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst226se_fw.h @@ -0,0 +1,503 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst226se_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { + 0x6C,0x03,0x00,0x20,0x09,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xF9,0x00,0x00,0x00,0xFB,0x00,0x00,0x00,0x1B,0x01,0x00,0x00,0x37,0x01,0x00,0x00, + 0x4B,0x01,0x00,0x00,0x00,0xF0,0x02,0xF8,0x00,0xF0,0x3E,0xF8,0x0C,0xA0,0x30,0xC8, + 0x08,0x38,0x24,0x18,0x2D,0x18,0xA2,0x46,0x67,0x1E,0xAB,0x46,0x54,0x46,0x5D,0x46, + 0xAC,0x42,0x01,0xD1,0x00,0xF0,0x30,0xF8,0x7E,0x46,0x0F,0x3E,0x0F,0xCC,0xB6,0x46, + 0x01,0x26,0x33,0x42,0x00,0xD0,0xFB,0x1A,0xA2,0x46,0xAB,0x46,0x33,0x43,0x18,0x47, + 0x04,0x18,0x00,0x00,0x24,0x18,0x00,0x00,0x10,0x3A,0x02,0xD3,0x78,0xC8,0x78,0xC1, + 0xFA,0xD8,0x52,0x07,0x01,0xD3,0x30,0xC8,0x30,0xC1,0x01,0xD5,0x04,0x68,0x0C,0x60, + 0x70,0x47,0x00,0x00,0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x10,0x3A,0x01,0xD3, + 0x78,0xC1,0xFB,0xD8,0x52,0x07,0x00,0xD3,0x30,0xC1,0x00,0xD5,0x0B,0x60,0x70,0x47, + 0x1F,0xB5,0x1F,0xBD,0x10,0xB5,0x10,0xBD,0x01,0xF0,0x05,0xFA,0x11,0x46,0xFF,0xF7, + 0xF7,0xFF,0x00,0xF0,0x53,0xF9,0x01,0xF0,0x1D,0xFA,0x03,0xB4,0xFF,0xF7,0xF2,0xFF, + 0x03,0xBC,0x01,0xF0,0x21,0xFA,0x00,0x00,0xFE,0xE7,0x1D,0x49,0x48,0x88,0x48,0x80, + 0x1C,0x48,0x02,0x7C,0xFF,0x2A,0x02,0xD2,0x02,0x7C,0x52,0x1C,0x02,0x74,0x00,0x7C, + 0x18,0x28,0x01,0xD2,0x00,0x20,0x88,0x80,0x70,0x47,0x17,0x49,0x8A,0x79,0x15,0x48, + 0x20,0x38,0x80,0x6F,0x43,0x7A,0x9A,0x43,0x8A,0x71,0x40,0x7A,0x48,0x72,0x11,0x49, + 0x01,0x20,0x08,0x74,0x70,0x47,0x10,0xB5,0x0F,0x48,0x80,0x30,0x81,0x88,0x80,0x22, + 0x11,0x43,0x81,0x80,0x0D,0xF0,0xEC,0xFE,0x10,0xBD,0x10,0xB5,0x09,0x48,0x20,0x30, + 0x01,0x78,0x49,0x06,0x08,0xD5,0x02,0x78,0x80,0x21,0x0A,0x43,0x02,0x70,0x07,0x48, + 0x42,0x88,0x8A,0x43,0x42,0x80,0x10,0xBD,0x00,0xF0,0xA2,0xFD,0x10,0xBD,0x00,0x00, + 0x00,0x02,0x00,0x40,0x90,0x0A,0x00,0x20,0x00,0x10,0x00,0x40,0x00,0x20,0x00,0x40, + 0x10,0xB5,0x8A,0x48,0x8A,0x4B,0x80,0x6F,0x01,0x46,0x80,0x31,0x0C,0x46,0x0A,0x7F, + 0x60,0x30,0x41,0x79,0x00,0x2A,0x06,0xD0,0x12,0x02,0x0A,0x43,0x5A,0x81,0xFF,0x21, + 0x23,0x31,0x59,0x80,0x03,0xE0,0x59,0x81,0xFF,0x21,0x03,0x31,0x59,0x80,0xA1,0x8E, + 0xD9,0x80,0x81,0x79,0x02,0x79,0x09,0x02,0x11,0x43,0x19,0x81,0x01,0x7A,0xC0,0x79, + 0x09,0x02,0x01,0x43,0x7A,0x48,0x20,0x38,0xC1,0x81,0x10,0xBD,0x10,0xB5,0x77,0x48, + 0x78,0x49,0x81,0x67,0x78,0x49,0xC1,0x61,0x78,0x49,0x01,0x62,0x78,0x49,0x41,0x62, + 0x78,0x49,0x81,0x62,0x78,0x49,0xC1,0x62,0x78,0x49,0xC1,0x67,0x78,0x49,0x41,0x64, + 0x78,0x49,0x81,0x64,0x78,0x49,0xC1,0x64,0x78,0x49,0x01,0x65,0x78,0x49,0x41,0x65, + 0x78,0x49,0x00,0x20,0xC8,0x80,0xC8,0x60,0x48,0x70,0x88,0x70,0xC8,0x70,0x08,0x71, + 0x48,0x71,0x7D,0x22,0xD2,0x00,0x0A,0x81,0x65,0x4A,0x01,0x21,0x60,0x3A,0x91,0x75, + 0x6A,0x49,0xA8,0x22,0x40,0x31,0x0A,0x73,0xC8,0x72,0x02,0x20,0x88,0x71,0x03,0x20, + 0x48,0x71,0x0D,0xF0,0xD9,0xFE,0x0D,0xF0,0xD3,0xFE,0x3C,0x20,0x0D,0xF0,0xCC,0xFE, + 0x0D,0xF0,0xC6,0xFE,0x0D,0xF0,0xC0,0xFE,0x00,0xF0,0xC5,0xFB,0x0D,0xF0,0xB8,0xFE, + 0x00,0xF0,0xED,0xFB,0x10,0xBD,0xFE,0xB5,0x63,0x4E,0x00,0x21,0x00,0x25,0x63,0x4C, + 0x00,0x22,0x68,0x46,0x42,0x54,0x0A,0x20,0x61,0x4A,0x48,0x43,0x82,0x18,0x23,0x20, + 0x40,0x01,0x13,0x18,0x00,0x22,0x30,0x78,0xC7,0x00,0x18,0x78,0x38,0x1A,0x80,0xB2, + 0x85,0x42,0x00,0xD2,0x05,0x46,0x84,0x42,0x00,0xD9,0x04,0x46,0x5B,0x1C,0x52,0x1C, + 0xD2,0xB2,0x0A,0x2A,0xF1,0xD3,0x28,0x1B,0x6B,0x46,0x58,0x54,0x76,0x1C,0x49,0x1C, + 0xC9,0xB2,0x0C,0x29,0xDA,0xD3,0x51,0x49,0x00,0x20,0x1A,0x5C,0x8A,0x42,0x00,0xD2, + 0x11,0x46,0x40,0x1C,0xC0,0xB2,0x0C,0x28,0xF7,0xD3,0x4A,0x4C,0x00,0x20,0x60,0x70, + 0x1A,0x5C,0x65,0x78,0x52,0x1A,0x52,0x19,0x62,0x70,0x40,0x1C,0xC0,0xB2,0x0C,0x28, + 0xF6,0xD3,0xFE,0xBD,0xF8,0xB5,0x35,0x4C,0x40,0x34,0x20,0x78,0x01,0x21,0x08,0x43, + 0x20,0x70,0x44,0x4F,0x31,0x4D,0x3F,0x4E,0x4C,0xE0,0x0D,0xF0,0x65,0xFE,0xF0,0x68, + 0x40,0x1C,0xF0,0x60,0x38,0x7A,0x00,0x28,0x03,0xD0,0x2C,0x49,0x18,0x20,0x20,0x31, + 0x08,0x74,0x0D,0xF0,0x55,0xFE,0x20,0x78,0xC0,0x07,0x01,0xD0,0x55,0x20,0x78,0x70, + 0x0D,0xF0,0x4A,0xFE,0xFF,0xF7,0x9F,0xFF,0xA8,0x6F,0x20,0x30,0x40,0x78,0x00,0x28, + 0x01,0xD0,0x0D,0xF0,0x3D,0xFE,0xA8,0x6F,0x21,0x21,0x09,0x5C,0x09,0x09,0x06,0xD0, + 0x1E,0x49,0x60,0x30,0x60,0x39,0x89,0x7B,0xC0,0x7A,0x81,0x42,0x1E,0xD1,0x0D,0xF0, + 0x2B,0xFE,0x00,0x20,0x30,0x70,0x0D,0xF0,0x23,0xFE,0x18,0x49,0x02,0x20,0x40,0x39, + 0x48,0x76,0x00,0xF0,0xBA,0xF8,0x0D,0xF0,0x17,0xFE,0x00,0xF0,0x1E,0xFA,0x00,0xF0, + 0x70,0xFB,0x0D,0xF0,0x0D,0xFE,0x0D,0xF0,0xFF,0xFD,0x23,0x48,0x0D,0xF0,0xF8,0xFD, + 0x0D,0xF0,0xF2,0xFD,0x00,0xF0,0x5A,0xFF,0x00,0xF0,0x58,0xFB,0x00,0xF0,0x60,0xF9, + 0x00,0xF0,0x60,0xF8,0xA0,0x78,0x06,0x28,0xAF,0xD1,0xF8,0xBD,0xFF,0xF7,0x1E,0xFF, + 0x06,0x4C,0x40,0x34,0xA0,0x78,0x00,0x28,0x04,0xD0,0x06,0x28,0xFA,0xD1,0x0D,0xF0, + 0xC3,0xFD,0xF7,0xE7,0xFF,0xF7,0x96,0xFF,0xF4,0xE7,0x00,0x00,0x70,0x0A,0x00,0x20, + 0x80,0x10,0x00,0x40,0x48,0x15,0x00,0x00,0x7A,0x17,0x00,0x00,0x8C,0x17,0x00,0x00, + 0x68,0x18,0x00,0x00,0x48,0x17,0x00,0x00,0x68,0x17,0x00,0x00,0x10,0x00,0x00,0x20, + 0x31,0x04,0x00,0x00,0x39,0x04,0x00,0x00,0xEF,0x0A,0x00,0x00,0xE7,0x0D,0x00,0x00, + 0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x20,0x84,0x08,0x00,0x20,0xFF,0xFF,0x00,0x00, + 0x70,0x03,0x00,0x20,0x64,0x00,0x00,0x20,0x9B,0x07,0x00,0x00,0x0B,0x49,0x0A,0x48, + 0xC8,0x60,0xBF,0xF3,0x40,0x8F,0xFE,0xE7,0x10,0xB5,0xFF,0xF7,0xBF,0xFF,0x10,0xBD, + 0x0F,0xB5,0x00,0x90,0x01,0x91,0x01,0x98,0x02,0x90,0x00,0x98,0x03,0x90,0x68,0x46, + 0x0F,0xC8,0x04,0xB0,0x00,0xBD,0x00,0x00,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0, + 0x10,0xB5,0x00,0xF0,0xB5,0xFF,0x10,0xBD,0x10,0xB5,0x00,0xF0,0xB1,0xFF,0x08,0x46, + 0x10,0xBD,0x00,0x00,0x70,0xB5,0xF9,0x48,0x00,0xE0,0x30,0xBF,0x01,0x7C,0x00,0x29, + 0xFB,0xD0,0xF6,0x4C,0x20,0x34,0x20,0x78,0x00,0x07,0x24,0xD5,0xF4,0x4E,0x01,0x25, + 0x35,0x76,0xA8,0x07,0x01,0x68,0x08,0x22,0x11,0x43,0x01,0x60,0x00,0x20,0x08,0xF0, + 0x6C,0xFD,0xEF,0x4A,0x20,0x3A,0x10,0x78,0x21,0x46,0x40,0x39,0x89,0x6F,0x20,0x31, + 0x8B,0x79,0x29,0x46,0x99,0x40,0x08,0x43,0x10,0x70,0x20,0x78,0xEF,0x21,0x08,0x40, + 0x20,0x70,0x00,0xE0,0x30,0xBF,0x20,0x78,0xC0,0x06,0xFB,0xD5,0x00,0x20,0x30,0x76, + 0x20,0x78,0x28,0x43,0x20,0x70,0xE3,0x4A,0x50,0x68,0x40,0x1C,0x50,0x60,0xE2,0x49, + 0x03,0x0E,0x8B,0x72,0x03,0x0C,0x4B,0x72,0x03,0x0A,0x0B,0x72,0xC8,0x71,0x10,0x7A, + 0x00,0x28,0x01,0xD0,0x30,0xBF,0xFD,0xE7,0x70,0xBD,0x30,0xB5,0xDB,0x48,0x00,0x68, + 0x0A,0x28,0x31,0xD9,0x00,0x25,0xDA,0x49,0x0A,0x46,0x00,0x23,0x00,0x20,0x14,0x78, + 0xFF,0x2C,0x00,0xD1,0x01,0x25,0x52,0x1C,0x40,0x1C,0xC0,0xB2,0x0A,0x28,0xF6,0xD3, + 0x5B,0x1C,0xDB,0xB2,0x0C,0x2B,0xF1,0xD3,0x00,0x24,0x00,0x22,0x00,0x20,0x0B,0x78, + 0x93,0x42,0x00,0xD9,0x1A,0x46,0x49,0x1C,0x40,0x1C,0xC0,0xB2,0x0A,0x28,0xF6,0xD3, + 0x0B,0x3A,0x31,0x2A,0x00,0xD2,0x01,0x25,0x64,0x1C,0xE4,0xB2,0x0C,0x2C,0xEC,0xD3, + 0xC8,0x49,0x00,0x2D,0x09,0xD0,0xC8,0x48,0x00,0x78,0x00,0x28,0x04,0xD1,0x08,0x78, + 0x64,0x28,0x01,0xD2,0x40,0x1C,0x08,0x70,0x30,0xBD,0x00,0x20,0x08,0x70,0x30,0xBD, + 0xF0,0xB5,0x85,0xB0,0x00,0x26,0xC1,0xA0,0x03,0xC8,0x02,0x91,0x01,0x90,0xB7,0x48, + 0x80,0x38,0xC0,0x7C,0xB5,0x49,0x20,0x39,0x04,0x91,0x00,0x28,0x1D,0xD0,0x01,0xA9, + 0x00,0x20,0xB7,0x4A,0x17,0x23,0xDC,0x3A,0x9B,0x01,0x11,0xE0,0x24,0x24,0x44,0x43, + 0xA4,0x18,0xE4,0x18,0x24,0x7C,0x01,0x2C,0x08,0xD1,0x08,0x70,0x49,0x1C,0x76,0x1C, + 0xF6,0xB2,0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0xB4,0x42,0x06,0xD0,0x40,0x1C,0xC0,0xB2, + 0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0x84,0x42,0xE8,0xD8,0xA7,0x4C,0x40,0x3C,0x01,0xAD, + 0x00,0x27,0xA2,0x48,0x40,0x38,0x03,0x90,0x0A,0xE0,0x00,0x2F,0x18,0xD0,0x28,0x78, + 0x6A,0x46,0x21,0x46,0x08,0xF0,0x8B,0xF9,0x6D,0x1C,0x64,0x1D,0x7F,0x1C,0xFF,0xB2, + 0xB7,0x42,0xF2,0xD3,0x03,0x98,0x00,0x7C,0xC1,0x09,0x24,0xD0,0x00,0x2E,0x17,0xD0, + 0x20,0x70,0x03,0x98,0x80,0x7C,0x60,0x70,0xA4,0x1C,0xAB,0x20,0x20,0x70,0x18,0xE0, + 0x28,0x78,0x6A,0x46,0x21,0x46,0x08,0xF0,0x72,0xF9,0x6D,0x1C,0x03,0x98,0x00,0x7C, + 0xC0,0x09,0xC0,0x01,0x30,0x43,0x60,0x71,0xAB,0x20,0xA0,0x71,0xE4,0x1D,0xDD,0xE7, + 0x20,0x70,0x03,0x98,0x80,0x7C,0x60,0x70,0x80,0x20,0x60,0x71,0xA4,0x1D,0xAB,0x20, + 0x20,0x70,0x64,0x1C,0x04,0xE0,0x01,0x2E,0x02,0xD9,0xAB,0x20,0x20,0x70,0x64,0x1C, + 0x20,0x46,0x08,0xF0,0x35,0xF8,0x82,0x4A,0x20,0x3A,0x10,0x78,0x04,0x99,0x89,0x6F, + 0x20,0x31,0x8B,0x79,0x01,0x21,0x99,0x40,0x08,0x43,0x10,0x70,0x05,0xB0,0xF0,0xBD, + 0xF8,0xB5,0x7A,0x4D,0x20,0x35,0xA8,0x78,0x00,0x28,0x03,0xD0,0x0D,0xF0,0x74,0xFC, + 0x00,0x28,0x36,0xD1,0x75,0x48,0x76,0x4F,0x80,0x38,0x84,0x46,0xC1,0x7C,0x76,0x48, + 0x72,0x4C,0x40,0x38,0x20,0x3F,0x01,0x26,0x20,0x3C,0x00,0x29,0x0A,0xD1,0xA2,0x6F, + 0x21,0x46,0x20,0x39,0x20,0x32,0x8B,0x7D,0x12,0x7A,0x93,0x42,0x05,0xD3,0x09,0x7C, + 0x09,0x06,0x02,0xD5,0x61,0x78,0x00,0x29,0x24,0xD0,0x6A,0x4A,0x51,0x78,0x55,0x29, + 0x06,0xD0,0x11,0x78,0x55,0x29,0x14,0xD1,0x61,0x46,0x49,0x7B,0x06,0x29,0x10,0xD1, + 0x00,0x21,0x11,0x70,0x51,0x70,0x01,0x70,0xAB,0x22,0x82,0x71,0x41,0x71,0xA8,0x78, + 0x00,0x28,0x07,0xD0,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0x30,0x43, + 0x38,0x70,0xF8,0xBD,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0xB0,0x43, + 0x38,0x70,0xF8,0xBD,0x57,0x49,0x55,0x22,0x0A,0x70,0x5B,0x49,0x09,0x78,0x00,0x29, + 0x02,0xD0,0xAA,0x78,0x00,0x2A,0x3C,0xD0,0x00,0x21,0x05,0x46,0x59,0x48,0x2A,0x78, + 0xAB,0x2A,0x03,0xD0,0x49,0x1C,0x89,0xB2,0x81,0x42,0xF8,0xD3,0x38,0x78,0xA1,0x6F, + 0x32,0x46,0x60,0x31,0x49,0x78,0x8A,0x40,0x10,0x42,0x12,0xD1,0x01,0x20,0x0C,0xF0, + 0x02,0xFF,0x38,0x78,0xA1,0x6F,0x60,0x31,0x4A,0x78,0x31,0x46,0x91,0x40,0x08,0x42, + 0x07,0xD1,0x4D,0x48,0x41,0x88,0x23,0x22,0x91,0x43,0x41,0x80,0x41,0x88,0x31,0x43, + 0x41,0x80,0xE5,0x67,0x0D,0xF0,0x04,0xFC,0xFF,0xF7,0x02,0xFF,0x38,0x78,0xA1,0x6F, + 0x20,0x31,0x8A,0x79,0x31,0x46,0x91,0x40,0x88,0x43,0x38,0x70,0x64,0x20,0x0C,0xF0, + 0xE2,0xFE,0x38,0x78,0xA1,0x6F,0x20,0x31,0x89,0x79,0x8E,0x40,0x30,0x43,0x38,0x70, + 0xF8,0xBD,0x3B,0x29,0x01,0xD0,0x01,0x29,0xFA,0xD1,0x00,0x21,0x01,0x70,0x41,0x71, + 0xAB,0x21,0x81,0x71,0x38,0x78,0xA1,0x6F,0x20,0x31,0x8A,0x79,0x31,0x46,0x91,0x40, + 0x88,0x43,0x38,0x70,0x64,0x20,0x0C,0xF0,0xC6,0xFE,0x38,0x78,0xA1,0x6F,0x20,0x31, + 0x89,0x79,0x8E,0x40,0x30,0x43,0x38,0x70,0xF8,0xBD,0xF0,0xB5,0x87,0xB0,0x00,0x20, + 0x00,0x90,0x00,0x22,0x00,0x24,0x00,0x23,0x0B,0x25,0xAD,0x01,0x27,0x26,0xF6,0x43, + 0x23,0x49,0x5F,0x00,0xDC,0x39,0x79,0x18,0x4F,0x19,0x38,0x21,0x79,0x5E,0xB1,0x42, + 0x02,0xDA,0x40,0x18,0x00,0xB2,0x03,0xE0,0x28,0x29,0x01,0xDD,0x52,0x18,0x92,0xB2, + 0x50,0x29,0x00,0xDD,0x01,0x24,0x5B,0x1C,0x1B,0xB2,0x78,0x2B,0xE8,0xDB,0x1F,0x4E, + 0xF0,0x85,0x32,0x86,0x1E,0x49,0x0D,0x78,0x1E,0x49,0x06,0x95,0x0B,0x88,0x0F,0x49, + 0x20,0x31,0x0F,0x2D,0x4E,0xD9,0xFF,0x25,0xF5,0x35,0xE8,0x42,0x3A,0xDA,0x00,0x28, + 0x01,0xDB,0x05,0x46,0x00,0xE0,0x45,0x42,0x95,0x42,0x33,0xDD,0x08,0x78,0x01,0x22, + 0x10,0x43,0x08,0x70,0x14,0x49,0x00,0x20,0x88,0x80,0x14,0x48,0x0C,0xF0,0x7B,0xFE, + 0x10,0x49,0x13,0x48,0x08,0x80,0x07,0xB0,0xF0,0xBD,0x00,0x00,0x90,0x0A,0x00,0x20, + 0x20,0x10,0x00,0x40,0x64,0x00,0x00,0x20,0x50,0x00,0x00,0x20,0x0C,0x00,0x00,0x20, + 0x4C,0x04,0x00,0x20,0x05,0x00,0x00,0x20,0x02,0x00,0x00,0x20,0xFF,0xFF,0xFF,0xFF, + 0xFF,0x00,0x00,0x00,0x4C,0x1D,0x00,0x00,0x00,0x20,0x00,0x40,0x70,0x08,0x00,0x20, + 0x01,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x00,0x02,0x00,0x40,0x88,0x13,0x00,0x00, + 0x70,0x17,0x00,0x00,0xC8,0x25,0xE8,0x42,0x2A,0xDA,0x00,0x28,0x01,0xDB,0x07,0x46, + 0x00,0xE0,0x47,0x42,0xFE,0x4D,0x9F,0x42,0x22,0xDD,0x00,0x28,0x00,0xDA,0x40,0x42, + 0x28,0x80,0x1D,0xE0,0x00,0x28,0x01,0xDB,0x05,0x46,0x00,0xE0,0x45,0x42,0x95,0x42, + 0x07,0xDD,0xFF,0x25,0x91,0x35,0xE8,0x42,0x03,0xDA,0xF5,0x4B,0xF5,0x48,0x18,0x80, + 0x0E,0xE0,0xC8,0x25,0xE8,0x42,0x0B,0xDA,0x00,0x28,0x01,0xDB,0x07,0x46,0x00,0xE0, + 0x47,0x42,0xEF,0x4D,0x9F,0x42,0x03,0xDD,0x00,0x28,0x00,0xDA,0x40,0x42,0x28,0x80, + 0xED,0x4D,0xEE,0x48,0x2B,0x78,0x00,0x78,0x05,0x90,0xED,0x48,0x14,0x2B,0x00,0x78, + 0x04,0x90,0x0B,0xD9,0x05,0x98,0x00,0x28,0x08,0xD1,0x04,0x98,0x00,0x28,0x05,0xD1, + 0x4B,0x20,0xC0,0x00,0x82,0x42,0x01,0xD2,0x00,0x2C,0x38,0xD0,0x00,0x20,0x02,0x90, + 0x00,0x20,0x00,0x21,0x01,0x91,0x02,0x99,0x4A,0x00,0xE2,0x49,0x52,0x18,0x5F,0x21, + 0xC9,0x00,0x53,0x18,0x1D,0x46,0x00,0x22,0x00,0x21,0x59,0x5E,0x08,0x18,0x00,0xB2, + 0x01,0x9C,0xA1,0x42,0x00,0xDD,0x01,0x91,0x14,0x33,0x52,0x1C,0xD2,0xB2,0x0C,0x2A, + 0xF2,0xD3,0x0C,0x21,0x00,0xF0,0x34,0xFD,0x04,0xB2,0x00,0x98,0xA0,0x42,0x01,0xDA, + 0xA0,0xB2,0x00,0x90,0x00,0x27,0x00,0x2C,0x21,0xDD,0x00,0x20,0x28,0x5E,0x03,0x90, + 0xA0,0x42,0x16,0xDB,0x03,0x21,0x01,0x98,0x00,0xF0,0x22,0xFD,0xA0,0x42,0x1C,0xDA, + 0xE0,0x0F,0x00,0x19,0x41,0x10,0x03,0x98,0x40,0x1A,0x28,0x80,0x15,0xE0,0x08,0x78, + 0x01,0x22,0x10,0x43,0x08,0x70,0xC2,0x49,0xC2,0x48,0x08,0x80,0x00,0x20,0x28,0x70, + 0x51,0xE7,0x03,0x98,0x00,0x28,0x08,0xDD,0x01,0x20,0x28,0x80,0x05,0xE0,0x00,0x20, + 0x28,0x5E,0xA0,0x42,0x01,0xDC,0x00,0x1B,0x28,0x80,0x14,0x35,0x7F,0x1C,0xFF,0xB2, + 0x0C,0x2F,0xD0,0xD3,0x02,0x98,0x40,0x1C,0xC0,0xB2,0x02,0x90,0x02,0x98,0x0A,0x28, + 0xA6,0xD3,0xB9,0x48,0x80,0x7A,0xF0,0x84,0x06,0x98,0x30,0x85,0x05,0x98,0x70,0x85, + 0x04,0x98,0xB0,0x85,0xB5,0x48,0x00,0x68,0x70,0x86,0x00,0x14,0xB0,0x86,0xAC,0x48, + 0x00,0x88,0xF0,0x86,0x27,0xE7,0x30,0xB5,0xB1,0x48,0x83,0x78,0xAE,0x49,0x01,0x22, + 0x60,0x31,0x89,0x6F,0x14,0x46,0x20,0x31,0x8D,0x79,0xAC,0x40,0xA3,0x43,0x83,0x70, + 0x43,0x78,0x8D,0x79,0x14,0x46,0xAC,0x40,0xA3,0x43,0x43,0x70,0x03,0x78,0x8D,0x79, + 0x14,0x46,0xAC,0x40,0x23,0x43,0x03,0x70,0x03,0x79,0x8D,0x79,0x14,0x46,0xAC,0x40, + 0x23,0x43,0x03,0x71,0x43,0x79,0x8D,0x79,0x14,0x46,0xAC,0x40,0xA3,0x43,0x43,0x71, + 0xC3,0x78,0x89,0x79,0x8A,0x40,0x13,0x43,0xC3,0x70,0x30,0xBD,0x70,0x47,0x9D,0x49, + 0x00,0x20,0x08,0x70,0x48,0x70,0x48,0x60,0x88,0x70,0x9B,0x4A,0xD0,0x72,0x08,0x72, + 0x70,0x47,0xF8,0xB5,0x99,0x4A,0x98,0x4B,0xD8,0x7A,0x00,0x28,0x4E,0xD0,0x00,0x20, + 0x00,0x24,0x28,0x25,0x90,0x49,0x60,0x31,0x00,0x91,0x8E,0x6F,0xF1,0x79,0x00,0x29, + 0x00,0xD0,0x1E,0x25,0x00,0x21,0x08,0xE0,0x00,0x27,0xD7,0x5F,0x0A,0x2F,0x01,0xDB, + 0x40,0x1C,0x80,0xB2,0x92,0x1C,0x49,0x1C,0x89,0xB2,0xA9,0x42,0xF4,0xD3,0x89,0x49, + 0x0A,0x28,0x08,0xD2,0x06,0x28,0x02,0xD3,0xD8,0x7A,0x40,0x06,0x03,0xD1,0x82,0x48, + 0xC0,0x7B,0x01,0x28,0x08,0xD9,0xD8,0x7A,0x80,0x28,0x00,0xD1,0x01,0x24,0x81,0x20, + 0xD8,0x72,0x14,0x20,0x88,0x70,0x0B,0xE0,0x88,0x78,0x00,0x28,0x02,0xD0,0x40,0x1E, + 0x88,0x70,0x05,0xE0,0xD8,0x7A,0x81,0x28,0x00,0xD1,0x01,0x24,0x80,0x20,0xD8,0x72, + 0x00,0x2C,0x13,0xD0,0x76,0x4C,0x20,0x78,0x20,0x36,0xB2,0x79,0x01,0x25,0x29,0x46, + 0x91,0x40,0x88,0x43,0x20,0x70,0x28,0x20,0x0C,0xF0,0x1D,0xFD,0x20,0x78,0x00,0x99, + 0x89,0x6F,0x20,0x31,0x89,0x79,0x8D,0x40,0x28,0x43,0x20,0x70,0xF8,0xBD,0xF8,0xB5, + 0x0D,0x46,0x07,0x9F,0x06,0x9E,0x11,0x46,0x67,0x4A,0x60,0x32,0x90,0x6F,0x40,0x30, + 0x00,0x2D,0x07,0xD0,0x00,0x2E,0x02,0xD0,0x1E,0x24,0x04,0x57,0x09,0xE0,0x1D,0x24, + 0x04,0x57,0x06,0xE0,0x00,0x2F,0x02,0xD0,0x1C,0x24,0x04,0x57,0x01,0xE0,0x1B,0x24, + 0x04,0x57,0x00,0x20,0x18,0x5E,0x00,0x28,0x00,0xDA,0x40,0x42,0xC0,0x01,0x0B,0x46, + 0x00,0x21,0x52,0x6C,0x59,0x5E,0x90,0x47,0x7F,0x28,0x00,0xDD,0x7F,0x20,0xFF,0x21, + 0x01,0x31,0x00,0x2E,0x01,0xD0,0x00,0x2D,0x03,0xD1,0x00,0x2F,0x02,0xD0,0x00,0x2D, + 0x00,0xD1,0x08,0x1A,0x00,0x19,0x88,0x42,0x01,0xDD,0x08,0x46,0xF8,0xBD,0x00,0x28, + 0xFC,0xDA,0x00,0x20,0xF8,0xBD,0xF0,0xB5,0x85,0xB0,0x50,0x4E,0x4A,0x48,0x60,0x30, + 0x80,0x6F,0x01,0x79,0x02,0x91,0xC0,0x78,0x01,0x90,0x00,0x25,0x46,0x48,0x04,0x90, + 0x39,0xE0,0x68,0x00,0x34,0x5E,0x87,0x19,0x14,0x20,0x38,0x5E,0x00,0x90,0x04,0x98, + 0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98,0x40,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11, + 0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,0xFB,0xFB,0x00,0x99,0x40,0x18,0x00,0xB2, + 0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0xB8,0x82,0x38,0x46,0xC0,0x30,0x1C,0x24, + 0x03,0x90,0x04,0x5F,0x08,0x27,0xC7,0x5F,0x04,0x98,0x80,0x7A,0xA0,0x42,0x10,0xDA, + 0x78,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0, + 0xDF,0xFB,0xC0,0x19,0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0x03,0x99, + 0x08,0x81,0x6D,0x1C,0xED,0xB2,0x02,0x98,0x85,0x42,0xC2,0xD3,0x00,0x27,0x3A,0xE0, + 0x38,0x46,0x14,0x21,0x48,0x43,0x34,0x5E,0x85,0x19,0x02,0x20,0x28,0x5E,0x00,0x90, + 0x04,0x98,0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98,0x40,0x00,0xA0,0x42,0x0D,0xDA, + 0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0,0xBA,0xFB,0x00,0x99,0x40,0x18, + 0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2,0x68,0x80,0x12,0x24,0x2C,0x5F, + 0x10,0x20,0x28,0x5E,0x00,0x90,0x04,0x98,0x80,0x7A,0xA0,0x42,0x11,0xDA,0x00,0x98, + 0x40,0x00,0xA0,0x42,0x0D,0xDA,0x21,0x11,0x10,0x20,0x41,0x1A,0x20,0x46,0x00,0xF0, + 0x9F,0xFB,0x00,0x99,0x40,0x18,0x00,0xB2,0xA0,0x42,0x01,0xDB,0x64,0x1E,0x20,0xB2, + 0x28,0x82,0x7F,0x1C,0xFF,0xB2,0x01,0x98,0x87,0x42,0xC1,0xD3,0xDE,0xE4,0x00,0x00, + 0x08,0x00,0x00,0x20,0x70,0x17,0x00,0x00,0x05,0x00,0x00,0x20,0x02,0x00,0x00,0x20, + 0x03,0x00,0x00,0x20,0x70,0x03,0x00,0x20,0x10,0x0A,0x00,0x20,0x0C,0x00,0x00,0x20, + 0x00,0x10,0x00,0x40,0x64,0x00,0x00,0x20,0x50,0x00,0x00,0x20,0x68,0x06,0x00,0x20, + 0xF8,0xB5,0xF7,0x4C,0xA3,0x88,0xCF,0x20,0x03,0x40,0x07,0x21,0xF5,0x48,0x09,0x02, + 0x42,0x18,0x35,0x21,0x49,0x01,0x45,0x18,0x0D,0x21,0xC9,0x01,0x40,0x18,0xF2,0x4F, + 0xD6,0x6F,0x81,0x6B,0x01,0x2B,0x1C,0xD0,0x05,0x2B,0x08,0xD0,0x00,0x22,0x09,0x2B, + 0x01,0xD0,0xA2,0x80,0xF8,0xBD,0x6A,0x75,0xE2,0x88,0xD2,0x07,0x04,0xD0,0xB9,0x42, + 0x05,0xD1,0xA5,0x20,0xE0,0x80,0x09,0xE0,0x10,0x20,0xA0,0x80,0xF8,0xBD,0x72,0x5C, + 0xE2,0x80,0x49,0x1C,0x81,0x63,0x51,0x29,0x00,0xD3,0x87,0x63,0x14,0x20,0xA0,0x80, + 0xF8,0xBD,0x6B,0x7D,0x02,0x2B,0x56,0xD2,0x00,0x2B,0x18,0xD0,0xE3,0x88,0x09,0x02, + 0xC9,0x18,0x8E,0xB2,0xD1,0x21,0x09,0x02,0x71,0x1A,0x20,0x29,0x14,0xD8,0xF0,0xB2, + 0x07,0xF0,0x7A,0xFE,0xD9,0x48,0x86,0x42,0x4F,0xD1,0x01,0x20,0x0D,0xF0,0x4C,0xF9, + 0xD7,0x49,0x18,0x20,0x08,0x74,0xD7,0x49,0x01,0x20,0x08,0x72,0x45,0xE0,0xD6,0x49, + 0xD1,0x67,0xE1,0x88,0x81,0x63,0x40,0xE0,0xD0,0x49,0xCE,0x39,0x8E,0x42,0x16,0xD1, + 0xD2,0x48,0x01,0x68,0xD0,0x48,0x0A,0x0E,0x40,0x30,0x02,0x70,0x0A,0x0C,0x42,0x70, + 0x0A,0x0A,0x82,0x70,0xC1,0x70,0x01,0x78,0x42,0x78,0x89,0x18,0x82,0x78,0xC3,0x78, + 0xD2,0x18,0x89,0x18,0xA5,0x31,0x0A,0x0A,0x02,0x71,0x41,0x71,0x25,0xE0,0xC8,0x49, + 0x71,0x18,0x23,0x29,0x04,0xD8,0x81,0x63,0xEF,0x20,0x40,0x01,0xD0,0x67,0x1C,0xE0, + 0xC3,0x49,0x30,0x39,0x71,0x18,0x20,0x29,0x04,0xD8,0x81,0x63,0x77,0x20,0x80,0x01, + 0xD0,0x67,0x12,0xE0,0x0D,0x21,0x09,0x03,0x71,0x1A,0x50,0x29,0x01,0xD8,0x81,0x63, + 0x0B,0xE0,0x87,0x63,0x09,0xE0,0xB9,0x42,0x07,0xD0,0xE2,0x88,0x72,0x54,0x81,0x6B, + 0x49,0x1C,0x81,0x63,0x51,0x29,0x00,0xD3,0x87,0x63,0x68,0x7D,0x40,0x1C,0x68,0x75, + 0x10,0x20,0xA0,0x80,0xF8,0xBD,0xF7,0xB5,0x8C,0xB0,0xAD,0x48,0x20,0x38,0x0B,0x90, + 0x80,0x6F,0x07,0x79,0x83,0x79,0x5B,0x1E,0xDB,0xB2,0x01,0x93,0xAD,0x4B,0x1B,0x78, + 0x8B,0x42,0x02,0xD2,0xAB,0x4B,0x19,0x70,0x04,0xE0,0xAA,0x4C,0x8B,0x42,0x01,0xD9, + 0xFF,0x23,0x23,0x70,0x43,0x78,0x5B,0x00,0x05,0x93,0xB2,0x23,0xC3,0x5E,0x04,0x93, + 0x9F,0x48,0x80,0x38,0xC4,0x7A,0x9B,0x48,0x03,0x46,0xDC,0x33,0x0A,0x93,0x91,0x23, + 0x9B,0x00,0xC3,0x18,0x28,0x30,0x09,0x93,0x08,0x90,0x01,0x2C,0x20,0xD1,0x08,0x46, + 0x0A,0x9B,0x78,0x43,0xC4,0x18,0x09,0x9B,0xC3,0x18,0x9C,0x46,0x08,0x9B,0xC0,0x18, + 0x86,0x46,0x0C,0x98,0x00,0x23,0x11,0xE0,0x06,0x78,0x26,0x70,0x64,0x1C,0x06,0x78, + 0x65,0x46,0x2E,0x70,0x06,0x78,0x75,0x46,0x80,0x1C,0x2E,0x70,0x65,0x46,0x6D,0x1C, + 0xAC,0x46,0x75,0x46,0x6D,0x1C,0xAE,0x46,0x5B,0x1C,0x5B,0xB2,0xBB,0x42,0xEB,0xDB, + 0x08,0x46,0x78,0x43,0x08,0x9B,0x07,0x90,0xC0,0x18,0x86,0x46,0x0C,0x98,0x84,0x46, + 0x00,0x20,0x35,0xE0,0x63,0x46,0x1B,0x88,0x74,0x46,0x24,0x78,0xE3,0x1A,0x1B,0xB2, + 0x05,0x9C,0xA3,0x42,0x02,0xDA,0x04,0x9C,0xA3,0x42,0x21,0xDC,0x01,0x24,0x8C,0x40, + 0x13,0x68,0x55,0x68,0xE6,0x17,0x23,0x43,0x35,0x43,0x55,0x60,0x2C,0x46,0x13,0x60, + 0x00,0x29,0x08,0xD0,0x25,0x46,0x4E,0x1E,0x01,0x24,0xB4,0x40,0xE6,0x17,0x23,0x43, + 0x35,0x43,0x55,0x60,0x13,0x60,0x01,0x9B,0x99,0x42,0x09,0xD2,0x4E,0x1C,0x01,0x23, + 0xB3,0x40,0x14,0x68,0x55,0x68,0xDE,0x17,0x1C,0x43,0x35,0x43,0x55,0x60,0x14,0x60, + 0x73,0x46,0x5B,0x1C,0x9E,0x46,0x63,0x46,0x9B,0x1C,0x9C,0x46,0x40,0x1C,0x40,0xB2, + 0xB8,0x42,0xC7,0xDB,0x07,0x99,0x0A,0x98,0x0D,0x18,0x07,0x99,0x09,0x98,0x0E,0x18, + 0x0C,0x9C,0x0B,0x98,0x80,0x6F,0x80,0x30,0x00,0x7E,0x01,0x28,0x03,0xD1,0x65,0x49, + 0x09,0x78,0xFF,0x29,0x02,0xD0,0x02,0x28,0x1D,0xD0,0x20,0xE0,0x00,0x23,0x16,0xE0, + 0x00,0x22,0xA2,0x5E,0x28,0x78,0x31,0x78,0x30,0x70,0x2A,0x70,0x88,0x42,0x02,0xDD, + 0x84,0x46,0x08,0x46,0x61,0x46,0x82,0x42,0x01,0xDC,0x20,0x80,0x02,0xE0,0x8A,0x42, + 0x00,0xDB,0x21,0x80,0x6D,0x1C,0x76,0x1C,0xA4,0x1C,0x5B,0x1C,0x5B,0xB2,0xBB,0x42, + 0xE6,0xDB,0x0F,0xB0,0x60,0xE4,0x53,0x48,0x00,0x78,0xFF,0x28,0x01,0xD0,0x00,0x20, + 0x2D,0xE0,0x00,0x20,0x06,0x90,0x1E,0xE0,0x00,0x21,0x61,0x5E,0x03,0x91,0x28,0x78, + 0x31,0x78,0x02,0x91,0x03,0x99,0x08,0x18,0x02,0x99,0x40,0x18,0x0B,0x99,0x4A,0x6C, + 0x03,0x21,0x90,0x47,0x00,0xB2,0x30,0x70,0x76,0x1C,0x03,0x99,0x29,0x70,0x6D,0x1C, + 0x02,0x99,0x4A,0x00,0x89,0x18,0x08,0x18,0x80,0x10,0x20,0x80,0xA4,0x1C,0x06,0x98, + 0x40,0x1C,0x40,0xB2,0x06,0x90,0x06,0x98,0xB8,0x42,0xDD,0xDB,0xD1,0xE7,0x21,0x78, + 0xA4,0x1C,0x29,0x70,0x6D,0x1C,0x31,0x70,0x76,0x1C,0x40,0x1C,0x40,0xB2,0xB8,0x42, + 0xF5,0xDB,0xC6,0xE7,0xF0,0xB5,0x85,0xB0,0x31,0x4E,0x20,0x3E,0xB0,0x6F,0xC1,0x7A, + 0x00,0x91,0x35,0x4C,0x04,0x94,0x1B,0x21,0x2A,0x48,0x89,0x01,0x47,0x18,0x35,0x21, + 0x49,0x01,0x45,0x18,0x00,0x99,0x24,0x23,0x30,0x4A,0x59,0x43,0x08,0x18,0x80,0x18, + 0x03,0x90,0x64,0xE0,0x20,0x78,0x0F,0x28,0x60,0xD0,0xE0,0x79,0x01,0x06,0x0F,0xD4, + 0x02,0x28,0x19,0xD0,0xE8,0x7C,0x02,0x28,0x01,0xD2,0x20,0x20,0xA0,0x70,0xFF,0x20, + 0x20,0x71,0x60,0x71,0xE0,0x78,0x79,0x7E,0x88,0x42,0x01,0xD8,0x00,0x20,0xE0,0x71, + 0xE0,0x79,0x40,0x06,0x40,0x0E,0xE0,0x71,0x00,0x28,0x01,0xD0,0x40,0x1E,0xE0,0x71, + 0xE0,0x79,0x00,0x28,0x3C,0xD0,0x41,0xE0,0x0E,0x20,0x20,0x5E,0x02,0x90,0x10,0x20, + 0x20,0x5E,0x01,0x90,0x09,0x21,0x20,0x46,0x08,0xF0,0xA4,0xFA,0x0E,0x21,0x61,0x5E, + 0x02,0x98,0x08,0x1A,0x00,0xD5,0x40,0x42,0x01,0xB2,0x10,0x22,0xA2,0x5E,0x01,0x98, + 0x10,0x1A,0x00,0xD5,0x40,0x42,0x40,0x18,0x00,0xB2,0xB1,0x6F,0x80,0x31,0xC9,0x8D, + 0x89,0x08,0x81,0x42,0xCB,0xDD,0x02,0x98,0xE0,0x81,0x01,0x98,0x20,0x82,0xC6,0xE7, + 0x00,0x20,0x00,0x40,0x70,0x03,0x00,0x20,0xFF,0xFF,0x00,0x00,0x0E,0xD1,0x00,0x00, + 0x90,0x0A,0x00,0x20,0x64,0x00,0x00,0x20,0x10,0x00,0x00,0x20,0x0C,0x00,0x00,0x20, + 0x10,0x2E,0xFF,0xFF,0x00,0x00,0x00,0x20,0x3E,0x09,0x00,0x20,0xCE,0x05,0x00,0x00, + 0x60,0x78,0x80,0x08,0x80,0x00,0x60,0x70,0x00,0x20,0xA0,0x70,0x24,0x34,0x03,0x98, + 0xA0,0x42,0x97,0xD8,0x00,0x21,0x00,0x22,0xEA,0x74,0x04,0x98,0x10,0xE0,0x04,0x78, + 0x00,0x9B,0x9C,0x42,0x0A,0xD2,0xC3,0x78,0x7C,0x7E,0x5B,0x06,0x5B,0x0E,0xA3,0x42, + 0x04,0xD9,0x83,0x78,0x20,0x2B,0x01,0xD0,0x01,0x21,0x04,0xE0,0x82,0x70,0x24,0x30, + 0x03,0x9B,0x83,0x42,0xEB,0xD8,0x00,0x29,0x2F,0xD0,0x04,0x98,0x2A,0xE0,0x82,0x70, + 0x03,0x78,0x00,0x99,0x8B,0x42,0x24,0xD2,0xC1,0x78,0x7B,0x7E,0x49,0x06,0x49,0x0E, + 0x99,0x42,0x1E,0xD9,0x01,0x21,0x81,0x70,0xE9,0x7C,0x49,0x1C,0xE9,0x74,0x0E,0x23, + 0xC3,0x5E,0x00,0x2B,0x01,0xDA,0xC2,0x81,0x06,0xE0,0xB1,0x6F,0x80,0x31,0x0C,0x8C, + 0xA3,0x42,0x01,0xDD,0x09,0x8C,0xC1,0x81,0x10,0x23,0xC3,0x5E,0x00,0x2B,0x01,0xDA, + 0x02,0x82,0x06,0xE0,0xB1,0x6F,0x80,0x31,0x4C,0x8C,0xA3,0x42,0x01,0xDD,0x49,0x8C, + 0x01,0x82,0x24,0x30,0x03,0x99,0x81,0x42,0xD1,0xD8,0x87,0xE5,0xF0,0xB5,0x80,0x4A, + 0x93,0x6F,0x1C,0x7F,0x62,0x00,0xFF,0x28,0x2D,0xD0,0x24,0x25,0x68,0x43,0x7D,0x4D, + 0x7D,0x4E,0x40,0x19,0x80,0x19,0x06,0x26,0x71,0x43,0x49,0x19,0x7A,0x4D,0x24,0x3D, + 0x4E,0x19,0x14,0x25,0x45,0x5F,0x00,0x2D,0x00,0xDA,0x6D,0x42,0x16,0x21,0x41,0x5E, + 0x00,0x29,0x00,0xDA,0x49,0x42,0x6D,0x18,0x74,0x49,0x8D,0x42,0x00,0xD3,0x00,0x25, + 0x0E,0x27,0x31,0x88,0xC7,0x5F,0xC9,0x1B,0x00,0xD5,0x49,0x42,0x10,0x27,0x76,0x88, + 0xC7,0x5F,0xF6,0x1B,0x00,0xD5,0x76,0x42,0x89,0x19,0x8C,0x42,0x2C,0xD8,0x84,0x79, + 0x01,0x2C,0x02,0xD0,0x07,0xE0,0x00,0x20,0xF0,0xBD,0x2D,0x27,0xFF,0x5C,0xC6,0x79, + 0x7F,0x1E,0xBE,0x42,0x1E,0xDB,0x62,0x4E,0xB6,0x6F,0x80,0x36,0x01,0x2C,0x08,0xD1, + 0xDB,0x7E,0xAB,0x42,0x05,0xD3,0xC0,0x78,0x73,0x7B,0x98,0x42,0x01,0xD8,0x0A,0x28, + 0x10,0xD2,0x01,0x2C,0x06,0xD1,0x91,0x42,0x04,0xD3,0x5D,0x4B,0x70,0x7B,0x1B,0x88, + 0x98,0x42,0x07,0xD2,0x01,0x2C,0x02,0xD1,0x50,0x00,0x88,0x42,0x02,0xD9,0x90,0x00, + 0x88,0x42,0x01,0xD8,0x00,0x20,0xF0,0xBD,0x01,0x20,0xF0,0xBD,0xF0,0xB5,0x85,0xB0, + 0x54,0x49,0x4F,0x48,0x40,0x30,0x80,0x78,0x05,0x28,0x7D,0xD0,0x52,0x4D,0xA8,0x1D, + 0x01,0x90,0x80,0x1D,0x00,0x90,0x00,0x20,0x49,0x4A,0x04,0x92,0xFF,0x22,0x0F,0x23, + 0x07,0xE0,0x2A,0x54,0xCC,0x79,0x00,0x2C,0x00,0xD1,0x0B,0x70,0x40,0x1C,0xC0,0xB2, + 0x24,0x31,0x04,0x9C,0xA4,0x6F,0xE4,0x7A,0x84,0x42,0xF2,0xD8,0x00,0x27,0x40,0x4E, + 0x60,0x3E,0xF0,0x7B,0x00,0x28,0x49,0xD0,0x2A,0x46,0x03,0xA9,0x00,0x98,0x08,0xF0, + 0x19,0xFD,0x07,0x46,0x38,0x00,0x0A,0xD0,0x01,0x2F,0x15,0xD0,0x68,0x46,0x02,0x7B, + 0xF3,0x7B,0x01,0x99,0x00,0x98,0x08,0xF0,0x1B,0xFC,0x00,0x24,0x33,0xE0,0x00,0x24, + 0x06,0xE0,0x22,0x46,0xFF,0x21,0x01,0x20,0x08,0xF0,0x00,0xFB,0x64,0x1C,0xE4,0xB2, + 0xF0,0x7B,0xA0,0x42,0xF5,0xD8,0x29,0xE0,0x2C,0x78,0x00,0x21,0x20,0x46,0xFF,0xF7, + 0x55,0xFF,0x00,0x28,0x01,0xD0,0x00,0x20,0x00,0xE0,0x01,0x20,0x00,0x22,0x21,0x46, + 0x08,0xF0,0xEC,0xFA,0x1A,0xE0,0x01,0x98,0x00,0x5D,0xFF,0x28,0x02,0xD0,0x28,0x5C, + 0x02,0x90,0x01,0xE0,0xFF,0x20,0x02,0x90,0x21,0x46,0x02,0x98,0xFF,0xF7,0x3E,0xFF, + 0x00,0x28,0x01,0xD0,0x00,0x20,0x00,0xE0,0x01,0x20,0x22,0x46,0x02,0x99,0x08,0xF0, + 0xD5,0xFA,0x64,0x1C,0xE4,0xB2,0xF0,0x7B,0xA0,0x42,0xE4,0xD8,0x38,0x46,0xFF,0xF7, + 0x61,0xFE,0xF0,0x7B,0x1A,0x4C,0x00,0x28,0x06,0xD1,0x20,0x88,0x7D,0x21,0xC9,0x00, + 0x88,0x42,0x01,0xD2,0x40,0x1C,0x20,0x80,0xF0,0x7C,0x00,0x28,0x04,0xD0,0x00,0x22, + 0x00,0x20,0x10,0x4D,0x17,0x26,0x00,0xE0,0x16,0xE0,0x04,0x99,0xB6,0x01,0x89,0x6F, + 0xCB,0x7A,0x0B,0xE0,0x24,0x21,0x41,0x43,0x49,0x19,0x89,0x19,0x0F,0x7C,0x01,0x2F, + 0x02,0xD1,0xC9,0x7B,0x03,0x29,0x08,0xD0,0x40,0x1C,0xC0,0xB2,0x83,0x42,0xF1,0xD8, + 0x00,0x2A,0x01,0xD1,0x00,0x20,0x20,0x80,0x88,0xE4,0x52,0x1C,0xD2,0xB2,0xF7,0xE7, + 0x70,0x0A,0x00,0x20,0x70,0x03,0x00,0x20,0xCE,0x05,0x00,0x00,0xFF,0xFF,0x00,0x00, + 0x06,0x00,0x00,0x20,0x3E,0x09,0x00,0x20,0x68,0x06,0x00,0x20,0x00,0x22,0x03,0x09, + 0x8B,0x42,0x2C,0xD3,0x03,0x0A,0x8B,0x42,0x11,0xD3,0x00,0x23,0x9C,0x46,0x4E,0xE0, + 0x03,0x46,0x0B,0x43,0x3C,0xD4,0x00,0x22,0x43,0x08,0x8B,0x42,0x31,0xD3,0x03,0x09, + 0x8B,0x42,0x1C,0xD3,0x03,0x0A,0x8B,0x42,0x01,0xD3,0x94,0x46,0x3F,0xE0,0xC3,0x09, + 0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41,0x83,0x09,0x8B,0x42,0x01,0xD3, + 0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42,0x01,0xD3,0x4B,0x01,0xC0,0x1A, + 0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01,0xC0,0x1A,0x52,0x41,0xC3,0x08, + 0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41,0x83,0x08,0x8B,0x42,0x01,0xD3, + 0x8B,0x00,0xC0,0x1A,0x52,0x41,0x43,0x08,0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A, + 0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46,0x52,0x41,0x10,0x46,0x70,0x47,0x5D,0xE0, + 0xCA,0x0F,0x00,0xD0,0x49,0x42,0x03,0x10,0x00,0xD3,0x40,0x42,0x53,0x40,0x00,0x22, + 0x9C,0x46,0x03,0x09,0x8B,0x42,0x2D,0xD3,0x03,0x0A,0x8B,0x42,0x12,0xD3,0xFC,0x22, + 0x89,0x01,0x12,0xBA,0x03,0x0A,0x8B,0x42,0x0C,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42, + 0x08,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42,0x04,0xD3,0x89,0x01,0x3A,0xD0,0x92,0x11, + 0x00,0xE0,0x89,0x09,0xC3,0x09,0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41, + 0x83,0x09,0x8B,0x42,0x01,0xD3,0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42, + 0x01,0xD3,0x4B,0x01,0xC0,0x1A,0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01, + 0xC0,0x1A,0x52,0x41,0xC3,0x08,0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41, + 0x83,0x08,0x8B,0x42,0x01,0xD3,0x8B,0x00,0xC0,0x1A,0x52,0x41,0xD9,0xD2,0x43,0x08, + 0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A,0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46, + 0x63,0x46,0x52,0x41,0x5B,0x10,0x10,0x46,0x01,0xD3,0x40,0x42,0x00,0x2B,0x00,0xD5, + 0x49,0x42,0x70,0x47,0x63,0x46,0x5B,0x10,0x00,0xD3,0x40,0x42,0x01,0xB5,0x00,0x20, + 0xC0,0x46,0xC0,0x46,0x02,0xBD,0x75,0x46,0x00,0xF0,0x22,0xF8,0xAE,0x46,0x05,0x00, + 0x69,0x46,0x53,0x46,0xC0,0x08,0xC0,0x00,0x85,0x46,0x18,0xB0,0x20,0xB5,0xFE,0xF7, + 0x87,0xFF,0x60,0xBC,0x00,0x27,0x49,0x08,0xB6,0x46,0x00,0x26,0xC0,0xC5,0xC0,0xC5, + 0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0x40,0x3D,0x49,0x00, + 0x8D,0x46,0x70,0x47,0x04,0x46,0xC0,0x46,0xC0,0x46,0x20,0x46,0xFE,0xF7,0xDD,0xFD, + 0x00,0x48,0x70,0x47,0x70,0x00,0x00,0x20,0x01,0x49,0x18,0x20,0xAB,0xBE,0xFE,0xE7, + 0x26,0x00,0x02,0x00,0x70,0x47,0x00,0x00,0x23,0x0B,0x28,0x0C,0x0A,0x0A,0x0C,0x00, + 0x02,0x02,0x40,0x06,0x00,0x00,0x00,0x01,0x08,0x08,0x10,0x85,0x1C,0x0E,0x07,0x03, + 0x0A,0x1E,0x64,0x21,0x42,0x42,0x08,0x02,0x16,0x00,0x00,0x00,0x10,0x06,0x02,0x00, + 0x06,0x04,0x14,0x14,0x0A,0x05,0x28,0x1E,0x3C,0x64,0x02,0x04,0x08,0x01,0x02,0x04, + 0x04,0x02,0x01,0x08,0x01,0x08,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x04,0x02,0x01,0x08,0x04,0x02,0x01,0x08,0x04,0x02,0x01,0x01,0x01,0x01, + 0xD8,0xE2,0xF6,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x02,0x04,0x03,0x08,0x09, + 0x09,0x00,0x3C,0x0A,0x01,0x02,0x02,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, + 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3C, + 0x3C,0x50,0x00,0x14,0xC8,0x14,0x00,0x01,0x84,0x04,0x02,0x02,0x5A,0x00,0x5A,0x01, + 0x02,0x06,0x01,0x01,0x00,0x00,0x00,0x00,0xE0,0x01,0x20,0x03,0xBE,0x00,0x09,0x00, + 0x90,0x01,0x01,0x01,0x00,0x01,0x20,0x00,0x00,0x00,0xF5,0xFF,0x52,0x01,0x92,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0xAA,0x42,0x00,0x00, + 0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x15,0x10,0x00,0x40, + 0x15,0x10,0x00,0x40,0x15,0x10,0x00,0x40,0x25,0x10,0x00,0x40,0x25,0x10,0x00,0x40, + 0x25,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x19,0x10,0x00,0x40,0x15,0x10,0x00,0x40, + 0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40, + 0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40, + 0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40, + 0x21,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x21,0x10,0x00,0x40,0x1D,0x10,0x00,0x40, + 0x1D,0x10,0x00,0x40,0x1D,0x10,0x00,0x40,0x1D,0x10,0x00,0x40,0x19,0x10,0x00,0x40, + 0x19,0x10,0x00,0x40,0x19,0x10,0x00,0x40,0x60,0x10,0x00,0x40,0x5C,0x10,0x00,0x40, + 0x58,0x10,0x00,0x40,0x54,0x10,0x00,0x40,0x50,0x10,0x00,0x40,0x4C,0x10,0x00,0x40, + 0x48,0x10,0x00,0x40,0x44,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x64,0x10,0x00,0x40, + 0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40,0x11,0x10,0x00,0x40, + 0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40, + 0x44,0x10,0x00,0x40,0x48,0x10,0x00,0x40,0x4C,0x10,0x00,0x40,0x50,0x10,0x00,0x40, + 0x54,0x10,0x00,0x40,0x58,0x10,0x00,0x40,0x48,0x10,0x00,0x40,0x44,0x10,0x00,0x40, + 0x40,0x10,0x00,0x40,0x64,0x10,0x00,0x40,0x60,0x10,0x00,0x40,0x5C,0x10,0x00,0x40, + 0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40, + 0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40, + 0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40,0x40,0x10,0x00,0x40, + 0xFF,0xFF,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0xFF,0x00,0xFF, + 0xFF,0xFF,0xFF,0x00,0xFF,0x01,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x76,0xA5,0x18,0xA7,0x23,0xA1,0x45,0x63,0x65,0x07,0x56,0xAA, + 0x78,0xA1,0x21,0x00,0x00,0x00,0x00,0x00,0x21,0xAA,0x43,0xAA,0x56,0xAA,0x81,0xA7, + 0x21,0x00,0x67,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0x87,0xAA,0x32,0xAA,0x87,0xAA, + 0x32,0xAA,0x87,0xA1,0x71,0x06,0x87,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0x00,0x00, + 0x87,0xAA,0x23,0xAA,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xAA,0x87,0xAA,0x51,0xA6, + 0x47,0x06,0x45,0x00,0x28,0xA1,0x76,0xAA,0x12,0xA8,0x00,0x00,0x00,0x00,0x34,0xAA, + 0x56,0xAA,0x78,0xA1,0x21,0x00,0x00,0x00,0x67,0xAA,0x23,0xAA,0xA1,0xAA,0x87,0xAA, + 0x32,0xAA,0x67,0xAA,0x23,0xAA,0x87,0xAA,0x32,0xAA,0xA1,0xAA,0x21,0xAA,0x56,0xAA, + 0x81,0xA7,0x21,0xAA,0x00,0x00,0x34,0xAA,0x65,0xAA,0x87,0xAA,0x51,0x46,0x47,0x03, + 0xA8,0xAA,0x21,0xAA,0x43,0xAA,0x56,0xAA,0x81,0xA7,0x34,0xAA,0x76,0xA5,0x18,0xA7, + 0x23,0xA1,0x45,0xA3,0x23,0xA4,0x21,0xA8,0x87,0xA6,0x32,0xA4,0x78,0x21,0x76,0xA5, + 0x23,0xA1,0x45,0x63,0x65,0x07,0x00,0x00,0x01,0x00,0x00,0xFF,0xFF,0x00,0x00,0x01, + 0x02,0x02,0x02,0x01,0x02,0x02,0x01,0x01,0x01,0x02,0x01,0x02,0x01,0x02,0x02,0x02, + 0x01,0x01,0x02,0x02,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02,0xFC,0x1D,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x00,0x00,0x00, + 0x98,0x00,0x00,0x00,0x0C,0x1E,0x00,0x00,0x10,0x00,0x00,0x20,0xE0,0x0A,0x00,0x00, + 0xB4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5B,0x5A,0x35,0x35,0xA5,0xA5,0xCA,0xCA,0x88,0x77,0x66,0x55, + 0x44,0x33,0x22,0x11,0x0C,0x00,0x0A,0x00,0xE0,0x01,0x20,0x03,0xEE,0x2F,0xCA,0xCA, + 0x02,0x03,0x00,0x00,0x11,0x18,0xA8,0x00,0x01,0x00,0x00,0x01,0xE5,0xFE,0xCA,0x8A, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst3240_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst3240_fw.h new file mode 100644 index 000000000000..3d1eb2d37ccb --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst3240_fw.h @@ -0,0 +1,1045 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst3240_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { + 0xFC,0x1F,0x00,0x20,0x5D,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xB9,0x08,0x00,0x00,0xBB,0x08,0x00,0x00,0xE9,0x08,0x00,0x00, + 0x35,0x0A,0x00,0x00,0x47,0x0A,0x00,0x00,0x4D,0x0A,0x00,0x00,0x4F,0x0A,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xF0,0x02,0xF8,0x00,0xF0,0x40,0xF8,0x0C,0xA0,0x30,0xC8,0x08,0x38,0x24,0x18, + 0x2D,0x18,0xA2,0x46,0x67,0x1E,0xAB,0x46,0x54,0x46,0x5D,0x46,0xAC,0x42,0x01,0xD1, + 0x00,0xF0,0x32,0xF8,0x7E,0x46,0x0F,0x3E,0x0F,0xCC,0xB6,0x46,0x01,0x26,0x33,0x42, + 0x00,0xD0,0xFB,0x1A,0xA2,0x46,0xAB,0x46,0x33,0x43,0x18,0x47,0x18,0x30,0x00,0x00, + 0x38,0x30,0x00,0x00,0x10,0x3A,0x02,0xD3,0x78,0xC8,0x78,0xC1,0xFA,0xD8,0x52,0x07, + 0x01,0xD3,0x30,0xC8,0x30,0xC1,0x01,0xD5,0x04,0x68,0x0C,0x60,0x70,0x47,0x00,0x00, + 0x00,0x23,0x00,0x24,0x00,0x25,0x00,0x26,0x10,0x3A,0x01,0xD3,0x78,0xC1,0xFB,0xD8, + 0x52,0x07,0x00,0xD3,0x30,0xC1,0x00,0xD5,0x0B,0x60,0x70,0x47,0x1F,0xB5,0xC0,0x46, + 0xC0,0x46,0x1F,0xBD,0x10,0xB5,0x10,0xBD,0x02,0xF0,0x75,0xFE,0x11,0x46,0xFF,0xF7, + 0xF5,0xFF,0x00,0xF0,0x82,0xFE,0x02,0xF0,0x8D,0xFE,0x03,0xB4,0xFF,0xF7,0xF2,0xFF, + 0x03,0xBC,0x02,0xF0,0x91,0xFE,0x00,0x00,0x70,0xB5,0x05,0x46,0x0C,0x46,0x16,0x46, + 0x02,0xE0,0x0F,0xCC,0x0F,0xC5,0x10,0x3E,0x10,0x2E,0xFA,0xD2,0x08,0x2E,0x02,0xD3, + 0x03,0xCC,0x03,0xC5,0x08,0x3E,0x04,0x2E,0x07,0xD3,0x01,0xCC,0x01,0xC5,0x36,0x1F, + 0x03,0xE0,0x21,0x78,0x29,0x70,0x64,0x1C,0x6D,0x1C,0x76,0x1E,0xF9,0xD2,0x70,0xBD, + 0x07,0x49,0x06,0x48,0xC8,0x60,0xBF,0xF3,0x40,0x8F,0xFE,0xE7,0x10,0xB5,0x00,0xF0, + 0x54,0xFE,0x10,0xBD,0x0A,0x46,0x03,0x46,0x70,0x47,0x00,0x00,0x04,0x00,0xFA,0x05, + 0x00,0xED,0x00,0xE0,0xFF,0xB5,0x01,0x20,0x81,0xB0,0x00,0x90,0x01,0x2A,0x01,0xD1, + 0x00,0x20,0x00,0x90,0x00,0x27,0x71,0xE0,0x04,0x98,0xB9,0x00,0x0E,0x18,0x31,0x68, + 0x3F,0x20,0x08,0x70,0x30,0x68,0xFF,0x21,0x20,0x38,0xC1,0x77,0x01,0x20,0xDA,0x4C, + 0xC0,0x02,0x20,0x82,0xD9,0x48,0x60,0x82,0xD9,0x48,0x20,0x81,0xD8,0x48,0xFD,0x30, + 0x60,0x81,0xD8,0x48,0x3A,0x46,0x43,0x68,0x03,0x21,0x00,0x98,0x98,0x47,0xA5,0x04, + 0x68,0x89,0x80,0x21,0x08,0x43,0x68,0x81,0xD3,0x48,0x20,0x80,0x03,0x20,0x20,0x80, + 0x81,0x20,0x00,0x02,0x01,0x21,0xC2,0x68,0x08,0x46,0x90,0x47,0x68,0x89,0x80,0x21, + 0x88,0x43,0x68,0x81,0x00,0x24,0x20,0x25,0xCA,0x49,0x2C,0x43,0x89,0x6B,0xE0,0xB2, + 0x88,0x47,0xC6,0x48,0xC4,0x49,0x40,0x38,0x48,0x82,0x81,0x20,0x00,0x02,0x05,0x21, + 0xC2,0x68,0x64,0x20,0x90,0x47,0xC3,0x48,0xBF,0x49,0xF0,0x38,0x48,0x82,0x81,0x20, + 0x00,0x02,0x05,0x21,0xC2,0x68,0x64,0x20,0x90,0x47,0x30,0x68,0x00,0x78,0x00,0x06, + 0x00,0xD4,0xAC,0x43,0x6D,0x08,0xDF,0xD1,0xB7,0x49,0xB8,0x48,0x48,0x82,0xB9,0x48, + 0x3A,0x46,0x43,0x68,0x01,0x21,0x00,0x98,0x98,0x47,0x31,0x68,0x30,0x20,0x08,0x70, + 0x30,0x68,0x00,0x21,0x20,0x38,0xC1,0x77,0x00,0x2C,0x02,0xD0,0x3F,0x2C,0x02,0xD0, + 0x02,0xE0,0x01,0x24,0x00,0xE0,0x7F,0x24,0x02,0x98,0xB0,0x49,0x04,0x80,0x02,0x98, + 0x80,0x1C,0x02,0x90,0xAA,0x20,0x88,0x80,0x7F,0x1C,0xFF,0xB2,0x01,0x98,0x87,0x42, + 0x8A,0xD3,0x01,0x21,0x89,0x07,0x48,0x89,0x80,0x22,0x10,0x43,0x48,0x81,0x05,0xB0, + 0xF0,0xBD,0xFE,0xB5,0x01,0x46,0xA0,0x48,0x02,0x8A,0xC3,0x14,0x1A,0x43,0x02,0x82, + 0x02,0x8A,0x83,0x15,0x9A,0x43,0x02,0x82,0xA1,0x4A,0xCC,0x23,0x53,0x74,0x63,0x23, + 0x13,0x74,0x00,0x22,0x82,0x81,0x9F,0x4E,0x14,0x46,0xF0,0x6A,0x05,0x79,0xC7,0x78, + 0x68,0x00,0x40,0x18,0x00,0x91,0x01,0x90,0x07,0xE0,0x96,0x48,0x01,0x21,0x43,0x68, + 0x22,0x46,0x00,0x20,0x98,0x47,0x64,0x1C,0xE4,0xB2,0xAC,0x42,0xF5,0xD3,0x00,0x24, + 0x07,0xE0,0x90,0x48,0x01,0x21,0x43,0x68,0x22,0x46,0x08,0x46,0x98,0x47,0x64,0x1C, + 0xE4,0xB2,0xBC,0x42,0xF5,0xD3,0x01,0x22,0x33,0x68,0x28,0x46,0x00,0x99,0xFF,0xF7, + 0x41,0xFF,0x00,0x22,0x73,0x68,0x38,0x46,0x01,0x99,0xFF,0xF7,0x3B,0xFF,0x82,0x49, + 0x00,0x20,0x48,0x82,0x08,0x82,0xFE,0xBD,0xF0,0xB5,0x86,0x49,0x8F,0xB0,0xC9,0x6A, + 0x84,0x4C,0x8A,0x79,0x0E,0x92,0x09,0x79,0x0D,0x91,0x81,0x21,0x09,0x02,0x80,0x3C, + 0x81,0x4E,0x7C,0x4F,0xCA,0x68,0x00,0x28,0x0D,0xD0,0x7D,0x48,0x33,0x21,0x41,0x74, + 0x03,0x21,0x01,0x74,0x77,0x20,0x70,0x72,0x41,0x20,0x30,0x72,0x26,0x21,0x78,0x20, + 0x90,0x47,0xA5,0x68,0x1A,0xE0,0x30,0x7A,0xBF,0x21,0x08,0x40,0x30,0x72,0x26,0x21, + 0x78,0x20,0xA5,0x69,0x90,0x47,0x00,0x22,0x7B,0x68,0x11,0x46,0x01,0x20,0x98,0x47, + 0x00,0x24,0x01,0x22,0x3B,0x6A,0x80,0x21,0x01,0xA8,0x98,0x47,0x64,0x1C,0xE4,0xB2, + 0x32,0x2C,0xF6,0xD3,0x30,0x7A,0x81,0x21,0x08,0x43,0x30,0x72,0x6B,0x49,0x00,0x20, + 0x48,0x73,0x39,0x68,0x02,0x20,0x88,0x47,0x62,0x48,0x00,0x21,0x40,0x38,0xC2,0x6B, + 0x02,0x20,0x90,0x47,0x00,0x24,0x1F,0xE0,0x00,0x21,0x7B,0x68,0x22,0x46,0x01,0x20, + 0x98,0x47,0x20,0x20,0x00,0x90,0x5B,0x48,0x23,0x46,0x40,0x30,0xC6,0x69,0x29,0x46, + 0x01,0xA8,0x0D,0x9A,0xB0,0x47,0x0D,0x98,0x7B,0x68,0x40,0x00,0x45,0x19,0x01,0x21, + 0x22,0x46,0x08,0x46,0x98,0x47,0x55,0x49,0xAA,0x20,0x88,0x80,0x57,0x49,0x00,0x20, + 0x60,0x31,0x08,0x77,0x64,0x1C,0xE4,0xB2,0x0E,0x98,0x84,0x42,0xDC,0xD3,0x4D,0x48, + 0x00,0x21,0x40,0x38,0xC2,0x6B,0x03,0x20,0x90,0x47,0x39,0x68,0x00,0x20,0x88,0x47, + 0x0F,0xB0,0xF0,0xBD,0xF0,0xB5,0x47,0x48,0xB5,0xB0,0x80,0x6A,0x80,0x47,0x4A,0x4C, + 0x20,0x7C,0x48,0x4D,0xE9,0x6A,0x20,0x31,0xCA,0x79,0x01,0x21,0x91,0x40,0x88,0x43, + 0x20,0x74,0x81,0x27,0x3F,0x02,0x39,0x69,0x32,0x20,0x88,0x47,0x00,0x26,0x66,0x72, + 0x20,0x7A,0xBF,0x21,0x08,0x40,0x20,0x72,0x80,0x20,0x20,0x72,0x26,0x21,0xFA,0x68, + 0x64,0x20,0x90,0x47,0x37,0x48,0x01,0x69,0x00,0x20,0x88,0x47,0x3C,0x4F,0x00,0x96, + 0x04,0xE0,0x00,0x98,0x40,0x1C,0x00,0x90,0xB8,0x42,0x02,0xD2,0x20,0x7A,0x00,0x07, + 0xF7,0xD5,0x30,0x48,0x40,0x30,0x80,0x69,0x80,0x47,0x34,0x4C,0x60,0x34,0x4E,0xE0, + 0x00,0x98,0x14,0x28,0x29,0xD3,0xB8,0x42,0x27,0xD2,0x30,0x48,0x80,0x30,0x86,0x77, + 0x00,0xF0,0x8A,0xFE,0x24,0x48,0x2F,0x49,0x41,0x80,0x10,0x21,0xC1,0x80,0x11,0x21, + 0x49,0x01,0x41,0x81,0x71,0x21,0x09,0x01,0x01,0x81,0xE8,0x6A,0x90,0x21,0x40,0x30, + 0x80,0x7C,0x40,0x06,0x40,0x0E,0x08,0x43,0x21,0x49,0x88,0x74,0x23,0x48,0x40,0x30, + 0x00,0x7A,0xEF,0x28,0x05,0xD0,0x00,0x20,0xFF,0xF7,0x2E,0xFF,0x01,0x20,0xFF,0xF7, + 0x2B,0xFF,0x03,0xA8,0xFF,0xF7,0xE5,0xFE,0x1B,0xE0,0x1A,0x49,0x02,0x22,0x80,0x39, + 0x88,0x69,0x89,0x68,0x02,0x91,0x03,0xA9,0x01,0x91,0x21,0x21,0x09,0x01,0x02,0xF0, + 0xB4,0xFB,0x00,0x98,0x14,0x28,0x01,0xD8,0x0E,0x22,0x00,0xE0,0x0A,0x22,0x21,0x21, + 0x09,0x01,0x02,0x98,0x02,0xF0,0xA9,0xFB,0x02,0x22,0xC8,0x21,0x01,0x98,0x02,0xF0, + 0xA4,0xFB,0x01,0x20,0xC0,0x03,0x42,0x6A,0x32,0x21,0x03,0xA8,0x90,0x47,0xE0,0x7F, + 0x06,0x28,0xAD,0xD0,0x35,0xB0,0xF0,0xBD,0x00,0x10,0x00,0x40,0xD0,0x82,0x00,0x00, + 0x02,0x02,0x00,0x00,0x80,0x81,0x00,0x00,0x45,0x08,0x00,0x00,0x00,0x02,0x00,0x40, + 0x60,0x12,0x00,0x40,0x44,0x01,0x00,0x20,0x00,0x03,0x00,0x40,0x04,0x00,0x00,0x20, + 0x10,0x27,0x00,0x00,0x82,0x10,0x00,0x00,0x70,0xB5,0xC7,0x4C,0x04,0x20,0xC7,0x4D, + 0x20,0x70,0x2A,0x69,0x21,0x1D,0x90,0x47,0x22,0x46,0x08,0x32,0xD1,0x1F,0x6B,0x69, + 0x04,0x20,0x98,0x47,0x10,0x22,0xC2,0x48,0xA1,0x68,0x02,0xF0,0x2D,0xFB,0x00,0x20, + 0xBF,0x4A,0x80,0x23,0x11,0x56,0x00,0x29,0x03,0xDA,0x11,0x5C,0x49,0x42,0x19,0x43, + 0x11,0x54,0x40,0x1C,0x80,0xB2,0x10,0x28,0xF4,0xD3,0x70,0xBD,0xFE,0xB5,0x00,0x20, + 0x00,0x90,0xB8,0x48,0x69,0x46,0xC0,0x6A,0x80,0x79,0x02,0x90,0xB3,0x48,0x02,0x69, + 0x04,0x20,0x90,0x47,0xB2,0x48,0xFF,0x21,0xA1,0x31,0x10,0x30,0x02,0xF0,0x74,0xFB, + 0x00,0x25,0xAF,0x48,0x00,0x21,0x2A,0x01,0x10,0x30,0x14,0x18,0x00,0x20,0x4B,0x00, + 0xAD,0x4A,0x12,0x5C,0x16,0x09,0x8E,0x42,0x06,0xD1,0x17,0x07,0xE6,0x5C,0x3F,0x0F, + 0x01,0x22,0xBA,0x40,0x16,0x43,0xE6,0x54,0x40,0x1C,0x16,0x28,0xF0,0xD3,0x49,0x1C, + 0x08,0x29,0xEB,0xD3,0x6D,0x1C,0x1A,0x2D,0xE3,0xD3,0x00,0x23,0x9C,0x46,0x1C,0x46, + 0x00,0x22,0xA1,0x49,0x9D,0x18,0x49,0x5D,0x00,0x20,0x01,0x91,0x09,0x09,0x8E,0x46, + 0x86,0x45,0x25,0xD1,0x01,0x99,0x00,0x9E,0x0D,0x07,0x2D,0x0F,0x01,0x21,0xA9,0x40, + 0xA5,0x00,0xAD,0x18,0x75,0x57,0x01,0x2D,0x02,0xD0,0x6D,0x1C,0x0B,0xD0,0x17,0xE0, + 0x65,0x46,0x2E,0x01,0x92,0x4D,0x10,0x35,0x76,0x19,0x45,0x00,0x77,0x5D,0x8F,0x43, + 0x77,0x55,0x75,0x19,0x09,0xE0,0x65,0x46,0x2E,0x01,0x8D,0x4D,0x10,0x35,0x75,0x19, + 0x46,0x00,0xAF,0x5D,0x0F,0x43,0xAF,0x55,0xAD,0x19,0x6E,0x78,0x0E,0x43,0x6E,0x70, + 0x40,0x1C,0x08,0x28,0xD4,0xD3,0x52,0x1C,0x04,0x2A,0xCA,0xD3,0x60,0x46,0x40,0x1C, + 0x64,0x1C,0x84,0x46,0x04,0x2C,0xC3,0xD1,0x02,0x98,0x1B,0x1D,0xC1,0x1A,0x00,0x24, + 0x49,0x1E,0x03,0x29,0x00,0xD2,0x03,0x1F,0x83,0x42,0xB9,0xD1,0xFE,0xBD,0xFE,0xB5, + 0x7C,0x4D,0x7E,0x48,0x81,0x26,0x36,0x02,0xE8,0x62,0xB1,0x68,0x02,0x20,0x88,0x47, + 0x7B,0x4C,0xA0,0x66,0xB1,0x68,0x01,0x20,0x88,0x47,0xE0,0x66,0xB1,0x68,0x03,0x20, + 0x88,0x47,0x20,0x67,0x77,0x48,0x60,0x67,0x77,0x48,0xA0,0x67,0x70,0x48,0x26,0x46, + 0x8C,0x38,0x28,0x63,0x00,0x21,0x80,0x36,0xF1,0x60,0x31,0x60,0x71,0x60,0xB1,0x60, + 0xB1,0x61,0x71,0x61,0x71,0x48,0x31,0x61,0xF0,0x63,0x0E,0x30,0xC0,0x34,0x20,0x60, + 0x0E,0x30,0x60,0x60,0x1C,0x30,0xA0,0x60,0x6D,0x48,0xE0,0x60,0x6D,0x48,0x20,0x61, + 0x6D,0x48,0x02,0x90,0x60,0x61,0x6D,0x48,0xA0,0x61,0x6D,0x48,0xE0,0x61,0xFF,0x30, + 0x6D,0x30,0x20,0x62,0x1A,0x30,0x01,0x90,0x60,0x62,0x1C,0x30,0xA0,0x62,0x1C,0x30, + 0x00,0x90,0xE0,0x62,0x1C,0x30,0x20,0x63,0x1C,0x30,0x60,0x63,0x1C,0x30,0xA0,0x63, + 0x0E,0x30,0xE0,0x63,0x63,0x48,0x64,0x4A,0x01,0x75,0x20,0x46,0x40,0x30,0x02,0x60, + 0x34,0x32,0x42,0x60,0x34,0x32,0x82,0x60,0x34,0x32,0xC2,0x60,0x34,0x32,0x02,0x61, + 0x34,0x32,0x42,0x61,0x1A,0x32,0x82,0x61,0x5C,0x4A,0xC2,0x61,0x18,0x32,0x02,0x62, + 0x48,0x32,0x42,0x62,0x5A,0x4A,0x42,0x63,0x16,0x3A,0x02,0x63,0x44,0x32,0x2A,0x60, + 0x30,0x32,0x6A,0x60,0xA4,0x3A,0xC2,0x62,0x58,0x3A,0x82,0x62,0xFF,0x32,0x55,0x32, + 0xAA,0x60,0x54,0x4A,0x6A,0x61,0x12,0x1F,0x2A,0x61,0x12,0x1F,0xEA,0x60,0x50,0x4A, + 0x22,0x32,0xC2,0x63,0x16,0x3A,0x82,0x63,0x4E,0x4A,0x52,0x1C,0xAA,0x61,0x00,0x22, + 0x94,0x46,0x19,0xE0,0x0A,0x46,0x24,0x21,0x51,0x43,0x47,0x6A,0x0F,0x23,0x7B,0x54, + 0x47,0x6A,0x00,0x23,0x4A,0x1C,0xBB,0x54,0x47,0x6A,0x8A,0x1C,0xBB,0x54,0x47,0x6A, + 0x0C,0x32,0xBB,0x52,0x47,0x6A,0x92,0x1C,0xBB,0x52,0x42,0x6A,0xC9,0x1D,0x53,0x54, + 0x61,0x46,0x49,0x1C,0xC9,0xB2,0x8C,0x46,0xE9,0x6A,0x0A,0x7B,0x61,0x46,0x62,0x45, + 0xE0,0xD8,0x16,0x21,0x20,0x6A,0x02,0xF0,0x65,0xFA,0xFF,0x21,0x09,0x31,0xE0,0x69, + 0x02,0xF0,0x60,0xFA,0x5B,0x21,0xC9,0x00,0x02,0x98,0x02,0xF0,0x5B,0xFA,0x1C,0x21, + 0x00,0x98,0x02,0xF0,0x57,0xFA,0x1C,0x21,0x01,0x98,0x02,0xF0,0x53,0xFA,0x2E,0x48, + 0x34,0x21,0x68,0x30,0x02,0xF0,0x4E,0xFA,0x34,0x21,0x2B,0x48,0x02,0xF0,0x4A,0xFA, + 0x0C,0x21,0x20,0x68,0x02,0xF0,0x46,0xFA,0x0C,0x21,0xF0,0x6B,0x02,0xF0,0x42,0xFA, + 0x1B,0x49,0x00,0x20,0x60,0x31,0xC8,0x77,0x20,0x39,0x0A,0x46,0x08,0x70,0x20,0x3A, + 0x90,0x76,0x7D,0x22,0x08,0x73,0x92,0x01,0x4A,0x81,0xFF,0x31,0x21,0x31,0x48,0x76, + 0x13,0x49,0x88,0x77,0x01,0x20,0xC8,0x77,0x01,0xF0,0xBF,0xF9,0x0C,0x48,0x1E,0x49, + 0x38,0x38,0x81,0x62,0x1D,0x49,0xC1,0x62,0x1D,0x49,0x01,0x63,0x1D,0x49,0x41,0x63, + 0xFF,0xF7,0x9C,0xFE,0xFF,0xF7,0x78,0xFE,0x04,0x48,0x40,0x30,0x80,0x6A,0x80,0x47, + 0x00,0xF0,0x0D,0xFF,0xFE,0xBD,0x00,0x00,0xA4,0x01,0x00,0x20,0x40,0x81,0x00,0x00, + 0x3C,0x16,0x00,0x20,0x44,0x01,0x00,0x20,0x32,0x2F,0x00,0x00,0x48,0x2E,0x00,0x00, + 0x04,0x00,0x00,0x20,0xD8,0x2E,0x00,0x00,0xF8,0x2E,0x00,0x00,0xC8,0x01,0x00,0x20, + 0xD8,0x04,0x00,0x20,0xB0,0x07,0x00,0x20,0x88,0x0A,0x00,0x20,0x60,0x0D,0x00,0x20, + 0x38,0x10,0x00,0x20,0x80,0x01,0x00,0x20,0x78,0x14,0x00,0x20,0x66,0x12,0x00,0x20, + 0xF2,0x2F,0x00,0x00,0x50,0x2F,0x00,0x00,0x4D,0x11,0x00,0x00,0xAB,0x1B,0x00,0x00, + 0x01,0x1C,0x00,0x00,0x17,0x13,0x00,0x00,0x70,0x47,0x70,0x47,0x01,0x22,0x69,0x49, + 0x04,0x28,0x04,0xD0,0x05,0x28,0x04,0xD0,0x06,0x28,0x04,0xD0,0x04,0xE0,0xCA,0x75, + 0x02,0xE0,0x4A,0x75,0x00,0xE0,0x8A,0x75,0x63,0x49,0xCA,0x7F,0xE0,0x31,0x4B,0x6B, + 0x9A,0x70,0x49,0x6B,0xC8,0x70,0x70,0x47,0xF8,0xB5,0x60,0x4C,0xA3,0x79,0x5E,0x4F, + 0xCF,0x20,0x60,0x3F,0x3E,0x46,0x03,0x40,0xFF,0x36,0x41,0x36,0x38,0x46,0x60,0x30, + 0x32,0x6B,0x79,0x69,0x01,0x2B,0x2A,0xD0,0x05,0x2B,0x08,0xD0,0x09,0x2B,0x01,0xD0, + 0x00,0x20,0x22,0xE0,0x00,0x23,0x7B,0x74,0x63,0x88,0xDB,0x07,0x05,0xD0,0x54,0x4E, + 0xB1,0x42,0x04,0xD1,0xA5,0x20,0x60,0x80,0x16,0xE0,0x10,0x20,0x15,0xE0,0xC5,0x7F, + 0x4D,0x4B,0x60,0x3B,0x5B,0x69,0x5B,0x1C,0x00,0x2D,0x07,0xD0,0xC5,0x7F,0x01,0x2D, + 0x00,0xD0,0xC0,0x7F,0x50,0x5C,0x60,0x80,0x7B,0x61,0x05,0xE0,0x50,0x5C,0x60,0x80, + 0x7B,0x61,0x51,0x2B,0x00,0xD3,0x7E,0x61,0x14,0x20,0xA0,0x71,0xF8,0xBD,0x7B,0x7C, + 0x02,0x2B,0x5B,0xD2,0x00,0x2B,0x12,0xD0,0x62,0x88,0x09,0x02,0x89,0x18,0x8D,0xB2, + 0xD1,0x21,0x09,0x02,0x01,0x22,0x69,0x1A,0xD2,0x03,0x20,0x29,0x36,0xD8,0xED,0xB2, + 0x28,0x1F,0x02,0x28,0x05,0xD8,0x28,0x46,0xFF,0xF7,0x98,0xFF,0x04,0xE0,0x60,0x88, + 0x42,0xE0,0x11,0x6A,0x28,0x46,0x88,0x47,0x1C,0x2D,0x47,0xD1,0x10,0x20,0xA0,0x71, + 0x81,0x20,0x00,0x02,0x05,0x21,0xC2,0x68,0x01,0x20,0x90,0x47,0x31,0x4C,0x20,0x88, + 0x20,0x21,0x88,0x43,0x20,0x80,0x04,0x20,0x00,0xF0,0x4A,0xF8,0x03,0x20,0x00,0xF0, + 0x47,0xF8,0x05,0x20,0x00,0xF0,0x44,0xF8,0x07,0x20,0x00,0xF0,0x41,0xF8,0x01,0x20, + 0x00,0xF0,0x3E,0xF8,0x28,0x48,0xFF,0x22,0x42,0x75,0x02,0x75,0x00,0x21,0xC1,0x74, + 0x02,0x74,0x81,0x74,0x41,0x74,0xAA,0x20,0xA0,0x80,0xFD,0xE7,0xC0,0x7F,0x00,0x28, + 0x0C,0xD0,0x92,0x6A,0x21,0x49,0x28,0x46,0x90,0x47,0x41,0x20,0x40,0x02,0x28,0x1A, + 0xFF,0x28,0x13,0xD8,0x71,0x6B,0x0A,0x31,0x31,0x63,0x05,0xE0,0x0D,0x20,0x00,0x03, + 0x28,0x1A,0x50,0x28,0x00,0xD9,0x16,0x48,0x78,0x61,0x07,0xE0,0x14,0x48,0x81,0x42, + 0x04,0xD0,0x60,0x88,0x50,0x54,0x78,0x69,0x40,0x1C,0xF5,0xE7,0x78,0x7C,0x40,0x1C, + 0x78,0x74,0x7A,0xE7,0x10,0xB5,0x12,0x48,0x81,0x88,0x11,0x22,0x11,0x43,0x81,0x80, + 0x00,0xF0,0xE0,0xFF,0x10,0xBD,0x0F,0x48,0xC0,0x68,0x00,0x47,0x70,0x47,0x70,0x47, + 0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40,0x40,0x09,0x0B,0x4A,0x80,0x00,0x80,0x18, + 0x01,0x60,0x70,0x47,0x80,0x01,0x00,0x20,0x64,0x00,0x00,0x20,0x00,0x20,0x00,0x40, + 0xFF,0xFF,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x03,0x00,0x40,0xB0,0x15,0x00,0x20, + 0x00,0x10,0x00,0x40,0x40,0x81,0x00,0x00,0x80,0xE1,0x00,0xE0,0xF8,0xB5,0xEE,0x4C, + 0xE0,0x7F,0x00,0x28,0x07,0xD0,0x01,0x20,0xC0,0x03,0x02,0x68,0xEB,0x49,0x14,0x20, + 0x90,0x47,0x00,0x28,0x49,0xD1,0xE8,0x48,0x60,0x38,0xC2,0x7B,0x01,0x46,0x08,0x46, + 0xFF,0x31,0x40,0x30,0x41,0x31,0x00,0x2A,0x0A,0xD1,0xCA,0x6A,0x03,0x78,0x20,0x32, + 0x52,0x7A,0x93,0x42,0x39,0xD3,0xE0,0x4A,0x40,0x3A,0x92,0x7E,0x12,0x06,0x34,0xD5, + 0x00,0x7B,0x00,0x28,0x31,0xD1,0xDD,0x4F,0xDD,0x4A,0x3B,0x78,0xAB,0x2B,0x03,0xD0, + 0x40,0x1C,0x80,0xB2,0x90,0x42,0xF8,0xD3,0xD7,0x4E,0x00,0x20,0xA0,0x36,0x0F,0xE0, + 0x24,0x25,0x03,0x46,0x6B,0x43,0x72,0x6A,0x9D,0x1C,0x55,0x5D,0x01,0x2D,0x05,0xD1, + 0x12,0x33,0xD5,0x5A,0xFF,0x2D,0x01,0xD3,0xFF,0x25,0xD5,0x52,0x40,0x1C,0xC0,0xB2, + 0xCA,0x6A,0x12,0x7B,0x82,0x42,0xEB,0xD8,0xCE,0x4B,0x18,0x7C,0xCA,0x6A,0x20,0x32, + 0xD5,0x79,0x01,0x22,0xAA,0x40,0x90,0x43,0x18,0x74,0xD8,0x13,0x0F,0x63,0x40,0x68, + 0x80,0x47,0xA0,0x7F,0x02,0x21,0x08,0x43,0xA0,0x77,0xF8,0xBD,0xF8,0xB5,0xC2,0x48, + 0xC1,0x4C,0x60,0x38,0x40,0x79,0x05,0x28,0x01,0xD8,0x03,0xE0,0x30,0xBF,0x20,0x7F, + 0x00,0x28,0xFB,0xD0,0xC0,0x4D,0x68,0x7D,0x00,0x27,0x01,0x26,0x00,0x28,0x1A,0xD0, + 0xAF,0x75,0x6F,0x75,0x81,0x20,0x00,0x02,0x01,0x69,0x3F,0x20,0x88,0x47,0xBC,0x48, + 0xBA,0x49,0x41,0x81,0x81,0x20,0x00,0x02,0x01,0x21,0xC2,0x69,0x00,0x20,0x90,0x47, + 0xB7,0x49,0xAA,0x20,0x88,0x80,0x27,0x77,0xA8,0x7D,0x01,0x28,0xF2,0xD1,0xAF,0x75, + 0x60,0x7F,0x30,0x43,0x60,0x77,0xAC,0x49,0xE0,0x31,0x48,0x6B,0x82,0x7A,0xCA,0x2A, + 0x06,0xD1,0x02,0x7C,0x01,0x2A,0x03,0xD1,0x07,0x74,0x60,0x7F,0x30,0x43,0x60,0x77, + 0xA0,0x7F,0x80,0x07,0x07,0xD5,0xA7,0x4B,0x1A,0x7C,0xC8,0x6A,0x20,0x30,0xC0,0x79, + 0x86,0x40,0x32,0x43,0x1A,0x74,0xA0,0x7F,0xFD,0x21,0x08,0x40,0xA0,0x77,0xF8,0xBD, + 0x70,0xB5,0x9D,0x4D,0x20,0x3D,0x28,0x7B,0x00,0x28,0x1A,0xD0,0xEC,0x1D,0xF9,0x34, + 0xE0,0x6A,0x80,0x30,0x80,0x68,0x00,0x28,0x13,0xD0,0x9C,0x48,0x5E,0x38,0xC0,0x68, + 0x80,0x47,0x00,0x22,0xFF,0x28,0x0D,0xD0,0xFE,0x28,0x0A,0xD0,0x00,0x28,0x08,0xD0, + 0xE1,0x6A,0x01,0x23,0x80,0x31,0x89,0x68,0x40,0x1E,0x83,0x40,0x19,0x42,0x00,0xD0, + 0x2A,0x73,0x70,0xBD,0xE0,0x6A,0x8C,0x4B,0x40,0x30,0x41,0x79,0x8A,0x48,0x60,0x38, + 0x81,0x72,0x02,0x21,0x41,0x77,0xC2,0x71,0x00,0x20,0x0F,0x21,0xA0,0x33,0x05,0xE0, + 0x24,0x22,0x42,0x43,0x5D,0x6A,0x40,0x1C,0xA9,0x54,0xC0,0xB2,0xE2,0x6A,0x12,0x7B, + 0x82,0x42,0xF5,0xD8,0x70,0xBD,0x30,0xB5,0x7F,0x4C,0x00,0x20,0x60,0x34,0x05,0xE0, + 0x00,0x28,0x03,0xD0,0x04,0x28,0x01,0xD0,0x08,0x28,0x0D,0xD1,0x18,0x21,0xA2,0x69, + 0x41,0x43,0x51,0x18,0x00,0x22,0x0B,0x88,0x0D,0x8B,0x0D,0x80,0x0B,0x83,0x52,0x1C, + 0x89,0x1C,0xD2,0xB2,0x0C,0x2A,0xF6,0xD3,0x80,0x1C,0xC0,0xB2,0x09,0x28,0xE7,0xD3, + 0x30,0xBD,0x79,0x48,0x77,0x49,0x81,0x60,0x00,0x68,0x70,0x47,0xF8,0xB5,0x01,0x20, + 0x40,0x07,0xC0,0x7A,0x6C,0x4C,0x75,0x4E,0xE0,0x34,0x00,0x25,0x20,0x46,0x20,0x30, + 0x66,0x63,0x05,0x76,0x14,0x21,0x30,0x46,0x01,0xF0,0xEC,0xFF,0xCA,0x20,0x30,0x70, + 0x61,0x6B,0x01,0x20,0x48,0x70,0x60,0x6B,0x85,0x70,0x60,0x6B,0xC5,0x70,0x61,0x6B, + 0x02,0x20,0x08,0x71,0xFF,0xF7,0xDD,0xFF,0x61,0x6B,0x48,0x71,0x60,0x6B,0x85,0x72, + 0x67,0x48,0x61,0x6B,0x00,0x78,0xC8,0x72,0x60,0x6B,0x08,0x26,0x06,0x73,0x60,0x6B, + 0x20,0x27,0x47,0x73,0x61,0x6B,0x04,0x20,0x88,0x73,0x61,0x6B,0x03,0x20,0xC8,0x73, + 0x60,0x6B,0x05,0x74,0x58,0x48,0x45,0x75,0x85,0x75,0xC5,0x75,0x05,0x76,0x45,0x76, + 0x85,0x76,0x5C,0x49,0x01,0x60,0x5C,0x49,0x41,0x60,0x5C,0x49,0x81,0x60,0x5C,0x49, + 0xC1,0x60,0xFF,0xF7,0xAC,0xFC,0xE0,0x6A,0x5A,0x49,0x00,0x78,0x81,0x24,0x88,0x83, + 0x24,0x02,0x20,0x6B,0x80,0x47,0x21,0x69,0x3C,0x20,0x88,0x47,0x4C,0x48,0x01,0x88, + 0x39,0x43,0x01,0x80,0x54,0x48,0xC5,0x71,0x46,0x48,0x05,0x71,0xC0,0x13,0xC0,0x6A, + 0x80,0x47,0xA0,0x05,0x41,0x89,0xB1,0x43,0x41,0x81,0x41,0x89,0x71,0x22,0x11,0x43, + 0x41,0x81,0x81,0x89,0x09,0x09,0x09,0x01,0x81,0x81,0x20,0x6A,0x80,0x47,0x60,0x69, + 0x80,0x47,0x60,0x6A,0x80,0x47,0x01,0xF0,0x1A,0xF9,0xF8,0xBD,0x70,0xB5,0x36,0x4D, + 0x69,0x7F,0x01,0x20,0x01,0x43,0x69,0x77,0x37,0x49,0x48,0x76,0x81,0x26,0x36,0x02, + 0x3F,0xE0,0xB0,0x69,0x80,0x47,0x35,0x48,0xE2,0x30,0x01,0x69,0x01,0x20,0x88,0x47, + 0x00,0xF0,0x9F,0xF9,0x2C,0x48,0xE0,0x30,0xC0,0x6A,0x20,0x30,0x80,0x78,0x00,0x28, + 0x01,0xD0,0x00,0xF0,0x45,0xFD,0x64,0x20,0x01,0xF0,0xA1,0xFA,0x00,0xF0,0xEE,0xFA, + 0x2A,0x4C,0x1E,0x3C,0x60,0x6A,0x80,0x47,0x63,0x21,0xC9,0x43,0x19,0x20,0x00,0xF0, + 0x41,0xFF,0x30,0x48,0x20,0x49,0x00,0x7F,0x60,0x39,0x08,0x71,0x20,0x6A,0x80,0x47, + 0xFF,0xF7,0x39,0xFF,0xE0,0x69,0x80,0x47,0x01,0x20,0xC0,0x03,0x00,0x6B,0x80,0x47, + 0x2A,0x48,0x01,0xF0,0x67,0xF9,0xF0,0x6B,0x80,0x47,0x1C,0x48,0x5E,0x38,0x00,0x69, + 0x80,0x47,0xFF,0xF7,0xED,0xFE,0xFF,0xF7,0x49,0xFE,0x00,0xF0,0x76,0xFA,0xFF,0xF7, + 0x9D,0xFE,0xE8,0x7F,0x06,0x28,0xBC,0xD1,0x70,0xBD,0x15,0x48,0x04,0x21,0x01,0x81, + 0xAA,0x21,0x81,0x80,0x28,0x21,0x01,0x80,0x1D,0x48,0x41,0x07,0x88,0x80,0x12,0x49, + 0x10,0x20,0x08,0x61,0x0B,0x49,0x00,0x20,0xC8,0x71,0xFF,0xF7,0x2F,0xFF,0x06,0x4C, + 0xE0,0x7F,0x00,0x28,0x04,0xD0,0x06,0x28,0xFA,0xD1,0xFF,0xF7,0xDB,0xFA,0xF7,0xE7, + 0xFF,0xF7,0x94,0xFF,0xF4,0xE7,0x00,0x00,0x64,0x00,0x00,0x20,0xB0,0x15,0x00,0x20, + 0x4C,0x1D,0x00,0x00,0x00,0x03,0x00,0x40,0x80,0x01,0x00,0x20,0x9E,0x80,0x00,0x00, + 0x00,0x02,0x00,0x40,0xE4,0x3F,0x00,0x00,0x00,0x01,0x00,0x40,0x0E,0x18,0x00,0x20, + 0xC0,0x30,0x00,0x00,0xEC,0x17,0x00,0x20,0xF8,0x17,0x00,0x20,0xA0,0x01,0x00,0x20, + 0x22,0x18,0x00,0x20,0x04,0x16,0x00,0x20,0x00,0x20,0x00,0x40,0x47,0x0C,0x00,0x00, + 0xCA,0xCA,0x00,0x00,0xF3,0xB5,0xA4,0x48,0xAF,0xB0,0xC0,0x6A,0x04,0x79,0x60,0x30, + 0x40,0x89,0x14,0x30,0x80,0xB2,0x05,0x90,0x9F,0x48,0x80,0x38,0xC1,0x69,0x30,0x98, + 0x60,0x43,0x0E,0x18,0x9D,0x48,0x00,0x78,0x04,0x90,0x00,0x20,0x00,0x90,0x04,0x99, + 0x02,0x90,0x88,0x42,0x78,0xD2,0x02,0x20,0x03,0x90,0x00,0x20,0x01,0x90,0x21,0x46, + 0x30,0x46,0x01,0xF0,0xD7,0xFE,0x00,0x25,0x2F,0x46,0x56,0xE0,0x7D,0x20,0x92,0x49, + 0xC0,0x00,0x93,0x4A,0xE0,0x39,0x13,0x7A,0x1B,0x07,0x04,0xD4,0xCB,0x7F,0x06,0x2B, + 0x01,0xD0,0x40,0x1E,0xF7,0xD1,0x8F,0x48,0x30,0x99,0xC2,0x6B,0x02,0x20,0x90,0x47, + 0x8D,0x48,0x00,0x78,0x01,0xF0,0x0E,0xF9,0x8C,0x48,0x00,0x21,0x01,0x76,0x8C,0x49, + 0x11,0x22,0x8A,0x80,0x43,0x22,0x0A,0x80,0x00,0xE0,0x30,0xBF,0x01,0x7E,0x00,0x29, + 0xFB,0xD0,0x84,0x48,0x40,0x30,0xC2,0x69,0x00,0x21,0x06,0xA8,0x90,0x47,0x00,0x21, + 0x08,0x46,0x0B,0xE0,0x43,0x00,0x06,0xAA,0xD3,0x5E,0x05,0x9A,0x93,0x42,0x03,0xDA, + 0x01,0x22,0x82,0x40,0x15,0x43,0x49,0x1C,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF1,0xD3, + 0xA1,0x42,0x05,0xD3,0x00,0x98,0x40,0x1C,0x00,0x90,0x01,0x20,0x01,0x90,0x17,0xE0, + 0x2F,0x98,0x7F,0x1C,0x87,0x42,0x13,0xD2,0x00,0x20,0x01,0x23,0x0B,0xE0,0x31,0x5C, + 0x2F,0x9A,0x91,0x42,0x05,0xD2,0x1A,0x46,0x82,0x40,0x2A,0x42,0x01,0xD1,0x49,0x1C, + 0x31,0x54,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF1,0xD3,0x01,0x98,0x00,0x28,0xA5,0xD0, + 0x03,0x98,0x40,0x1E,0x00,0x06,0x00,0x0E,0x03,0x90,0x02,0xD0,0x01,0x98,0x00,0x28, + 0x95,0xD0,0x68,0x48,0x40,0x7B,0x01,0x28,0x1F,0xD0,0x02,0x98,0x00,0x28,0x04,0xD0, + 0x00,0x20,0x1A,0xAA,0x24,0xAB,0x16,0xE0,0x22,0xE0,0x22,0x46,0x31,0x46,0x1A,0xA8, + 0x01,0xF0,0xFA,0xFD,0x22,0x46,0x31,0x46,0x24,0xA8,0x01,0xF0,0xF5,0xFD,0x0C,0xE0, + 0x15,0x5C,0x31,0x5C,0x8D,0x42,0x00,0xD9,0x11,0x54,0x1D,0x5C,0x8D,0x42,0x00,0xD2, + 0x19,0x54,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF2,0xD3,0x57,0x49,0xAA,0x20,0x88,0x80, + 0x51,0x48,0x01,0x68,0x49,0x1C,0x01,0x60,0x02,0x98,0x40,0x1C,0xC0,0xB2,0x5E,0xE7, + 0x00,0x20,0x1A,0xA9,0x24,0xAA,0x06,0xE0,0x0B,0x5C,0x15,0x5C,0x5B,0x19,0x5B,0x08, + 0x33,0x54,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF6,0xD3,0x46,0x4D,0x00,0x24,0x40,0x35, + 0x42,0x4E,0x08,0xE0,0x30,0x98,0x6B,0x68,0x00,0x19,0xC2,0xB2,0x01,0x21,0x08,0x46, + 0x98,0x47,0x64,0x1C,0xE4,0xB2,0x30,0x78,0x84,0x42,0xF3,0xD3,0x04,0x98,0x41,0x08, + 0x00,0x98,0x81,0x42,0x02,0xD2,0x01,0x20,0x31,0xB0,0xF0,0xBD,0x00,0x20,0xFB,0xE7, + 0xFE,0xB5,0x35,0x48,0x00,0x24,0xC0,0x6A,0x39,0x49,0x86,0x79,0x08,0x22,0xCA,0x80, + 0x40,0x30,0x40,0x78,0x40,0x1E,0xC0,0xB2,0x00,0x90,0x02,0x20,0x01,0x90,0x32,0x48, + 0x04,0x60,0x31,0x4A,0x34,0x49,0x17,0x78,0xAA,0x20,0x88,0x80,0x00,0x25,0x28,0x02, + 0x2F,0x49,0x28,0x43,0x88,0x81,0x2C,0x48,0x21,0x46,0x07,0x60,0x00,0x98,0xFF,0xF7, + 0x01,0xFF,0x00,0x28,0x05,0xD1,0x01,0x98,0x85,0x42,0x02,0xD0,0x6D,0x1C,0xAD,0xB2, + 0xED,0xE7,0x21,0x48,0x80,0x38,0x00,0x6A,0x00,0x2C,0x05,0x55,0x1F,0x48,0x0E,0xD0, + 0x00,0x78,0x20,0x18,0xC4,0xB2,0xB4,0x42,0x08,0xD0,0x1C,0x48,0x00,0x78,0x21,0x18, + 0xB1,0x42,0x01,0xD9,0x30,0x1A,0xC4,0xB2,0xB4,0x42,0xD2,0xD3,0xFE,0xBD,0x04,0x78, + 0xF1,0xE7,0x70,0xB5,0x1B,0x48,0x60,0x30,0x40,0x7F,0xC0,0x07,0x23,0xD0,0x81,0x25, + 0x2D,0x02,0x29,0x69,0x3C,0x20,0x88,0x47,0x16,0x48,0x00,0x24,0x80,0x30,0x84,0x77, + 0x00,0xF0,0x4A,0xF8,0x13,0x48,0x44,0x73,0x0E,0x4C,0x40,0x34,0xA1,0x68,0x01,0x20, + 0x88,0x47,0x21,0x68,0x02,0x20,0x88,0x47,0xFF,0xF7,0xA2,0xFF,0x21,0x68,0x00,0x20, + 0x88,0x47,0x21,0x68,0x02,0x20,0x88,0x47,0x06,0x48,0x00,0x21,0xC2,0x6B,0x02,0x20, + 0x90,0x47,0x28,0x6B,0x80,0x47,0x70,0xBD,0x44,0x01,0x00,0x20,0xA4,0x01,0x00,0x20, + 0x00,0x03,0x00,0x40,0x40,0x81,0x00,0x00,0xC4,0x01,0x00,0x20,0x80,0x01,0x00,0x20, + 0x00,0x10,0x00,0x40,0x04,0x00,0x00,0x20,0x00,0x02,0x00,0x40,0xFD,0x49,0x48,0x6B, + 0x82,0x7A,0xCA,0x2A,0x17,0xD1,0xC2,0x7A,0x13,0x02,0x02,0x7B,0x13,0x43,0xFA,0x4A, + 0x13,0x81,0x43,0x7B,0xFF,0x33,0xFF,0x33,0x02,0x33,0x53,0x81,0xC2,0x7B,0x80,0x7B, + 0x00,0x01,0x02,0x43,0xC8,0x6A,0x80,0x21,0x40,0x30,0x00,0x79,0xC0,0x00,0x08,0x43, + 0x02,0x43,0xF2,0x48,0x82,0x74,0x70,0x47,0x10,0xB5,0xEF,0x49,0xF0,0x48,0x48,0x80, + 0xF0,0x48,0xEC,0x4C,0x00,0x78,0x3F,0x23,0x02,0x02,0xE0,0x6A,0x1B,0x5C,0x1A,0x43, + 0x0A,0x81,0x7A,0x22,0x12,0x5A,0xCA,0x80,0x40,0x30,0x42,0x78,0xFF,0x32,0xFF,0x32, + 0x02,0x32,0x4A,0x81,0xC2,0x78,0x81,0x78,0x12,0x01,0x00,0x79,0x11,0x43,0xC0,0x00, + 0x80,0x22,0x10,0x43,0x01,0x43,0xE1,0x48,0x81,0x74,0xFF,0xF7,0xBF,0xFF,0xE0,0x6A, + 0xE1,0x49,0xC2,0x78,0xE1,0x48,0x01,0xF0,0xEF,0xFC,0xE0,0x6A,0xE0,0x49,0x02,0x79, + 0xE0,0x48,0x01,0xF0,0xE9,0xFC,0x10,0xBD,0x70,0xB5,0xD6,0x48,0xDE,0x4B,0xC0,0x6A, + 0xDE,0x4D,0x01,0x78,0x00,0x20,0x98,0x77,0x19,0x71,0xA9,0x83,0x68,0x8A,0xDC,0x4C, + 0x01,0x22,0x28,0x28,0x02,0xD8,0xA6,0x8B,0x00,0x2E,0x06,0xD0,0xC8,0x28,0x00,0xD9, + 0xC8,0x20,0xC0,0x08,0x9A,0x77,0x40,0x18,0x18,0x71,0x18,0x79,0xA8,0x83,0x9A,0x77, + 0xD1,0x4A,0x02,0x20,0xD8,0x77,0x80,0x32,0xD1,0x6B,0xE8,0x78,0x08,0x70,0xD1,0x6B, + 0x28,0x79,0x48,0x70,0x00,0x20,0xCD,0x49,0x0D,0x79,0x8E,0x78,0x49,0x69,0x75,0x43, + 0x6D,0x00,0x46,0x00,0xAD,0x19,0x49,0x5B,0x49,0x08,0xFF,0x29,0x00,0xDD,0xFF,0x21, + 0x85,0x1C,0xD6,0x6B,0x40,0x1C,0x40,0xB2,0x71,0x55,0x04,0x28,0xEB,0xDB,0xD6,0x6B, + 0x65,0x7C,0x81,0x1C,0x75,0x54,0xC1,0x1C,0xD5,0x6B,0x1B,0x79,0x6B,0x54,0xD2,0x6B, + 0x21,0x7F,0x00,0x1D,0x11,0x54,0x70,0xBD,0x18,0x21,0xBE,0x4B,0x10,0xB5,0x48,0x43, + 0xC1,0x18,0xBD,0x4A,0x8C,0x78,0xD4,0x70,0xCC,0x78,0x94,0x70,0x4C,0x78,0x54,0x70, + 0x18,0x5C,0x10,0x70,0x88,0x79,0xD0,0x72,0xC8,0x79,0x90,0x72,0x48,0x79,0x50,0x72, + 0x08,0x79,0x10,0x72,0x88,0x7A,0xD0,0x74,0xC8,0x7A,0x90,0x74,0x48,0x7A,0x50,0x74, + 0x08,0x7A,0x10,0x74,0x88,0x7B,0xD0,0x76,0xC8,0x7B,0x90,0x76,0x48,0x7B,0x50,0x76, + 0x08,0x7B,0x10,0x76,0xAC,0x48,0x8A,0x7C,0x20,0x30,0xC2,0x70,0xCA,0x7C,0x82,0x70, + 0x4A,0x7C,0x42,0x70,0x0A,0x7C,0x02,0x70,0x8A,0x7D,0xC2,0x72,0xCA,0x7D,0x82,0x72, + 0x4A,0x7D,0x42,0x72,0x09,0x7D,0x01,0x72,0x10,0xBD,0x10,0xB5,0xA0,0x48,0x00,0xE0, + 0x00,0xBF,0x41,0x7E,0x00,0x29,0xFB,0xD0,0x01,0x20,0x80,0x07,0x41,0x88,0x04,0x22, + 0x91,0x43,0x41,0x80,0x00,0x20,0xFF,0xF7,0xB7,0xFF,0x9C,0x48,0x00,0x21,0xC2,0x6B, + 0x08,0x46,0x90,0x47,0x10,0xBD,0xF8,0xB5,0x8A,0x4C,0xE0,0x6A,0x81,0x79,0x42,0x79, + 0x20,0x46,0x80,0x38,0x00,0x90,0x51,0x43,0x40,0x69,0x49,0x00,0x01,0xF0,0xAA,0xFC, + 0xE0,0x6A,0x85,0x4D,0x60,0x30,0x40,0x8B,0xE8,0x80,0x8D,0x48,0x00,0x24,0x44,0x76, + 0x04,0x76,0x8F,0x4F,0xAE,0x04,0x3C,0x60,0x70,0x88,0x04,0x21,0x08,0x43,0x70,0x80, + 0x00,0x98,0x00,0x6A,0x00,0x78,0x01,0x02,0x01,0x43,0xA9,0x81,0x87,0x48,0x00,0x21, + 0xC2,0x6B,0x02,0x20,0x90,0x47,0x00,0x20,0x00,0xF0,0xDC,0xFE,0x70,0x88,0x08,0x21, + 0x08,0x43,0x70,0x80,0x11,0x20,0xA8,0x80,0x43,0x20,0x28,0x80,0x7A,0x48,0x84,0x71, + 0x80,0x48,0x04,0x70,0x38,0x68,0x40,0x1C,0x38,0x60,0xF8,0xBD,0x70,0xB5,0xFF,0xF7, + 0x2B,0xFF,0x7A,0x4D,0x40,0x35,0x28,0x6B,0x80,0x47,0x73,0x4C,0x00,0x20,0x60,0x73, + 0x20,0x46,0x02,0x21,0x80,0x30,0x81,0x77,0xFF,0xF7,0xB5,0xFF,0x60,0x79,0x02,0x28, + 0x03,0xD8,0xFF,0xF7,0x9A,0xFF,0x28,0x6B,0x80,0x47,0x62,0x4A,0x00,0x20,0x40,0x3A, + 0x05,0xE0,0x00,0x28,0x03,0xD0,0x04,0x28,0x01,0xD0,0x08,0x28,0x06,0xD1,0x11,0x68, + 0x43,0x00,0xC9,0x18,0x0B,0x88,0x4D,0x88,0x0D,0x80,0x4B,0x80,0x80,0x1C,0xC0,0xB2, + 0x09,0x28,0xEE,0xD3,0x57,0x4B,0x00,0x20,0x80,0x3B,0x59,0x6A,0x42,0x00,0x8A,0x18, + 0x00,0x21,0x51,0x5E,0x50,0x29,0x05,0xDD,0xCD,0x17,0xAD,0x0F,0x6D,0x18,0xAD,0x10, + 0x49,0x19,0x11,0x80,0x40,0x1C,0xC0,0xB2,0x0C,0x28,0xEE,0xD3,0x4D,0x48,0x99,0x69, + 0xC0,0x6A,0x82,0x79,0x40,0x79,0x42,0x43,0x52,0x00,0xD8,0x68,0x01,0xF0,0xCC,0xFB, + 0x60,0x79,0xC8,0x28,0x01,0xD2,0x40,0x1C,0x60,0x71,0x70,0xBD,0xF0,0xB5,0x06,0x00, + 0x55,0x48,0x45,0x4A,0x45,0x6A,0x43,0x48,0x4D,0x4F,0xC0,0x6A,0x91,0xB0,0x04,0x79, + 0x02,0xD0,0x01,0x2E,0x13,0xD0,0x03,0xE0,0x84,0x79,0x3E,0x48,0x40,0x38,0x05,0x68, + 0x39,0x7D,0x04,0x20,0x0B,0x02,0x0B,0x43,0x93,0x81,0xFF,0xF7,0x0D,0xFF,0x00,0x22, + 0x02,0x21,0x30,0x46,0x00,0xF0,0x7E,0xFE,0x01,0x2E,0x05,0xD0,0x09,0xE0,0x3E,0x49, + 0x02,0x20,0x40,0x31,0x49,0x78,0xED,0xE7,0x01,0x22,0x02,0x21,0x30,0x46,0x00,0xF0, + 0x71,0xFE,0x3D,0x49,0x01,0x20,0x40,0x39,0xC8,0x72,0x00,0x20,0x00,0xF0,0x3E,0xFE, + 0x3A,0x49,0x40,0x31,0x01,0x2E,0x09,0xD0,0x35,0x48,0x8B,0x69,0x80,0x88,0x22,0x46, + 0x80,0xB2,0x69,0x46,0x98,0x47,0x00,0x20,0x6F,0x46,0x19,0xE0,0x38,0x88,0x8B,0x69, + 0x80,0xB2,0x22,0x46,0x29,0x46,0x98,0x47,0x00,0x22,0x03,0x21,0x30,0x46,0x00,0xF0, + 0x51,0xFE,0x01,0x22,0x03,0x21,0x30,0x46,0x00,0xF0,0x4C,0xFE,0x05,0x20,0xFF,0xF7, + 0xD3,0xFE,0x11,0xB0,0xF0,0xBD,0x41,0x00,0x7A,0x5A,0x80,0x1C,0x6A,0x52,0xC0,0xB2, + 0xA0,0x42,0xF8,0xD3,0x00,0x22,0x03,0x21,0x30,0x46,0x00,0xF0,0x3B,0xFE,0x03,0x20, + 0xFF,0xF7,0xC2,0xFE,0x01,0x22,0x02,0x21,0x30,0x46,0x00,0xF0,0x33,0xFE,0x1E,0x48, + 0x01,0x21,0x40,0x38,0xC1,0x72,0x00,0x20,0x00,0xF0,0x00,0xFE,0x18,0x48,0x1B,0x49, + 0x80,0x88,0x40,0x31,0x8B,0x69,0x80,0xB2,0x22,0x46,0x69,0x46,0x98,0x47,0x01,0x20, + 0x04,0xE0,0x41,0x00,0x7A,0x5A,0x80,0x1C,0x6A,0x52,0xC0,0xB2,0xA0,0x42,0xF8,0xD3, + 0x05,0x20,0xFF,0xF7,0xA1,0xFE,0x01,0x22,0x03,0x21,0x30,0x46,0x00,0xF0,0x12,0xFE, + 0xC7,0xE7,0x00,0x00,0x44,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0x60,0x12,0x00,0x40, + 0x82,0x10,0x00,0x00,0xC0,0x30,0x00,0x00,0x1C,0x2F,0x00,0x00,0xF8,0x17,0x00,0x20, + 0x10,0x2F,0x00,0x00,0xEC,0x17,0x00,0x20,0x04,0x00,0x00,0x20,0x04,0x16,0x00,0x20, + 0x80,0x01,0x00,0x20,0x38,0x18,0x00,0x20,0x40,0x03,0x00,0x40,0x40,0x81,0x00,0x00, + 0xC4,0x01,0x00,0x20,0xC3,0x01,0x00,0x20,0xC4,0x00,0x00,0x20,0xF3,0xB5,0x05,0x46, + 0xFA,0xA0,0x9D,0xB0,0x00,0x68,0x1A,0x90,0xF9,0x48,0xFA,0x4A,0x01,0x68,0x17,0x91, + 0xC0,0x68,0xFF,0x21,0x11,0x70,0xF8,0x49,0x49,0x79,0x02,0x29,0x03,0xD8,0x2C,0x22, + 0x17,0x99,0x01,0xF0,0x01,0xFB,0xF5,0x48,0x80,0x8B,0x00,0x28,0x55,0xD0,0x2C,0x22, + 0x0C,0xA8,0x17,0x99,0x01,0xF0,0xF8,0xFA,0x00,0x27,0x68,0x46,0x19,0x95,0x07,0x80, + 0x3C,0x46,0x18,0x97,0x00,0x20,0xFF,0xF7,0x29,0xFF,0x32,0x22,0x0A,0x21,0x68,0x46, + 0x01,0xF0,0x43,0xFA,0x1B,0x90,0x68,0x46,0x06,0x88,0xBE,0x42,0x0B,0xD9,0x0F,0x2E, + 0x09,0xD3,0x2C,0x22,0x01,0xA8,0x17,0x99,0x01,0xF0,0xDE,0xFA,0xE4,0x48,0x37,0x46, + 0x00,0x89,0x00,0x0A,0x19,0x90,0x1B,0x98,0x00,0x28,0x1D,0xD0,0x14,0x2E,0x1B,0xD2, + 0x04,0x2C,0x06,0xD2,0x1A,0xA8,0x00,0x5D,0x40,0x19,0x64,0x1C,0xC0,0xB2,0xE4,0xB2, + 0x03,0xE0,0x00,0x24,0x2D,0x1D,0xED,0xB2,0x28,0x46,0xD5,0x49,0x00,0x02,0x40,0x31, + 0xC9,0x6A,0x40,0x31,0x09,0x7D,0x08,0x43,0xD5,0x49,0x08,0x81,0x18,0x98,0x1E,0x99, + 0x40,0x1C,0x18,0x90,0x88,0x42,0xC5,0xD3,0x0F,0x2F,0x06,0xD3,0x2C,0x22,0x01,0xA9, + 0x17,0x98,0x01,0xF0,0xB1,0xFA,0x19,0x98,0x05,0xE0,0x2C,0x22,0x0C,0xA9,0x17,0x98, + 0x01,0xF0,0xAA,0xFA,0xFF,0x20,0xC7,0x49,0x08,0x70,0x1F,0xB0,0xF0,0xBD,0xF8,0xB5, + 0x90,0x21,0xC8,0x48,0x01,0xF0,0x06,0xFB,0xC6,0x4C,0xC7,0x4E,0x00,0x20,0x00,0x22, + 0xB1,0x18,0xAA,0x23,0x5B,0x5C,0x83,0x42,0x27,0xD1,0x83,0x00,0x80,0x31,0xE5,0x5C, + 0x09,0x7A,0x0D,0x43,0xE5,0x54,0x1B,0x19,0x9F,0x7E,0x1D,0x46,0x0F,0x43,0x9F,0x76, + 0x20,0x35,0xEF,0x7C,0x0F,0x43,0xEF,0x74,0xD5,0x07,0x09,0xD0,0x1D,0x46,0x40,0x35, + 0xAF,0x7A,0x0F,0x43,0xAF,0x72,0x20,0x35,0xEF,0x78,0x0F,0x43,0xEF,0x70,0x08,0xE0, + 0x1D,0x46,0x60,0x35,0xAF,0x78,0x0F,0x43,0xAF,0x70,0x20,0x3D,0xEF,0x7A,0x0F,0x43, + 0xEF,0x72,0x60,0x33,0xDD,0x7E,0x0D,0x43,0xDD,0x76,0x52,0x1C,0xD2,0xB2,0x16,0x2A, + 0xCE,0xD3,0x00,0x22,0xB1,0x18,0xC0,0x23,0x5B,0x5C,0x83,0x42,0x19,0xD1,0x83,0x00, + 0x80,0x31,0xE5,0x5C,0x89,0x7F,0x0D,0x43,0xE5,0x54,0x1B,0x19,0xDF,0x7E,0x1D,0x46, + 0x0F,0x43,0xDF,0x76,0x20,0x35,0xAF,0x7C,0x0F,0x43,0xAF,0x74,0x20,0x35,0xEF,0x7A, + 0x0F,0x43,0xEF,0x72,0x20,0x35,0xEB,0x78,0x0B,0x43,0xEB,0x70,0xEB,0x7E,0x0B,0x43, + 0xEB,0x76,0x52,0x1C,0xD2,0xB2,0x0C,0x2A,0xDC,0xD3,0x40,0x1C,0xC0,0xB2,0x06,0x28, + 0xA5,0xD3,0xF8,0xBD,0xF3,0xB5,0x92,0x49,0x85,0xB0,0x40,0x39,0x48,0x6A,0x03,0x90, + 0x08,0x46,0x80,0x30,0x04,0x90,0xC0,0x6A,0x06,0x9A,0x04,0x79,0x01,0x2A,0x0D,0xD0, + 0x40,0x31,0x8E,0x69,0x09,0x68,0x03,0x91,0x84,0x79,0x60,0x30,0xC7,0x89,0x02,0x20, + 0x02,0x90,0x00,0x20,0x00,0x90,0x00,0x20,0x01,0x46,0x04,0xE0,0xCE,0x6B,0xF4,0xE7, + 0x31,0x54,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xFA,0xD3,0x00,0x25,0x01,0x95,0x35,0xE0, + 0x06,0x98,0xFF,0xF7,0x53,0xFE,0x04,0x9A,0x00,0x21,0xD2,0x6A,0x08,0x46,0x20,0x32, + 0x94,0x46,0x0D,0xE0,0x03,0x9A,0x43,0x00,0xD2,0x5E,0x63,0x46,0x9B,0x7C,0xDB,0x19, + 0x9A,0x42,0x03,0xDA,0x01,0x22,0x82,0x40,0x15,0x43,0x49,0x1C,0x40,0x1C,0xC0,0xB2, + 0xA0,0x42,0xEF,0xD3,0xA1,0x42,0x02,0xD3,0x01,0x20,0x00,0x90,0x19,0xE0,0x01,0x98, + 0x05,0x99,0x40,0x1C,0x01,0x90,0x88,0x42,0x13,0xD2,0x00,0x20,0x01,0x23,0x0B,0xE0, + 0x31,0x5C,0x05,0x9A,0x91,0x42,0x05,0xD2,0x1A,0x46,0x82,0x40,0x2A,0x42,0x01,0xD1, + 0x49,0x1C,0x31,0x54,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF1,0xD3,0x00,0x98,0x00,0x28, + 0xC6,0xD0,0x02,0x98,0x40,0x1E,0x00,0x06,0x00,0x0E,0x02,0x90,0x02,0xD0,0x00,0x98, + 0x00,0x28,0xB0,0xD0,0x00,0x98,0x07,0xB0,0xC0,0xB2,0xF0,0xBD,0x01,0x46,0x60,0x4A, + 0x10,0x20,0xD0,0x80,0x5A,0x48,0x5C,0x4B,0x40,0x30,0xC0,0x6A,0x01,0x22,0x40,0x30, + 0x40,0x7D,0x40,0x1E,0x40,0x33,0x5A,0x70,0x58,0x4B,0xC0,0xB2,0x1A,0x75,0x81,0xE7, + 0xF0,0xB5,0x57,0x48,0x8B,0xB0,0x01,0x88,0x09,0x91,0x41,0x88,0x08,0x91,0xC1,0x88, + 0x07,0x91,0x81,0x89,0x06,0x91,0x01,0x89,0x05,0x91,0x40,0x89,0x04,0x90,0x53,0x48, + 0x01,0x7C,0x03,0x91,0x81,0x7C,0x02,0x91,0x40,0x7C,0x01,0x90,0x48,0x48,0x51,0x4F, + 0x40,0x30,0x00,0x90,0xC3,0x6A,0x06,0x24,0x18,0x46,0x40,0x30,0x01,0x7D,0x42,0x7D, + 0x46,0x78,0x89,0x18,0x1A,0x46,0x20,0x32,0xD5,0x7F,0x89,0x1C,0xAD,0x19,0xAD,0x1C, + 0x47,0x4E,0xAC,0x46,0xF5,0x78,0x36,0x79,0xB6,0x00,0xF6,0x19,0xAE,0x5D,0x65,0x46, + 0x75,0x19,0x8E,0x1D,0xB5,0x42,0x02,0xD2,0x6D,0x00,0xB5,0x42,0x01,0xD3,0x69,0x1A, + 0xCC,0xB2,0x41,0x49,0x71,0x25,0xCD,0x71,0x01,0x7A,0x3C,0x4D,0x09,0x01,0x49,0x1C, + 0x29,0x74,0x50,0x21,0x69,0x74,0x06,0x7D,0x21,0x02,0x31,0x43,0x34,0x4E,0x31,0x81, + 0x60,0x33,0x19,0x8A,0xF1,0x80,0x91,0x79,0x52,0x79,0x80,0x27,0x12,0x01,0x3A,0x43, + 0x11,0x43,0xA9,0x74,0x34,0x49,0xC9,0x79,0x89,0x07,0x01,0xD5,0x33,0x49,0x01,0xE0, + 0x32,0x49,0x09,0x1F,0x71,0x80,0x41,0x21,0x31,0x80,0x40,0x7D,0xFF,0x30,0xFF,0x30, + 0x02,0x30,0x70,0x81,0xFF,0xF7,0x2A,0xFC,0x00,0x98,0xC0,0x6A,0x20,0x30,0x42,0x79, + 0x81,0x79,0x12,0x01,0x3A,0x43,0x11,0x43,0xA9,0x74,0x1F,0x49,0x28,0x4F,0x49,0x79, + 0x01,0x29,0x0E,0xD8,0x00,0x79,0xB0,0x81,0xB9,0x68,0x02,0x20,0x88,0x47,0x01,0x20, + 0xFF,0xF7,0x74,0xFF,0x17,0x48,0x04,0x70,0x00,0x98,0xC0,0x6A,0x60,0x30,0x00,0x8A, + 0xF0,0x80,0x01,0x20,0xFF,0xF7,0x7A,0xFD,0x1E,0x48,0x81,0x6A,0x01,0x20,0x88,0x47, + 0x01,0x20,0x00,0xF0,0x46,0xFC,0x09,0x98,0x30,0x80,0x08,0x98,0x70,0x80,0x07,0x98, + 0xF0,0x80,0x06,0x98,0xB0,0x81,0x05,0x98,0x30,0x81,0x04,0x98,0x70,0x81,0x03,0x98, + 0x28,0x74,0x02,0x98,0xA8,0x74,0x01,0x98,0x68,0x74,0x81,0x20,0x00,0x02,0x80,0x6B, + 0x80,0x47,0x39,0x68,0x02,0x20,0x88,0x47,0x0B,0xB0,0xF0,0xBD,0xFF,0x01,0xFE,0x02, + 0x04,0x01,0x00,0x20,0xC2,0x01,0x00,0x20,0x04,0x00,0x00,0x20,0x80,0x01,0x00,0x20, + 0x00,0x10,0x00,0x40,0x38,0x18,0x00,0x20,0x54,0x2F,0x00,0x00,0x60,0x12,0x00,0x40, + 0x04,0x16,0x00,0x20,0xC0,0x30,0x00,0x00,0x00,0x03,0x00,0x40,0x07,0x10,0x00,0x00, + 0x80,0x81,0x00,0x00,0x80,0x80,0x00,0x00,0xF0,0xB5,0x92,0x4C,0x8A,0xB0,0xE6,0x6A, + 0x25,0x46,0x33,0x79,0x80,0x3D,0xED,0x69,0x58,0x43,0x2D,0x18,0x8E,0x48,0x22,0x68, + 0x40,0x7B,0x01,0x28,0x01,0xD1,0xF3,0x79,0x22,0x69,0x00,0x20,0x6C,0x46,0x09,0xE0, + 0x00,0x29,0x0B,0xD0,0x82,0x26,0x26,0x54,0xF7,0xB2,0x40,0xCA,0x20,0x3E,0xF7,0x77, + 0x40,0x1C,0xC0,0xB2,0x98,0x42,0xF3,0xD3,0x0A,0xB0,0xBE,0xE7,0x2E,0x5C,0x80,0x27, + 0x3E,0x43,0xF0,0xE7,0xF0,0xB5,0x80,0x48,0x8D,0xB0,0x87,0x79,0x7D,0x48,0x0B,0x90, + 0xC0,0x6A,0x85,0x79,0x41,0x79,0x09,0x91,0x7A,0x49,0x80,0x39,0x08,0x91,0x00,0x79, + 0x49,0x69,0x78,0x43,0x40,0x00,0x0C,0x18,0x78,0x49,0x01,0x20,0x08,0x76,0x76,0x48, + 0x80,0x30,0x80,0x7F,0x00,0x28,0x71,0xD0,0xAF,0x42,0x70,0xD2,0x74,0x48,0x01,0x78, + 0x74,0x48,0x06,0x78,0x74,0x48,0x71,0x43,0x08,0x18,0x0A,0x90,0x73,0x48,0x00,0x21, + 0xC2,0x69,0x02,0xA8,0x90,0x47,0x6E,0x48,0x69,0x1E,0x00,0x78,0x3A,0x18,0x8A,0x42, + 0x37,0xD2,0x38,0x43,0x02,0xD1,0x01,0x20,0x00,0xF0,0x5C,0xFB,0x01,0x20,0x80,0x07, + 0x41,0x88,0x08,0x22,0x11,0x43,0x41,0x80,0x69,0x4A,0x11,0x88,0x02,0x23,0x19,0x43, + 0x11,0x80,0x41,0x88,0x04,0x23,0x19,0x43,0x41,0x80,0x61,0x48,0x01,0x78,0x61,0x48, + 0x00,0x78,0x83,0x1E,0x99,0x42,0x04,0xD0,0x01,0x2E,0x14,0xD1,0xAB,0x1E,0x9F,0x42, + 0x11,0xD1,0x3B,0x18,0x1B,0x18,0xAB,0x42,0x01,0xD9,0x28,0x1A,0x01,0xE0,0x78,0x18, + 0x80,0x1C,0x08,0x99,0xC0,0xB2,0x09,0x6A,0x09,0x5C,0x0B,0x02,0x0B,0x43,0x93,0x81, + 0x00,0x21,0xFF,0xF7,0x79,0xFF,0x57,0x48,0x00,0x78,0x40,0x1C,0xC0,0xB2,0x00,0xF0, + 0x29,0xFB,0x11,0x21,0x09,0x9A,0x30,0x02,0x10,0x43,0x00,0x90,0x01,0x91,0x02,0xA8, + 0x81,0xB2,0x4E,0x4F,0x0A,0x98,0x7F,0x6A,0xA3,0xB2,0xA2,0xB2,0x80,0xB2,0xB8,0x47, + 0x47,0x49,0x72,0x1E,0x08,0x78,0x90,0x42,0x2D,0xD1,0x43,0x4A,0x00,0x20,0x93,0x79, + 0x9B,0x19,0x93,0x71,0x08,0x70,0x48,0x49,0x09,0x78,0x02,0x29,0x08,0xD0,0x04,0x29, + 0x08,0xD0,0x08,0x29,0x08,0xD0,0x10,0x29,0x08,0xD0,0x08,0xE0,0x3F,0xE0,0x36,0xE0, + 0x01,0x20,0x04,0xE0,0x02,0x20,0x02,0xE0,0x03,0x20,0x00,0xE0,0x04,0x20,0x01,0x2E, + 0x13,0xD0,0x00,0x28,0x11,0xD0,0x37,0x49,0x0A,0x78,0x09,0x99,0x4A,0x43,0x00,0x21, + 0x06,0xE0,0x00,0x23,0xE3,0x5E,0x03,0x41,0x23,0x80,0xA4,0x1C,0x49,0x1C,0x89,0xB2, + 0x91,0x42,0xF6,0xD3,0x01,0xE0,0x40,0x1C,0x08,0x70,0x2B,0x4A,0x90,0x79,0x29,0x1A, + 0x2C,0x48,0x00,0x78,0x81,0x42,0x12,0xDA,0x00,0x29,0x10,0xDD,0x41,0x1A,0x28,0x1A, + 0xC0,0xB2,0xCB,0xB2,0x90,0x71,0x0B,0x99,0xC9,0x6A,0x09,0x79,0x48,0x43,0x42,0x00, + 0x08,0x98,0x59,0x43,0x40,0x69,0x49,0x00,0x10,0x18,0x01,0xF0,0x7B,0xF8,0x1E,0x48, + 0x80,0x79,0xA8,0x42,0x05,0xD0,0x23,0x49,0x08,0x68,0x40,0x1C,0x08,0x60,0x0D,0xB0, + 0xEB,0xE6,0x1A,0x49,0x01,0x20,0x48,0x76,0xF9,0xE7,0x70,0xB5,0x17,0x49,0x00,0x20, + 0x88,0x83,0x1E,0x4C,0x01,0x26,0x26,0x70,0x20,0x82,0x60,0x82,0xE0,0x83,0x20,0x62, + 0x60,0x62,0x60,0x71,0xA0,0x71,0xE0,0x70,0x20,0x71,0x19,0x4D,0xFF,0x20,0x28,0x70, + 0x08,0x21,0x18,0x48,0x01,0xF0,0x56,0xF8,0x08,0x21,0x17,0x48,0x01,0xF0,0x52,0xF8, + 0x01,0x22,0x16,0x21,0x15,0x48,0x01,0xF0,0x28,0xF8,0x12,0x48,0xA5,0x60,0x60,0x61, + 0x11,0x48,0xA0,0x61,0x12,0x48,0xE0,0x60,0x66,0x70,0x04,0x20,0xA0,0x70,0x70,0xBD, + 0x70,0x47,0x70,0x47,0x44,0x01,0x00,0x20,0x04,0x00,0x00,0x20,0x80,0x01,0x00,0x20, + 0xC3,0x01,0x00,0x20,0xA4,0x01,0x00,0x20,0x3C,0x16,0x00,0x20,0x80,0x81,0x00,0x00, + 0x00,0x10,0x00,0x40,0xC4,0x01,0x00,0x20,0xA5,0x01,0x00,0x20,0x04,0x16,0x00,0x20, + 0xB0,0x01,0x00,0x20,0xB2,0x01,0x00,0x20,0xBA,0x01,0x00,0x20,0x22,0x18,0x00,0x20, + 0xC0,0x30,0x00,0x00,0xF3,0xB5,0x83,0xB0,0xFC,0x48,0x02,0x90,0xC0,0x6A,0x41,0x79, + 0x85,0x79,0x8E,0x46,0x20,0x30,0x81,0x78,0xF8,0x48,0x80,0x38,0x84,0x46,0x00,0x29, + 0x76,0xD0,0xC0,0x38,0x01,0x6B,0x80,0x6A,0x01,0x42,0x71,0xD1,0x00,0x22,0x63,0x46, + 0x03,0x9F,0x5C,0x6A,0x7F,0x42,0x10,0x46,0x11,0x46,0x13,0x46,0x01,0x97,0x11,0xE0, + 0x00,0x26,0xA6,0x5F,0x03,0x9F,0xBE,0x42,0x01,0xDD,0x40,0x1C,0x08,0xE0,0x01,0x9F, + 0xBE,0x42,0x05,0xDA,0x04,0x9F,0x49,0x1C,0xBE,0x42,0x01,0xDA,0x52,0x1C,0xD2,0xB2, + 0xA4,0x1C,0x5B,0x1C,0x73,0x45,0xEB,0xD3,0xE4,0x4B,0x40,0x3B,0x00,0x93,0x1C,0x68, + 0x00,0x23,0x11,0xE0,0x00,0x26,0xA6,0x5F,0x03,0x9F,0xBE,0x42,0x01,0xDD,0x40,0x1C, + 0x08,0xE0,0x01,0x9F,0xBE,0x42,0x05,0xDA,0x04,0x9F,0x49,0x1C,0xBE,0x42,0x01,0xDA, + 0x52,0x1C,0xD2,0xB2,0xA4,0x1C,0x5B,0x1C,0xAB,0x42,0xEB,0xD3,0xD8,0x4B,0x04,0x28, + 0x9B,0x7C,0x01,0xD8,0x00,0x29,0x08,0xD0,0x5B,0x1C,0xD5,0x49,0xD8,0xB2,0x88,0x74, + 0x00,0x2A,0x07,0xD0,0x40,0x1D,0x88,0x74,0x04,0xE0,0xD1,0x48,0x00,0x2B,0x2A,0xD0, + 0x5B,0x1E,0x83,0x74,0xCE,0x48,0x80,0x7C,0x32,0x28,0x24,0xD9,0x60,0x46,0x86,0x6B, + 0xC4,0x6A,0x03,0x6B,0x00,0x20,0x07,0x46,0x04,0xE0,0x41,0x00,0x62,0x5A,0x5A,0x52, + 0x37,0x54,0x40,0x1C,0x70,0x45,0xF8,0xD3,0x00,0x98,0x86,0x68,0x44,0x69,0xC3,0x68, + 0x00,0x20,0x04,0xE0,0x41,0x00,0x72,0x5A,0x5A,0x52,0x27,0x54,0x40,0x1C,0xA8,0x42, + 0xF8,0xD3,0xBF,0x48,0x01,0x21,0x87,0x74,0xBE,0x48,0x41,0x71,0x03,0xE0,0xFF,0xE7, + 0xBB,0x49,0x00,0x20,0x88,0x74,0x02,0x9A,0x71,0x46,0x4D,0x43,0x00,0x26,0xD7,0x6A, + 0x60,0x46,0x3B,0x46,0x80,0x69,0xAC,0x46,0x34,0x46,0x31,0x46,0x20,0x33,0x10,0xE0, + 0x00,0x22,0x82,0x5E,0x1D,0x7C,0xAA,0x42,0x04,0xDD,0x3D,0x78,0xAA,0x42,0x01,0xDA, + 0x76,0x1C,0x04,0xE0,0x14,0x25,0x5D,0x57,0xAA,0x42,0x00,0xDA,0x64,0x1C,0x80,0x1C, + 0x49,0x1C,0x61,0x45,0xEC,0xD3,0x98,0x78,0x00,0x25,0x14,0x27,0x00,0x28,0x0F,0xD0, + 0x05,0x2C,0x04,0xD9,0xA7,0x48,0x80,0x6A,0x00,0x28,0x07,0xD0,0x01,0xE0,0x00,0x2C, + 0x06,0xD0,0xA4,0x49,0x88,0x6A,0x09,0x6B,0x08,0x42,0x01,0xD1,0x01,0x25,0x28,0x27, + 0x60,0x46,0x80,0x00,0x05,0x21,0x00,0xF0,0x61,0xFF,0x86,0x42,0x03,0xD2,0x84,0x42, + 0x01,0xD2,0x01,0x2D,0x0E,0xD1,0x9A,0x49,0xC8,0x7C,0x40,0x1C,0xC0,0xB2,0xC8,0x74, + 0xB8,0x42,0x12,0xD3,0x97,0x48,0x60,0x30,0x42,0x7F,0x01,0x23,0x1A,0x43,0x42,0x77, + 0x00,0x20,0x09,0xE0,0x40,0x08,0xB0,0x42,0x07,0xD9,0xA0,0x42,0x05,0xD9,0x90,0x49, + 0xC8,0x7C,0x00,0x28,0x01,0xD0,0x40,0x1E,0xC8,0x74,0x05,0xB0,0xF0,0xBD,0xF0,0xB5, + 0x8A,0x49,0x8A,0x48,0xC9,0x6A,0x40,0x38,0xCF,0x78,0x95,0xB0,0x00,0x68,0x09,0x79, + 0x14,0x91,0x89,0x49,0x06,0x46,0x49,0x8A,0x64,0x29,0x01,0xD2,0x00,0x21,0x06,0xE0, + 0x64,0x39,0xFF,0x22,0x89,0xB2,0x91,0x32,0x91,0x42,0x00,0xD9,0x11,0x46,0x89,0x08, + 0xFA,0x31,0x10,0x91,0x00,0x21,0x0D,0x46,0x0C,0x46,0x13,0x91,0x0B,0xE0,0x00,0x22, + 0x82,0x5E,0x3C,0x2A,0x01,0xDD,0x6D,0x1C,0xED,0xB2,0xA2,0x42,0x00,0xDD,0x14,0x46, + 0x80,0x1C,0x49,0x1C,0x89,0xB2,0xB9,0x42,0xF1,0xD3,0xB8,0x00,0x05,0x21,0x00,0xF0, + 0x0D,0xFF,0xA8,0x42,0x07,0xD2,0xFF,0x20,0x2D,0x30,0x84,0x42,0x03,0xDD,0xA0,0xB2, + 0x10,0x90,0x01,0x20,0x13,0x90,0x10,0x98,0x84,0x42,0x00,0xDD,0x04,0xB2,0x00,0x25, + 0x52,0xE0,0x00,0x20,0x31,0x46,0x20,0x39,0x30,0x5E,0xC9,0x8B,0x10,0xAB,0x99,0x80, + 0xD8,0x80,0x71,0x88,0x02,0x46,0x19,0x81,0x00,0x2D,0x02,0xD1,0x00,0x21,0x99,0x80, + 0x05,0xE0,0x79,0x1E,0x8D,0x42,0x02,0xD1,0x00,0x21,0x10,0xAB,0x19,0x81,0x00,0x28, + 0x01,0xDC,0x01,0x20,0x03,0xE0,0x10,0x9B,0x98,0x42,0x00,0xDD,0x18,0x46,0x10,0xAB, + 0x04,0x21,0x59,0x5E,0x8C,0x46,0x8A,0x42,0x13,0xDA,0x08,0x21,0x59,0x5E,0x8A,0x42, + 0x0F,0xDA,0x1E,0x29,0x02,0xDC,0x62,0x46,0x1E,0x2A,0x0A,0xDD,0x60,0x46,0x40,0x18, + 0x40,0x10,0x02,0xB2,0x32,0x80,0x00,0x2A,0x03,0xDC,0x61,0x45,0x00,0xDC,0x61,0x46, + 0x48,0x10,0x13,0x99,0x00,0x29,0x06,0xD0,0x3C,0x28,0x01,0xD9,0x3C,0x38,0x00,0xE0, + 0x01,0x20,0x3C,0x3C,0x24,0xB2,0x1E,0x2C,0x12,0xDD,0x00,0x02,0x21,0x46,0x00,0xF0, + 0xB5,0xFE,0x81,0xB2,0x68,0x00,0x6A,0x46,0x11,0x52,0x00,0x29,0x01,0xD1,0x01,0x21, + 0x11,0x52,0xB6,0x1C,0x6D,0x1C,0xAD,0xB2,0xBD,0x42,0xAA,0xD3,0x00,0x23,0x23,0xE0, + 0xFF,0x20,0x01,0x30,0x69,0x00,0x6A,0x46,0x50,0x52,0xF2,0xE7,0x3B,0x48,0x59,0x00, + 0x80,0x38,0x80,0x69,0x14,0x9A,0x40,0x18,0x00,0x21,0x55,0x00,0x10,0xE0,0x00,0x22, + 0x82,0x5E,0x0F,0x2A,0x09,0xDB,0x4C,0x00,0x6E,0x46,0x34,0x5B,0x54,0x43,0x24,0x0A, + 0xE6,0x00,0x34,0x1B,0xA2,0x18,0xD2,0x10,0x02,0x80,0x28,0x18,0x49,0x1C,0xC9,0xB2, + 0xB9,0x42,0xEC,0xD3,0x5B,0x1C,0xDB,0xB2,0x14,0x98,0x83,0x42,0xDE,0xD3,0x15,0xB0, + 0xF0,0xBD,0x2D,0x48,0xC0,0x8B,0x00,0x28,0x00,0xD0,0x38,0xE7,0x70,0x47,0x28,0x49, + 0x00,0x20,0x08,0x74,0x48,0x74,0x88,0x74,0xC8,0x74,0x70,0x47,0xF3,0xB5,0x23,0x49, + 0x85,0xB0,0xC9,0x6A,0xCA,0x78,0x00,0x92,0x0D,0x79,0x20,0x49,0x80,0x39,0x04,0x91, + 0x4E,0x6A,0xC0,0x39,0x0C,0x6B,0x00,0x22,0x11,0x46,0x03,0x94,0x2B,0xE0,0x4B,0x00, + 0x9C,0x46,0x9B,0x19,0x9E,0x46,0x20,0x3B,0xDF,0x8B,0x6B,0x46,0x9F,0x80,0x63,0x46, + 0xF7,0x5E,0x6B,0x46,0xDF,0x80,0xBC,0x46,0x73,0x46,0x5F,0x88,0x6B,0x46,0x1F,0x81, + 0x00,0x29,0x02,0xD1,0x00,0x27,0x9F,0x80,0x05,0xE0,0x6B,0x1E,0x99,0x42,0x02,0xD1, + 0x00,0x27,0x6B,0x46,0x1F,0x81,0xE3,0x07,0x0B,0xD0,0x6B,0x46,0x04,0x27,0xDF,0x5F, + 0x87,0x42,0x06,0xDA,0x84,0x45,0x04,0xDA,0x08,0x27,0xDF,0x5F,0x87,0x42,0x00,0xDA, + 0x52,0x1C,0x64,0x08,0x49,0x1C,0xA9,0x42,0xD1,0xD3,0x05,0x4C,0x00,0x2A,0x61,0x7C, + 0x20,0x7C,0x33,0xD0,0x00,0x29,0x09,0xD0,0x0A,0x21,0x09,0xE0,0x44,0x01,0x00,0x20, + 0x80,0x01,0x00,0x20,0x04,0x00,0x00,0x20,0x04,0x16,0x00,0x20,0x06,0x99,0x09,0xB2, + 0x88,0x42,0x03,0xDA,0x52,0x1C,0x52,0x08,0x80,0x18,0x20,0x74,0x20,0x7C,0x88,0x42, + 0x1A,0xDB,0x26,0x48,0x80,0x6A,0x00,0x28,0x02,0xD0,0x03,0x99,0x01,0x42,0x11,0xD1, + 0x04,0x9A,0x04,0x98,0x96,0x69,0x00,0x9A,0x04,0x99,0x6A,0x43,0x55,0x00,0x80,0x68, + 0xC9,0x68,0x2A,0x46,0x00,0xF0,0x98,0xFD,0x29,0x46,0x30,0x46,0x00,0xF0,0xFA,0xFD, + 0x00,0x20,0x20,0x74,0xC8,0x20,0x60,0x74,0x07,0xB0,0xF0,0xBD,0x00,0x29,0x04,0xD0, + 0x03,0x9A,0x00,0x2A,0x01,0xD1,0x49,0x1E,0x61,0x74,0x00,0x28,0xF4,0xD0,0x40,0x1E, + 0x20,0x74,0xF1,0xE7,0x70,0xB5,0x12,0x4C,0x00,0x22,0xE5,0x8B,0x0F,0x4B,0xE2,0x83, + 0xDA,0x72,0x1A,0x73,0x9A,0x73,0x1A,0x46,0x60,0x32,0x51,0x7F,0x53,0x7F,0x49,0x07, + 0xC9,0x0F,0x49,0x00,0xFD,0x26,0x33,0x40,0x0B,0x43,0x53,0x77,0x51,0x7F,0xFB,0x23, + 0x19,0x40,0x51,0x77,0x07,0x49,0x01,0x22,0x8E,0x6A,0x01,0x46,0x00,0x20,0x19,0x23, + 0xB0,0x47,0x05,0x48,0x80,0x68,0x80,0x47,0xE5,0x83,0x70,0xBD,0x04,0x00,0x00,0x20, + 0x04,0x16,0x00,0x20,0xC0,0x81,0x00,0x00,0x80,0x80,0x00,0x00,0xFC,0x48,0x00,0x21, + 0x01,0x76,0xFC,0x49,0x11,0x22,0x8A,0x80,0x43,0x22,0x0A,0x80,0x01,0x7E,0x00,0x29, + 0xFC,0xD0,0x70,0x47,0xF8,0x4B,0x10,0xB5,0x02,0x01,0xD0,0x18,0xF7,0x49,0x44,0x78, + 0x4C,0x70,0x9A,0x5C,0x0A,0x70,0xC2,0x78,0x4A,0x72,0x82,0x78,0x0A,0x72,0x42,0x79, + 0x4A,0x74,0x02,0x79,0x0A,0x74,0xC2,0x79,0x4A,0x76,0x82,0x79,0x0A,0x76,0xEF,0x49, + 0x42,0x7A,0x20,0x31,0x4A,0x70,0x02,0x7A,0x0A,0x70,0xC2,0x7A,0x4A,0x72,0x80,0x7A, + 0x08,0x72,0x10,0xBD,0xF0,0xB5,0xEA,0x4E,0x94,0x00,0x33,0x68,0xA4,0x46,0x1B,0x19, + 0x34,0x46,0x80,0x3C,0xF7,0x6A,0xE4,0x6B,0x3D,0x79,0xA4,0x18,0x00,0x28,0x06,0xD1, + 0x30,0x46,0x40,0x38,0x73,0x68,0x80,0x69,0xBD,0x79,0x63,0x44,0x84,0x18,0x02,0x29, + 0x10,0xD1,0x80,0x20,0x0F,0x21,0x0A,0xE0,0x26,0x78,0x1F,0x68,0x06,0x43,0x20,0x3F, + 0xFE,0x77,0x1E,0x68,0x31,0x70,0x08,0x33,0xA4,0x1C,0x92,0x1C,0xD2,0xB2,0xAA,0x42, + 0xF2,0xD3,0xF0,0xBD,0x03,0x29,0xFC,0xD1,0x00,0x20,0x07,0xE0,0x19,0x68,0x20,0x39, + 0xC8,0x77,0x19,0x68,0x08,0x70,0x08,0x33,0x92,0x1C,0xD2,0xB2,0xAA,0x42,0xF5,0xD3, + 0xF0,0xBD,0xF1,0xB5,0x82,0xB0,0xCE,0x48,0x01,0x90,0xC2,0x6A,0x80,0x38,0xC1,0x6A, + 0x83,0x6B,0x8E,0x46,0x44,0x6A,0x01,0x6B,0x02,0x98,0x15,0x79,0x9C,0x46,0x00,0x28, + 0x09,0xD1,0xC7,0x48,0x95,0x79,0x40,0x38,0x81,0x68,0x42,0x69,0x8E,0x46,0x94,0x46, + 0x04,0x68,0xC1,0x68,0x03,0xE0,0xC3,0x4A,0x00,0x20,0x50,0x62,0x90,0x62,0x00,0x20, + 0x3A,0xE0,0x42,0x00,0x73,0x46,0x9B,0x5A,0x8E,0x5A,0x13,0x27,0x9B,0x1B,0x1B,0xB2, + 0xA3,0x52,0x01,0x9E,0xF6,0x6A,0x20,0x36,0xF7,0x57,0x9F,0x42,0x09,0xDD,0x02,0x9A, + 0x01,0x2A,0x27,0xD1,0xB7,0x4E,0x01,0x23,0x72,0x6A,0x83,0x40,0x1A,0x43,0x72,0x62, + 0x20,0xE0,0xF6,0x7B,0x9E,0x42,0x09,0xDA,0x02,0x9A,0x01,0x2A,0x1A,0xD1,0xB1,0x4E, + 0x01,0x23,0xB2,0x6A,0x83,0x40,0x1A,0x43,0xB2,0x62,0x13,0xE0,0xAD,0x4B,0x20,0x33, + 0x1B,0x7D,0x00,0x2B,0x0E,0xD1,0x8F,0x5E,0x63,0x46,0x1B,0x5C,0x3E,0x02,0x9E,0x19, + 0x73,0x46,0x9B,0x5E,0x9B,0x00,0x9E,0x19,0xBB,0x00,0xF3,0x1A,0x1E,0x12,0x8E,0x52, + 0x62,0x46,0x13,0x54,0x40,0x1C,0xC0,0xB2,0xA8,0x42,0xC2,0xD3,0x00,0x20,0x13,0x23, + 0xDB,0x43,0x06,0x46,0x02,0x46,0x47,0x1F,0x10,0xE0,0x51,0x00,0x61,0x5E,0xB9,0x42, + 0x03,0xDA,0x99,0x42,0x07,0xDA,0x19,0x46,0x05,0xE0,0x05,0x29,0x03,0xDD,0x14,0x29, + 0x00,0xDD,0x14,0x21,0x76,0x1C,0x40,0x18,0x52,0x1C,0xD2,0xB2,0xAA,0x42,0xEC,0xD3, + 0x29,0x46,0x00,0xF0,0xED,0xFC,0x03,0x2E,0x10,0xDD,0x00,0x22,0x0C,0xE0,0x53,0x00, + 0xE1,0x5E,0x00,0x28,0x05,0xDD,0x81,0x42,0x02,0xDD,0x09,0x1A,0x09,0xB2,0x00,0xE0, + 0x01,0x21,0x52,0x1C,0xE1,0x52,0xD2,0xB2,0xAA,0x42,0xF0,0xD3,0xFE,0xBD,0xF1,0xB5, + 0x9A,0xB0,0x87,0x48,0x19,0x90,0xC0,0x6A,0x87,0x4C,0x05,0x79,0xC1,0x78,0xA2,0x78, + 0x06,0x92,0x1A,0x9A,0x1E,0x2A,0x01,0xD2,0x1E,0x22,0x1A,0x92,0x00,0x7D,0x00,0x26, + 0x02,0x06,0x7F,0x48,0x80,0x38,0x18,0x90,0x00,0x2A,0x0A,0xDB,0x4D,0x43,0x69,0x00, + 0x80,0x69,0x00,0xF0,0xAF,0xFC,0x76,0x48,0x86,0x83,0xE6,0x70,0x26,0x71,0x1B,0xB0, + 0xF0,0xBD,0x7A,0x48,0x81,0x68,0x05,0x20,0x88,0x47,0x78,0x4F,0x00,0x21,0x40,0x3F, + 0xFA,0x6B,0x01,0x20,0x90,0x47,0x01,0x21,0xBA,0x6B,0x00,0x20,0x90,0x47,0x6D,0x48, + 0x81,0x8A,0x6B,0x46,0x99,0x85,0x72,0x49,0x8A,0x7C,0xDA,0x85,0xC2,0x88,0x1A,0x86, + 0x82,0x89,0x5A,0x86,0x4A,0x7C,0xDA,0x86,0x0A,0x7C,0x1A,0x87,0x3B,0x22,0x4A,0x74, + 0x13,0x22,0x0A,0x74,0x6B,0x4A,0x42,0x80,0x08,0x22,0xC2,0x80,0x00,0x22,0x82,0x81, + 0x93,0x20,0x88,0x74,0x08,0x92,0x07,0x92,0xA8,0x00,0x69,0x00,0x01,0x92,0x16,0x91, + 0x42,0x18,0x18,0x99,0x17,0x90,0x15,0x92,0x89,0x69,0x0F,0x91,0x08,0x18,0x10,0x90, + 0x52,0x18,0x00,0x20,0x11,0x92,0x09,0x90,0x20,0x78,0x5F,0x4E,0x00,0x28,0x07,0xD0, + 0x61,0x78,0x00,0x29,0x04,0xD0,0x20,0x6A,0x00,0xF0,0x68,0xFC,0xC8,0xB2,0x09,0x90, + 0x06,0x99,0x09,0x98,0xE2,0x68,0x48,0x43,0x14,0x90,0x10,0x18,0x00,0x25,0x0A,0x90, + 0x77,0xE0,0x0A,0x98,0x51,0x49,0x40,0x5D,0xA2,0x6A,0x40,0x31,0x00,0x92,0x0F,0x68, + 0x0F,0xA9,0x0E,0xC9,0xB8,0x47,0x69,0x00,0x02,0xAA,0x50,0x52,0x14,0x98,0xA3,0x69, + 0x40,0x00,0x40,0x18,0x1F,0x5E,0x52,0x5A,0x1A,0x52,0x02,0xAA,0x52,0x5E,0xD3,0x1B, + 0x00,0xD5,0x5B,0x42,0xD2,0x18,0x12,0xB2,0x02,0xAB,0x5A,0x52,0x63,0x69,0x1B,0x5A, + 0xD7,0x1A,0x19,0x2F,0x06,0xDD,0x57,0x00,0xD2,0x19,0x9A,0x18,0x92,0x10,0x02,0xAB, + 0x5A,0x52,0x05,0xE0,0x5F,0x00,0xDB,0x19,0x9A,0x18,0x02,0xAF,0x92,0x10,0x7A,0x52, + 0x02,0xAA,0x67,0x69,0x53,0x5A,0x3B,0x52,0x50,0x5E,0xB0,0x42,0x01,0xDA,0x06,0x46, + 0x08,0x95,0x01,0x99,0x88,0x42,0x01,0xDD,0x07,0x95,0x01,0x90,0x11,0x99,0x17,0x98, + 0x40,0x18,0x11,0x90,0x10,0x99,0x17,0x98,0x40,0x18,0x10,0x90,0x1A,0x98,0x86,0x42, + 0x1F,0xDA,0x27,0x48,0x80,0x8B,0x00,0x28,0x1B,0xD1,0xE0,0x78,0xA8,0x42,0x18,0xD1, + 0x20,0x79,0x09,0x99,0x88,0x42,0x14,0xD1,0x20,0x6A,0x6B,0x46,0x40,0x1E,0x20,0x62, + 0x08,0x95,0xE5,0x70,0x09,0x98,0x20,0x71,0x08,0x21,0x1A,0x98,0x59,0x5E,0x14,0x38, + 0x81,0x42,0x05,0xDA,0x1A,0x48,0x80,0x8B,0x00,0x28,0x01,0xD1,0x08,0x90,0xE0,0x70, + 0xA5,0xE0,0x19,0x98,0x40,0x6B,0x80,0x7A,0xCA,0x28,0x01,0xD1,0x08,0x95,0x9E,0xE0, + 0x20,0x78,0x00,0x28,0x03,0xD1,0x08,0x95,0xE5,0x70,0x20,0x71,0x97,0xE0,0x6D,0x1C, + 0xED,0xB2,0x06,0x98,0x85,0x42,0x84,0xD3,0x04,0x28,0x31,0xD1,0x07,0x98,0x03,0x28, + 0x0A,0xD1,0x6B,0x46,0x0A,0x20,0x08,0x21,0x18,0x5E,0x59,0x5E,0x88,0x42,0x01,0xDA, + 0x01,0x20,0x24,0xE0,0x00,0x20,0x22,0xE0,0x00,0x28,0x21,0xD1,0x6B,0x46,0x0C,0x20, + 0x0E,0x21,0x18,0x5E,0x59,0x5E,0x88,0x42,0x18,0xDA,0x02,0x20,0x17,0xE0,0x00,0x00, + 0x80,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0x4C,0x16,0x00,0x20,0x40,0x03,0x00,0x40, + 0x44,0x01,0x00,0x20,0x04,0x00,0x00,0x20,0x04,0x16,0x00,0x20,0x80,0x81,0x00,0x00, + 0x60,0x12,0x00,0x40,0x82,0x11,0x00,0x00,0xFF,0x7F,0x00,0x00,0x03,0x20,0x08,0x90, + 0xA2,0x68,0x09,0x99,0x08,0x98,0x50,0x54,0x20,0x79,0x13,0x90,0x05,0x90,0xE2,0x78, + 0x12,0x92,0x63,0x78,0xFB,0x4E,0x00,0x20,0x9C,0x46,0x09,0x99,0x10,0xE0,0xA3,0x68, + 0x1B,0x5C,0xFF,0x2B,0x0A,0xD0,0x06,0x9D,0x5B,0x00,0x45,0x43,0x6D,0x00,0xEB,0x18, + 0x65,0x69,0xEF,0x5A,0xB7,0x42,0x01,0xDA,0xEE,0x5E,0x01,0x46,0x40,0x1C,0xC0,0xB2, + 0x84,0x45,0xEC,0xD8,0xEF,0x48,0x86,0x42,0x02,0xD0,0x05,0x91,0xA0,0x68,0x42,0x5C, + 0x60,0x6A,0x00,0x28,0x09,0xD1,0x61,0x71,0xA0,0x68,0x42,0x5C,0xA2,0x71,0x21,0x71, + 0x40,0x5C,0xE0,0x70,0x01,0x20,0x60,0x62,0x29,0xE0,0x12,0x99,0x91,0x42,0x03,0xD1, + 0x05,0x9B,0x13,0x99,0x99,0x42,0x19,0xD0,0x06,0x9B,0x13,0x99,0x06,0x9F,0x59,0x43, + 0x12,0x9B,0x05,0x9D,0x49,0x00,0x5B,0x00,0xCB,0x18,0x7D,0x43,0x61,0x69,0x6D,0x00, + 0x57,0x00,0xCB,0x5A,0xED,0x19,0x49,0x5B,0x1E,0x31,0x8B,0x42,0x08,0xD9,0x40,0x1C, + 0x60,0x62,0x06,0x28,0x08,0xD3,0xE2,0x70,0x05,0x98,0x20,0x71,0x01,0x20,0x02,0xE0, + 0x01,0x28,0x01,0xD9,0x40,0x1E,0x60,0x62,0xA2,0x71,0x05,0x98,0x60,0x71,0x1A,0x99, + 0x01,0x98,0x32,0x31,0x88,0x42,0x0B,0xDD,0xCF,0x49,0x1E,0x20,0x88,0x83,0x01,0x99, + 0x8A,0x19,0x1A,0x99,0xFF,0x31,0x5F,0x31,0x8A,0x42,0x19,0xDD,0xE0,0x83,0x17,0xE0, + 0x1A,0x99,0x88,0x42,0x14,0xDA,0xE0,0x8B,0x00,0x28,0x01,0xD0,0x40,0x1E,0xE0,0x83, + 0x1A,0x99,0x01,0x98,0x14,0x39,0x88,0x42,0x0A,0xDA,0xC3,0x49,0x88,0x8B,0x00,0x28, + 0x06,0xD0,0x40,0x1E,0x00,0x04,0x00,0x0C,0x88,0x83,0x01,0xD1,0xE0,0x6A,0x80,0x47, + 0x18,0x98,0x15,0x9A,0x81,0x69,0x50,0x18,0x17,0x9A,0x8D,0x18,0x08,0x9A,0x16,0x99, + 0x51,0x43,0x4F,0x00,0x39,0x18,0x16,0x9A,0x00,0xF0,0xAE,0xFA,0x79,0x19,0x28,0x46, + 0x16,0x9A,0x00,0xF0,0xA9,0xFA,0x26,0x82,0x01,0x98,0x60,0x82,0x20,0x79,0x06,0x99, + 0xE2,0x68,0x48,0x43,0xE1,0x78,0x10,0x18,0x40,0x5C,0x01,0x02,0x19,0x98,0xC0,0x6A, + 0x20,0x30,0xC0,0x7F,0x01,0x43,0xAD,0x48,0x01,0x81,0x6B,0x46,0x99,0x8D,0x81,0x82, + 0xAB,0x49,0xDA,0x8D,0x8A,0x74,0x1A,0x8E,0xC2,0x80,0x5A,0x8E,0x82,0x81,0xDA,0x8E, + 0x4A,0x74,0x1A,0x8F,0x0A,0x74,0xA7,0x49,0x41,0x80,0xA0,0x6A,0x80,0x47,0x20,0x6A, + 0x40,0x1C,0x20,0x62,0x3B,0xE6,0xF1,0xB5,0x9A,0xB0,0xA3,0x48,0x19,0x90,0xC0,0x6A, + 0xA2,0x4C,0x05,0x79,0xC1,0x78,0xA2,0x78,0x06,0x92,0x1A,0x9A,0x14,0x2A,0x01,0xD2, + 0x14,0x22,0x1A,0x92,0x00,0x7D,0x00,0x26,0x02,0x06,0x9B,0x48,0x80,0x38,0x18,0x90, + 0x00,0x2A,0x09,0xDB,0x4D,0x43,0x69,0x00,0x80,0x69,0x00,0xF0,0xCB,0xFA,0x92,0x48, + 0x86,0x83,0xE6,0x70,0x26,0x71,0x1A,0xE6,0x95,0x48,0x81,0x68,0x01,0x20,0x88,0x47, + 0x93,0x4F,0x00,0x21,0x40,0x3F,0xFA,0x6B,0x01,0x20,0x90,0x47,0x01,0x21,0xBA,0x6B, + 0x00,0x20,0x90,0x47,0x89,0x48,0x81,0x8A,0x6B,0x46,0x99,0x85,0x88,0x49,0x8A,0x7C, + 0xDA,0x85,0xC2,0x88,0x1A,0x86,0x82,0x89,0x5A,0x86,0x4A,0x7C,0xDA,0x86,0x0A,0x7C, + 0x1A,0x87,0x3B,0x22,0x4A,0x74,0x13,0x22,0x0A,0x74,0x86,0x4A,0x42,0x80,0x08,0x22, + 0xC2,0x80,0x00,0x22,0x82,0x81,0x93,0x20,0x88,0x74,0x07,0x92,0x08,0x92,0xA8,0x00, + 0x69,0x00,0x02,0x92,0x16,0x91,0x42,0x18,0x18,0x99,0x17,0x90,0x15,0x92,0x89,0x69, + 0x0F,0x91,0x08,0x18,0x10,0x90,0x52,0x18,0x00,0x20,0x11,0x92,0x09,0x90,0x20,0x78, + 0x70,0x4E,0x00,0x28,0x07,0xD0,0x61,0x78,0x00,0x29,0x04,0xD0,0x20,0x6A,0x00,0xF0, + 0x85,0xFA,0xC8,0xB2,0x09,0x90,0x06,0x99,0x09,0x98,0xE2,0x68,0x48,0x43,0x14,0x90, + 0x10,0x18,0x00,0x21,0x0A,0x90,0x03,0xA8,0x0A,0x46,0x0B,0x46,0x0E,0xC0,0x0D,0x46, + 0x73,0xE0,0x0A,0x98,0x6A,0x49,0x40,0x5D,0xA2,0x6A,0x40,0x31,0x00,0x92,0x0F,0x68, + 0x0F,0xA9,0x0E,0xC9,0xB8,0x47,0x69,0x00,0x03,0xAA,0x50,0x52,0x14,0x98,0xA3,0x69, + 0x40,0x00,0x40,0x18,0x1F,0x5E,0x52,0x5A,0x1A,0x52,0x03,0xAA,0x52,0x5E,0xD3,0x1B, + 0x00,0xD5,0x5B,0x42,0xD2,0x18,0x12,0xB2,0x03,0xAB,0x5A,0x52,0x63,0x69,0x1B,0x5A, + 0xD7,0x1A,0x19,0x2F,0x06,0xDD,0x57,0x00,0xD2,0x19,0x9A,0x18,0x92,0x10,0x03,0xAB, + 0x5A,0x52,0x05,0xE0,0x5F,0x00,0xDB,0x19,0x9A,0x18,0x03,0xAF,0x92,0x10,0x7A,0x52, + 0x03,0xAA,0x67,0x69,0x53,0x5A,0x3B,0x52,0x50,0x5E,0xB0,0x42,0x01,0xDA,0x06,0x46, + 0x08,0x95,0x02,0x99,0x88,0x42,0x01,0xDD,0x07,0x95,0x02,0x90,0x11,0x9A,0x17,0x99, + 0x89,0x18,0x11,0x91,0x10,0x9A,0x17,0x99,0x89,0x18,0x10,0x91,0xE1,0x78,0xA9,0x42, + 0x1B,0xD1,0x21,0x79,0x09,0x9A,0x91,0x42,0x17,0xD1,0x1A,0x99,0x88,0x42,0x14,0xDA, + 0x02,0x96,0x20,0x6A,0x6B,0x46,0x40,0x1E,0x20,0x62,0x08,0x95,0xE5,0x70,0x09,0x98, + 0x20,0x71,0x0C,0x21,0x59,0x5E,0x1A,0x98,0x81,0x42,0x05,0xDA,0x36,0x48,0x80,0x8B, + 0x00,0x28,0x01,0xD1,0x08,0x90,0xE0,0x70,0xA0,0xE0,0x19,0x98,0x40,0x6B,0x80,0x7A, + 0xCA,0x28,0x01,0xD1,0x08,0x95,0x99,0xE0,0x20,0x78,0x00,0x28,0x03,0xD1,0x08,0x95, + 0xE5,0x70,0x20,0x71,0x92,0xE0,0x6D,0x1C,0xED,0xB2,0x06,0x98,0x85,0x42,0x88,0xD3, + 0x04,0x28,0x1A,0xD1,0x07,0x98,0x03,0x28,0x0A,0xD1,0x6B,0x46,0x0E,0x20,0x0C,0x21, + 0x18,0x5E,0x59,0x5E,0x88,0x42,0x01,0xDA,0x01,0x20,0x0D,0xE0,0x00,0x20,0x0B,0xE0, + 0x00,0x28,0x0A,0xD1,0x6B,0x46,0x10,0x20,0x12,0x21,0x18,0x5E,0x59,0x5E,0x88,0x42, + 0x01,0xDA,0x02,0x20,0x00,0xE0,0x03,0x20,0x08,0x90,0xA2,0x68,0x09,0x98,0x08,0x99, + 0x11,0x54,0x20,0x79,0x13,0x90,0x01,0x90,0xE2,0x78,0x12,0x92,0x63,0x78,0x15,0x4E, + 0x00,0x20,0x9C,0x46,0x09,0x99,0x10,0xE0,0xA3,0x68,0x1B,0x5C,0xFF,0x2B,0x0A,0xD0, + 0x06,0x9D,0x5B,0x00,0x45,0x43,0x6D,0x00,0xEB,0x18,0x65,0x69,0xEF,0x5A,0xB7,0x42, + 0x01,0xDA,0xEE,0x5E,0x01,0x46,0x40,0x1C,0xC0,0xB2,0x84,0x45,0xEC,0xD8,0x09,0x48, + 0x86,0x42,0x02,0xD0,0x01,0x91,0xA0,0x68,0x42,0x5C,0x60,0x6A,0x00,0x28,0x1B,0xD1, + 0x61,0x71,0xA0,0x68,0x42,0x5C,0xA2,0x71,0x21,0x71,0x40,0x5C,0xE0,0x70,0x01,0x20, + 0x60,0x62,0x3B,0xE0,0xFF,0x7F,0x00,0x00,0x80,0x01,0x00,0x20,0x00,0x10,0x00,0x40, + 0x60,0x12,0x00,0x40,0x82,0x10,0x00,0x00,0x44,0x01,0x00,0x20,0x04,0x16,0x00,0x20, + 0x80,0x81,0x00,0x00,0x82,0x11,0x00,0x00,0x12,0x99,0x91,0x42,0x03,0xD1,0x01,0x9B, + 0x13,0x99,0x99,0x42,0x19,0xD0,0x06,0x9B,0x13,0x99,0x06,0x9F,0x59,0x43,0x4B,0x00, + 0x12,0x99,0x01,0x9D,0x49,0x00,0x5B,0x18,0x7D,0x43,0x61,0x69,0x6D,0x00,0x57,0x00, + 0xCB,0x5A,0xED,0x19,0x49,0x5B,0x1E,0x31,0x8B,0x42,0x08,0xD9,0x40,0x1C,0x60,0x62, + 0x06,0x28,0x08,0xD3,0xE2,0x70,0x01,0x98,0x20,0x71,0x01,0x20,0x02,0xE0,0x01,0x28, + 0x01,0xD9,0x40,0x1E,0x60,0x62,0xA2,0x71,0x01,0x98,0x60,0x71,0x1A,0x99,0x02,0x98, + 0x88,0x42,0x0B,0xDD,0x7A,0x48,0x1E,0x21,0x81,0x83,0x02,0x98,0x82,0x19,0x1A,0x98, + 0x43,0x00,0xC0,0x18,0x82,0x42,0x11,0xDD,0xE1,0x83,0x0F,0xE0,0xE0,0x8B,0x00,0x28, + 0x01,0xD0,0x40,0x1E,0xE0,0x83,0x72,0x49,0x88,0x8B,0x00,0x28,0x06,0xD0,0x40,0x1E, + 0x00,0x04,0x00,0x0C,0x88,0x83,0x01,0xD1,0xE0,0x6A,0x80,0x47,0x18,0x98,0x15,0x9A, + 0x81,0x69,0x50,0x18,0x17,0x9A,0x8D,0x18,0x08,0x9A,0x16,0x99,0x51,0x43,0x49,0x00, + 0x0F,0x46,0x09,0x18,0x16,0x9A,0x00,0xF0,0xD7,0xF8,0x79,0x19,0x28,0x46,0x16,0x9A, + 0x00,0xF0,0xD2,0xF8,0x26,0x82,0x02,0x98,0x60,0x82,0x20,0x79,0x06,0x9A,0xE1,0x68, + 0x50,0x43,0x08,0x18,0xE1,0x78,0x40,0x5C,0x01,0x02,0x19,0x98,0xC0,0x6A,0x20,0x30, + 0xC0,0x7F,0x01,0x43,0x5B,0x48,0x01,0x81,0x6B,0x46,0x99,0x8D,0x81,0x82,0x5A,0x49, + 0xDA,0x8D,0x8A,0x74,0x1A,0x8E,0xC2,0x80,0x5A,0x8E,0x82,0x81,0xDA,0x8E,0x4A,0x74, + 0x1A,0x8F,0x0A,0x74,0x55,0x49,0x41,0x80,0xA0,0x6A,0x80,0x47,0x20,0x6A,0x40,0x1C, + 0x20,0x62,0x64,0xE4,0x00,0x20,0x70,0x47,0x70,0x47,0xF7,0xB5,0x50,0x48,0x88,0xB0, + 0x01,0x68,0x01,0x91,0xC7,0x68,0x40,0x30,0xC0,0x6A,0x08,0x99,0x80,0x79,0x07,0x90, + 0x00,0x20,0x08,0x80,0x03,0x46,0x04,0x46,0x05,0x46,0x06,0x46,0x06,0x90,0x05,0x90, + 0x48,0x48,0x00,0x22,0x04,0x90,0x20,0xE0,0x01,0x99,0x50,0x00,0x09,0x5A,0x38,0x5A, + 0x08,0x1A,0x00,0xB2,0x14,0x28,0x01,0xDB,0x36,0x18,0x04,0xE0,0x09,0x21,0xC9,0x43, + 0x88,0x42,0x00,0xDA,0x2D,0x18,0x19,0x18,0x0B,0xB2,0x06,0x99,0x81,0x42,0x00,0xDA, + 0x06,0x90,0x01,0x1B,0x04,0x46,0x05,0x98,0x09,0xB2,0x88,0x42,0x00,0xDA,0x05,0x91, + 0x04,0x98,0x88,0x42,0x00,0xDD,0x04,0x91,0x52,0x1C,0x07,0x98,0x82,0x42,0xDB,0xD3, + 0x01,0x46,0x18,0x46,0x00,0xF0,0xDC,0xF8,0x00,0x24,0x00,0xB2,0x86,0x46,0x21,0x46, + 0xA4,0x46,0x20,0x46,0x02,0x94,0x17,0xE0,0x01,0x9A,0x43,0x00,0xD2,0x5A,0xFB,0x5A, + 0xD2,0x1A,0x12,0xB2,0x72,0x45,0x06,0xDB,0x0A,0x9B,0x9A,0x42,0x03,0xDD,0x49,0x1C, + 0x94,0x44,0x09,0xB2,0x07,0xE0,0x00,0x2A,0x00,0xDA,0x52,0x42,0x02,0x9B,0xD2,0x18, + 0x64,0x1C,0x24,0xB2,0x02,0x92,0x40,0x1C,0x07,0x9A,0x90,0x42,0xE4,0xD3,0x00,0x20, + 0x08,0x9A,0x07,0x46,0x10,0x80,0x00,0x29,0x14,0xDD,0x00,0x2C,0x12,0xDD,0x60,0x46, + 0x00,0xF0,0xAE,0xF8,0x03,0x90,0x21,0x46,0x02,0x98,0x00,0xF0,0xA9,0xF8,0x41,0x1C, + 0x03,0x98,0x00,0xF0,0xA5,0xF8,0x08,0x99,0x80,0xB2,0x08,0x80,0x09,0x99,0x88,0x42, + 0x03,0xD2,0x01,0xE0,0x02,0x2C,0x00,0xDB,0x01,0x27,0x64,0x2E,0x03,0xD8,0x63,0x20, + 0xC0,0x43,0x85,0x42,0x11,0xDA,0x05,0x98,0x32,0x28,0x0D,0xDD,0x31,0x21,0x04,0x98, + 0xC9,0x43,0x88,0x42,0x08,0xDA,0x96,0x2E,0x06,0xD9,0x06,0x98,0x3C,0x28,0x03,0xDD, + 0x77,0x20,0xC0,0x43,0x85,0x42,0x00,0xDC,0x01,0x27,0x38,0x46,0x0B,0xB0,0xF0,0xBD, + 0x80,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0x60,0x12,0x00,0x40,0x82,0x10,0x00,0x00, + 0x04,0x01,0x00,0x20,0xFF,0x7F,0x00,0x00,0xF8,0xB5,0x04,0x2A,0x2C,0xD3,0x83,0x07, + 0x12,0xD0,0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x83,0x07,0x0B,0xD0, + 0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x83,0x07,0x04,0xD0,0x0B,0x78, + 0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x8B,0x07,0x9B,0x0F,0x05,0xD0,0xC9,0x1A, + 0xDF,0x00,0x20,0x23,0xDE,0x1B,0x08,0xC9,0x0A,0xE0,0xFD,0xF7,0x8D,0xFA,0xF8,0xBD, + 0x1D,0x46,0x08,0xC9,0xFD,0x40,0x1C,0x46,0xB4,0x40,0x2C,0x43,0x10,0xC0,0x12,0x1F, + 0x04,0x2A,0xF5,0xD2,0xF3,0x08,0xC9,0x1A,0x52,0x1E,0xF0,0xD4,0x0B,0x78,0x49,0x1C, + 0x03,0x70,0x40,0x1C,0x52,0x1E,0xEA,0xD4,0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C, + 0x52,0x1E,0xE4,0xD4,0x09,0x78,0x01,0x70,0xF8,0xBD,0xD2,0xB2,0x10,0xB5,0x13,0x02, + 0x9A,0x18,0x13,0x04,0x9A,0x18,0x00,0xF0,0x0E,0xF8,0x10,0xBD,0x01,0xE0,0x04,0xC0, + 0x09,0x1F,0x04,0x29,0xFB,0xD2,0x8B,0x07,0x01,0xD5,0x02,0x80,0x80,0x1C,0xC9,0x07, + 0x00,0xD0,0x02,0x70,0x70,0x47,0x00,0x29,0x0B,0xD0,0xC3,0x07,0x02,0xD0,0x02,0x70, + 0x40,0x1C,0x49,0x1E,0x02,0x29,0x04,0xD3,0x83,0x07,0x02,0xD5,0x02,0x80,0x80,0x1C, + 0x89,0x1E,0xE3,0xE7,0x00,0x22,0xEE,0xE7,0x00,0x22,0xDF,0xE7,0x00,0x22,0x03,0x09, + 0x8B,0x42,0x2C,0xD3,0x03,0x0A,0x8B,0x42,0x11,0xD3,0x00,0x23,0x9C,0x46,0x4E,0xE0, + 0x03,0x46,0x0B,0x43,0x3C,0xD4,0x00,0x22,0x43,0x08,0x8B,0x42,0x31,0xD3,0x03,0x09, + 0x8B,0x42,0x1C,0xD3,0x03,0x0A,0x8B,0x42,0x01,0xD3,0x94,0x46,0x3F,0xE0,0xC3,0x09, + 0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41,0x83,0x09,0x8B,0x42,0x01,0xD3, + 0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42,0x01,0xD3,0x4B,0x01,0xC0,0x1A, + 0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01,0xC0,0x1A,0x52,0x41,0xC3,0x08, + 0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41,0x83,0x08,0x8B,0x42,0x01,0xD3, + 0x8B,0x00,0xC0,0x1A,0x52,0x41,0x43,0x08,0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A, + 0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46,0x52,0x41,0x10,0x46,0x70,0x47,0x5D,0xE0, + 0xCA,0x0F,0x00,0xD0,0x49,0x42,0x03,0x10,0x00,0xD3,0x40,0x42,0x53,0x40,0x00,0x22, + 0x9C,0x46,0x03,0x09,0x8B,0x42,0x2D,0xD3,0x03,0x0A,0x8B,0x42,0x12,0xD3,0xFC,0x22, + 0x89,0x01,0x12,0xBA,0x03,0x0A,0x8B,0x42,0x0C,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42, + 0x08,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42,0x04,0xD3,0x89,0x01,0x3A,0xD0,0x92,0x11, + 0x00,0xE0,0x89,0x09,0xC3,0x09,0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41, + 0x83,0x09,0x8B,0x42,0x01,0xD3,0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42, + 0x01,0xD3,0x4B,0x01,0xC0,0x1A,0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01, + 0xC0,0x1A,0x52,0x41,0xC3,0x08,0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41, + 0x83,0x08,0x8B,0x42,0x01,0xD3,0x8B,0x00,0xC0,0x1A,0x52,0x41,0xD9,0xD2,0x43,0x08, + 0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A,0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46, + 0x63,0x46,0x52,0x41,0x5B,0x10,0x10,0x46,0x01,0xD3,0x40,0x42,0x00,0x2B,0x00,0xD5, + 0x49,0x42,0x70,0x47,0x63,0x46,0x5B,0x10,0x00,0xD3,0x40,0x42,0x01,0xB5,0x00,0x20, + 0xC0,0x46,0xC0,0x46,0x02,0xBD,0x75,0x46,0x00,0xF0,0x22,0xF8,0xAE,0x46,0x05,0x00, + 0x69,0x46,0x53,0x46,0xC0,0x08,0xC0,0x00,0x85,0x46,0x18,0xB0,0x20,0xB5,0xFD,0xF7, + 0xB1,0xF9,0x60,0xBC,0x00,0x27,0x49,0x08,0xB6,0x46,0x00,0x26,0xC0,0xC5,0xC0,0xC5, + 0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0xC0,0xC5,0x40,0x3D,0x49,0x00, + 0x8D,0x46,0x70,0x47,0x04,0x46,0xC0,0x46,0xC0,0x46,0x20,0x46,0xFD,0xF7,0x6D,0xF9, + 0x00,0x48,0x70,0x47,0xC8,0x18,0x00,0x20,0x01,0x49,0x18,0x20,0xAB,0xBE,0xFE,0xE7, + 0x26,0x00,0x02,0x00,0x70,0x47,0x00,0x00,0x3C,0x14,0x32,0x16,0x0C,0x0C,0x16,0x00, + 0x00,0x02,0x20,0x70,0x05,0x00,0x00,0x00,0x00,0x08,0x14,0x1E,0x80,0x96,0x4B,0x25, + 0x03,0x0A,0x3C,0x64,0x2B,0x20,0x57,0x08,0x02,0x16,0x01,0x00,0x00,0x04,0x03,0x00, + 0x00,0x06,0x04,0x00,0x00,0x28,0x04,0x28,0x1E,0x32,0x0A,0xD8,0xE2,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x04,0x05,0x02,0x08,0x00,0x20,0x03,0x04,0x00,0x14,0x08,0x01, + 0x04,0x02,0x3C,0x3C,0x50,0x00,0x00,0xC8,0x28,0x00,0x83,0x04,0x08,0x20,0x5A,0x00, + 0x5A,0x00,0x00,0x00,0x01,0x01,0x00,0x02,0x78,0x78,0x12,0x01,0x00,0x00,0x38,0x04, + 0x80,0x07,0x20,0x01,0x07,0x00,0xA0,0x01,0x30,0x00,0x00,0x01,0x20,0x00,0x00,0x00, + 0xEC,0xFF,0x28,0x00,0x20,0x00,0x00,0x00,0x00,0x5A,0x00,0x00,0x45,0x57,0x00,0x00, + 0xFF,0xFF,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x01,0x02,0x00,0x0F,0x0E,0x0C,0x07,0x06,0x0D, + 0x0F,0x05,0x04,0x00,0x01,0x03,0x02,0x0C,0x0B,0x0A,0x09,0x08,0x07,0x06,0x05,0x04, + 0x03,0x02,0x34,0x47,0x46,0x35,0x37,0x45,0x44,0x40,0x41,0x43,0x42,0x14,0x13,0x12, + 0x11,0x10,0x07,0x06,0x05,0x04,0x03,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x59,0x03,0x00,0x40,0x61,0x03,0x00,0x40,0x61,0x03,0x00,0x40, + 0x59,0x03,0x00,0x40,0x59,0x03,0x00,0x40,0x61,0x03,0x00,0x40,0x61,0x03,0x00,0x40, + 0x61,0x03,0x00,0x40,0x61,0x03,0x00,0x40,0x61,0x03,0x00,0x40,0x61,0x03,0x00,0x40, + 0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40, + 0x49,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x41,0x03,0x00,0x40, + 0x41,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x59,0x03,0x00,0x40, + 0x59,0x03,0x00,0x40,0x51,0x03,0x00,0x40,0x51,0x03,0x00,0x40,0x51,0x03,0x00,0x40, + 0x51,0x03,0x00,0x40,0x51,0x03,0x00,0x40,0x51,0x03,0x00,0x40,0x51,0x03,0x00,0x40, + 0x51,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x10,0x80,0x40,0x20, + 0x80,0x20,0x10,0x01,0x02,0x08,0x04,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10, + 0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x02,0x04,0x01,0x80,0x40,0x03,0x04, + 0x04,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01, + 0x25,0x12,0x00,0x40,0x21,0x12,0x00,0x40,0x1D,0x12,0x00,0x40,0x19,0x12,0x00,0x40, + 0x15,0x12,0x00,0x40,0x11,0x12,0x00,0x40,0x0D,0x12,0x00,0x40,0x05,0x12,0x00,0x40, + 0x09,0x12,0x00,0x40,0x01,0x12,0x00,0x40,0x3D,0x12,0x00,0x40,0x39,0x12,0x00,0x40, + 0x31,0x12,0x00,0x40,0x1D,0x12,0x00,0x40,0x19,0x12,0x00,0x40,0x35,0x12,0x00,0x40, + 0x3D,0x12,0x00,0x40,0x15,0x12,0x00,0x40,0x11,0x12,0x00,0x40,0x01,0x12,0x00,0x40, + 0x05,0x12,0x00,0x40,0x0D,0x12,0x00,0x40,0x09,0x12,0x00,0x40,0x31,0x12,0x00,0x40, + 0x2D,0x12,0x00,0x40,0x29,0x12,0x00,0x40,0x25,0x12,0x00,0x40,0x21,0x12,0x00,0x40, + 0x1D,0x12,0x00,0x40,0x19,0x12,0x00,0x40,0x15,0x12,0x00,0x40,0x11,0x12,0x00,0x40, + 0x0D,0x12,0x00,0x40,0x09,0x12,0x00,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + 0x06,0x0C,0x12,0x19,0xE4,0x30,0x00,0x00,0xA0,0x01,0x00,0x20,0x28,0x00,0x00,0x00, + 0xB4,0x00,0x00,0x00,0x0C,0x31,0x00,0x00,0xC8,0x01,0x00,0x20,0x60,0x17,0x00,0x00, + 0xD0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5B,0x5A,0x35,0x35,0xA5,0xA5,0xCA,0xCA,0x88,0x77,0x66,0x55, + 0x44,0x33,0x22,0x11,0x16,0x00,0x0C,0x00,0x38,0x04,0x80,0x07,0x20,0x4E,0xCA,0xCA, + 0xAA,0x55,0xAA,0x55,0x70,0x64,0x40,0x32,0x03,0x00,0x00,0x01,0xA6,0xC3,0xF6,0x11, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst36xxes_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst36xxes_fw.h new file mode 100644 index 000000000000..0009f6de1eea --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst36xxes_fw.h @@ -0,0 +1,663 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst36xxes_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { + 0x80,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x2C,0x00,0x01,0x00,0x54,0x00,0x01,0x00, + 0x80,0x00,0x01,0x00,0xAC,0x00,0x01,0x00,0xD8,0x00,0x01,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00,0x60,0x02,0x00,0x00, + 0x05,0x23,0xCA,0xCA,0x0A,0xA5,0xCA,0xCA,0x10,0x27,0xCA,0xCA,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD0,0x0A,0x00,0xD0,0x02,0x00,0x05, + 0x00,0x00,0x00,0x00,0x62,0x47,0x00,0x00,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x22,0x14,0x00,0x00,0x44,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x0C,0x0D,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C, + 0x1D,0x1E,0x1F,0x20,0x21,0x22,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x00,0x00,0x0A,0x00,0x00,0x00, + 0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x3A,0x43,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14, + 0x05,0x0A,0x20,0x28,0x3C,0x14,0x19,0x1E,0x2D,0x33,0x37,0x37,0x0A,0x08,0x0F,0x5A, + 0x28,0x32,0x64,0x01,0x01,0x08,0x14,0x05,0x1E,0x0A,0x5F,0x14,0x32,0x96,0x03,0x5A, + 0x03,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x80,0x0A,0x28,0x02,0x00, + 0x20,0x03,0x00,0x00,0x00,0x5B,0x02,0x03,0x02,0x37,0x00,0x00,0x00,0x04,0x01,0x00, + 0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x01,0x11,0x00,0x00, + 0x64,0x00,0x02,0x01,0x01,0x30,0x00,0x00,0x14,0x28,0xD8,0x28,0x03,0x03,0x28,0x14, + 0x50,0xB0,0x28,0x03,0x03,0x32,0x14,0x28,0xD8,0x28,0x03,0x03,0x32,0x00,0x00,0x00, + 0xE8,0x03,0x02,0x00,0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x00,0x42,0x25,0x0D,0x70, + 0x73,0x67,0x1E,0x00,0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x30,0x00,0x46,0x73,0x67, + 0x04,0x0F,0x70,0x14,0xC8,0x00,0x00,0x01,0x20,0x01,0x03,0x50,0x28,0x14,0xC8,0x00, + 0x20,0x01,0x01,0x08,0x04,0x03,0x0F,0x16,0x23,0x33,0x11,0x19,0x2A,0x44,0x13,0x1F, + 0x2F,0x55,0x0F,0x13,0x21,0x0F,0x17,0x28,0x0F,0x1C,0x30,0x11,0x1A,0x23,0x28,0x34, + 0x4D,0x64,0x01,0x14,0x70,0x10,0x00,0x32,0x41,0xA3,0x46,0xA3,0x4F,0x10,0x80,0x33, + 0x77,0x43,0x89,0x74,0x43,0xAB,0x00,0x33,0x2D,0x10,0x4E,0x10,0x8C,0x60,0x0E,0x10, + 0x84,0x64,0x0C,0x60,0x07,0x08,0x6D,0x10,0x4D,0x10,0x00,0x31,0xC8,0x64,0x06,0x08, + 0x3C,0x78,0x00,0x90,0x00,0xB2,0x03,0x23,0xF1,0x07,0x20,0xB3,0x03,0x23,0xF7,0x07, + 0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x40,0x09,0x00,0x00,0x00,0x00,0x28,0x00,0x00, + 0x00,0x28,0x00,0x00,0x30,0x19,0x00,0x00,0x00,0x28,0x00,0x00,0x2C,0x56,0x00,0x00, + 0x05,0x10,0x00,0xC0,0x20,0x64,0x25,0x10,0x87,0x6F,0xFF,0xE3,0xCD,0xFF,0x00,0xE0, + 0x8B,0x01,0x00,0x04,0x00,0x01,0x00,0x80,0x7C,0x5F,0x00,0x00,0x00,0x30,0x3C,0x78, + 0x3C,0x78,0xA5,0x30,0x3C,0x78,0x3C,0x78,0xD4,0x14,0xB0,0x02,0x70,0x85,0x40,0x3B, + 0x13,0x08,0x20,0x37,0xD4,0x61,0x6F,0x87,0x40,0x3B,0x9F,0x6D,0x0D,0x08,0x94,0x02, + 0x60,0x94,0x0B,0x93,0xC1,0x7B,0x65,0x87,0x40,0x3B,0x07,0x0C,0x40,0x38,0x07,0x08, + 0x76,0x85,0x00,0x23,0x76,0xA5,0x94,0x14,0x40,0x38,0xFE,0x0F,0x60,0x94,0x6A,0x93, + 0xCD,0x7B,0x60,0x94,0x07,0x93,0xC1,0x7B,0x40,0x38,0xF6,0x0F,0x00,0x33,0x00,0x2B, + 0x6A,0xA6,0xF2,0x07,0xC2,0x14,0x41,0x03,0x6A,0x82,0x30,0x31,0xC4,0x64,0x17,0x0C, + 0x59,0x3B,0x17,0x08,0x87,0x03,0x20,0x33,0xD0,0x60,0x32,0x83,0x01,0x49,0x43,0x6D, + 0xA5,0x3D,0xB3,0xA3,0xBF,0x84,0xF0,0x34,0x16,0x65,0x05,0x08,0x00,0x34,0x5F,0x2C, + 0x10,0x6C,0x13,0xA3,0x00,0x21,0x32,0xA3,0x6D,0x03,0x63,0xB2,0x00,0x30,0x82,0x14, + 0x01,0x30,0xFE,0x07,0xD4,0x14,0x39,0x14,0x70,0x03,0x80,0x37,0x63,0xB8,0x60,0x93, + 0x05,0x1C,0xDC,0x60,0x43,0x6D,0x67,0x93,0x10,0x32,0x33,0x03,0x13,0x6C,0xCD,0x7B, + 0x10,0x33,0xD0,0x60,0x8F,0x6D,0x77,0x03,0x10,0x32,0x60,0x93,0xDC,0x60,0x67,0x93, + 0x38,0x03,0x1B,0x6C,0xCD,0x7B,0x2B,0x33,0xD6,0x64,0x30,0x08,0xBA,0x03,0x7F,0x33, + 0x23,0x85,0x4C,0x68,0x0C,0x84,0x2D,0xA4,0x00,0xE0,0xE0,0x07,0x63,0x85,0xCE,0x74, + 0xDF,0x3B,0x7A,0x13,0x5F,0x03,0x60,0x93,0x64,0x93,0x17,0x08,0x13,0x6C,0x00,0x31, + 0xCD,0x7B,0x5E,0x13,0x21,0x82,0x60,0x82,0xC4,0x7C,0x02,0x84,0x26,0x84,0x9C,0x13, + 0xCD,0x74,0x90,0x60,0x00,0xE0,0x95,0x07,0x76,0x13,0x01,0x32,0x42,0xA3,0x00,0x32, + 0x03,0x2A,0x41,0xA3,0x19,0x14,0x94,0x14,0x01,0x31,0x13,0x6C,0xCD,0x7B,0x97,0x6C, + 0x64,0x85,0x26,0x84,0x02,0x84,0x17,0x22,0xEE,0x07,0x2C,0x33,0xD6,0x64,0x22,0x08, + 0x8C,0x13,0x63,0x84,0x40,0x3B,0x12,0x08,0xF2,0x32,0x8C,0x13,0x44,0x42,0x20,0x84, + 0x90,0x60,0x03,0x94,0x00,0xE0,0xB4,0x06,0x40,0x84,0x41,0x42,0x66,0x13,0x8C,0x60, + 0x21,0x84,0x04,0x94,0x00,0xE0,0xAC,0x06,0xD8,0x07,0x24,0x84,0x42,0x13,0x04,0x94, + 0x00,0xE0,0xA6,0x06,0x44,0x84,0x41,0x42,0x7F,0x12,0x8C,0x60,0x25,0x84,0x05,0x94, + 0xF2,0x07,0x2D,0x33,0xD6,0x64,0x9D,0x08,0x7A,0x12,0x43,0x83,0x40,0x3A,0x5D,0x12, + 0x43,0xB8,0x59,0x08,0x60,0x92,0x01,0x32,0xB8,0x12,0xDC,0x60,0x42,0xB8,0x40,0x85, + 0x41,0xB8,0x59,0x12,0x94,0x60,0x40,0xB8,0x6D,0x93,0x64,0xB8,0x77,0x12,0x43,0xB8, + 0xD4,0x60,0x41,0x95,0x23,0x95,0x1B,0x6C,0xC4,0x98,0xD9,0x7B,0x74,0x12,0x26,0x83, + 0x70,0x12,0x00,0x32,0x60,0x93,0xDC,0x60,0x6E,0x93,0x16,0x84,0xCD,0x7B,0x03,0x6D, + 0x00,0xE0,0x66,0x06,0x00,0x30,0x00,0xE0,0x18,0x07,0x6A,0x12,0x60,0x93,0xDC,0x60, + 0x6F,0x93,0xCD,0x7B,0x67,0x12,0x60,0x93,0xDC,0x60,0x71,0x93,0xCD,0x7B,0x7E,0x11, + 0xF2,0x30,0x60,0x93,0x40,0x85,0xDC,0x60,0x24,0x12,0x04,0x40,0x54,0x60,0x41,0x42, + 0x67,0x93,0x14,0x60,0xCD,0x7B,0x75,0x11,0xF2,0x30,0x60,0x93,0x04,0x40,0x40,0x85, + 0xC3,0x93,0x53,0x6C,0x63,0x98,0x14,0x60,0xD9,0x7B,0x01,0x31,0x00,0x30,0x00,0xE0, + 0x91,0x07,0x01,0x31,0x01,0x30,0x00,0xE0,0x8D,0x07,0x00,0x85,0x72,0x11,0x01,0x40, + 0x0C,0x60,0x6A,0x11,0x41,0x85,0x60,0x93,0xC3,0x93,0x76,0x11,0xD4,0x60,0x53,0x6C, + 0xD9,0x7B,0x6B,0x07,0xAE,0x5B,0x17,0x23,0x63,0xB8,0x01,0x32,0x6D,0x11,0x1B,0x6C, + 0x60,0x93,0x42,0xB8,0x40,0x85,0x41,0xB8,0x43,0x98,0x40,0xB8,0xDC,0x60,0x6D,0x93, + 0x64,0xB8,0x23,0x95,0xCB,0x6C,0xC4,0x98,0x41,0x95,0xD9,0x7B,0x65,0x11,0x32,0x84, + 0x60,0x93,0xDC,0x60,0x00,0x32,0x6E,0x93,0x16,0x84,0xCD,0x7B,0x03,0x6D,0x00,0xE0, + 0x0F,0x06,0x00,0x30,0x00,0xE0,0xC1,0x06,0x7E,0x10,0x60,0x93,0xDC,0x60,0x6F,0x93, + 0xCD,0x7B,0x7C,0x10,0x60,0x93,0xDC,0x60,0x71,0x93,0xCD,0x7B,0x72,0x10,0x40,0x85, + 0x60,0x93,0xDC,0x60,0x23,0x98,0x41,0x42,0x67,0x93,0x13,0x10,0xCD,0x7B,0x6B,0x10, + 0x40,0x85,0x60,0x93,0xA3,0x93,0x53,0x6C,0x63,0x98,0x0F,0x10,0xD5,0x7B,0x2D,0x07, + 0x2E,0x33,0xD6,0x64,0x30,0x0B,0x67,0x31,0x73,0x30,0x00,0xE0,0xEF,0x06,0x6A,0x10, + 0x00,0xAB,0x23,0x07,0xD4,0x51,0x00,0x00,0xD0,0x51,0x00,0x00,0x00,0x28,0x00,0x00, + 0x07,0x52,0x00,0x00,0xE4,0x54,0x00,0x00,0x50,0x17,0x00,0x00,0x60,0x17,0x00,0x00, + 0x10,0x28,0x00,0x00,0x14,0x4C,0x00,0x00,0xF4,0x3C,0x00,0x00,0xEE,0x0A,0x00,0x00, + 0x14,0x3C,0x00,0x00,0x0C,0x0F,0x00,0x00,0xBA,0x0E,0x00,0x00,0xF4,0x51,0x00,0x00, + 0x98,0x0E,0x00,0x00,0xD4,0x14,0x2E,0x16,0x6E,0x01,0x4D,0x01,0xCD,0x01,0x2C,0x01, + 0x0C,0x01,0x33,0x20,0x60,0xB2,0x4C,0x01,0x40,0xB6,0x4C,0x01,0x40,0xB1,0x60,0x93, + 0x00,0x31,0xCD,0x7B,0x71,0x01,0x37,0x23,0x63,0xB8,0x60,0x96,0x80,0x93,0x00,0x31, + 0x63,0x98,0x12,0x1F,0x52,0x01,0x11,0x01,0xD1,0x7B,0x71,0x01,0x81,0xEA,0x52,0x01, + 0x37,0xAB,0x52,0x01,0x81,0xEA,0x51,0x01,0x45,0xB3,0x38,0xAB,0x57,0x22,0x20,0x31, + 0x4C,0x60,0x4F,0xB3,0x30,0x30,0x60,0x02,0x97,0x01,0xB6,0x01,0x14,0x32,0x60,0x93, + 0x12,0xA1,0x7F,0x23,0x53,0x6C,0x67,0x93,0x17,0x6C,0xCD,0x7B,0x16,0x33,0xD0,0x60, + 0x66,0xB5,0x38,0x33,0xD0,0x60,0x67,0xB5,0x4C,0x33,0xD0,0x60,0x68,0xB5,0x65,0xB8, + 0x7F,0x01,0xD0,0x60,0x69,0xB5,0x7F,0x01,0xD0,0x60,0x6A,0xB5,0x60,0x02,0xD0,0x60, + 0x6B,0xB5,0x60,0x02,0xD0,0x60,0x6C,0xB5,0x66,0xB8,0x61,0x02,0xD0,0x60,0x6D,0xB5, + 0x62,0x02,0xD0,0x60,0x6E,0xB5,0x62,0x02,0xD0,0x60,0x6F,0xB5,0x63,0x02,0xD0,0x60, + 0x70,0xB5,0x67,0xB8,0x64,0x02,0xD0,0x60,0x71,0xB5,0x64,0x02,0xD0,0x60,0x72,0xB5, + 0x65,0x02,0xD0,0x60,0x73,0xB5,0xF2,0x33,0x64,0x43,0xD0,0x60,0x74,0xB5,0x67,0x02, + 0xD0,0x60,0x75,0xB5,0x68,0x02,0xD0,0x60,0x76,0xB5,0xA4,0xB7,0x29,0x02,0x7F,0x02, + 0x9B,0x23,0x61,0xB7,0x77,0x21,0x61,0x03,0xD3,0x23,0x62,0xB7,0x1F,0x6C,0x6C,0x02, + 0x44,0x03,0x63,0xB7,0x00,0x33,0x65,0xB7,0x6E,0x02,0x66,0xB7,0x67,0x03,0x0F,0x23, + 0x67,0xB7,0x6F,0x02,0x68,0xB7,0x6F,0x02,0x69,0xB7,0xA2,0x33,0x61,0x43,0xC8,0x60, + 0x6A,0xB7,0x76,0x02,0x6B,0xB7,0x72,0x02,0x6C,0xB7,0x78,0x02,0x17,0x23,0x4D,0xB7, + 0x43,0x98,0x64,0xB8,0x6E,0xB7,0x75,0x02,0x65,0xB2,0x75,0x02,0x66,0xB1,0x75,0x02, + 0x62,0xB1,0x75,0x03,0x60,0x93,0x61,0x93,0xCD,0x7B,0x20,0x32,0x7F,0x02,0x41,0xA3, + 0x60,0x96,0x69,0x93,0xCD,0x7B,0x00,0x33,0x7F,0x2B,0x5B,0x02,0x64,0xA2,0x10,0x32, + 0x64,0x03,0x00,0x31,0x40,0xA3,0x20,0x32,0x41,0xA3,0x60,0x96,0x68,0x93,0x04,0x30, + 0xCD,0x7B,0x00,0x32,0x69,0x03,0x00,0x2A,0x5F,0xA3,0x0A,0x32,0x02,0xA3,0x5E,0xA3, + 0x1F,0x23,0x0F,0x32,0x46,0xA3,0x01,0x32,0x47,0xA3,0x02,0x32,0x51,0xA3,0x01,0x32, + 0x44,0xA3,0x63,0xB8,0x60,0x96,0x11,0x31,0x01,0x30,0x01,0x32,0x6B,0x93,0xCD,0x7B, + 0x72,0x13,0x60,0x93,0x78,0x93,0xCD,0x7B,0x64,0x98,0x4E,0xD8,0x0A,0x10,0x48,0xAB, + 0x4E,0xD8,0x0C,0x10,0x4C,0xAB,0x4E,0xD8,0x0E,0x10,0x50,0xAB,0x6B,0x13,0x60,0x93, + 0x62,0x93,0xCD,0x7B,0x67,0x13,0x14,0x32,0x60,0x93,0x7F,0x23,0x57,0x6C,0x67,0x93, + 0x13,0x6C,0xCD,0x7B,0x74,0x85,0x74,0xA4,0x75,0x85,0x75,0xA4,0xC8,0x31,0x60,0x96, + 0x68,0x93,0x22,0x41,0x00,0x30,0xCD,0x7B,0x60,0x96,0x45,0x98,0x40,0xB8,0x7F,0x23, + 0x78,0x93,0xA0,0x32,0x8A,0x35,0x64,0xB8,0xA1,0x45,0x37,0x13,0x41,0x42,0x16,0x13, + 0x84,0x60,0x14,0x60,0x53,0x6C,0x71,0x13,0xA4,0x98,0xD5,0x7B,0x70,0x13,0x1E,0x83, + 0x60,0x96,0x6A,0x93,0x00,0x31,0xCD,0x7B,0x00,0x33,0x6E,0xB8,0x5F,0x6C,0x73,0x12, + 0x0E,0x18,0x60,0x93,0x5D,0x93,0x50,0xB8,0x5E,0x93,0x79,0x93,0x6F,0xB8,0x51,0xB8, + 0x6F,0x13,0x47,0x13,0x2B,0x22,0x60,0xB7,0x6E,0x13,0x62,0xB7,0x6E,0x13,0x63,0xB7, + 0x6E,0x13,0x61,0xB7,0x60,0x96,0x41,0xB8,0x00,0x32,0x40,0xB8,0xD0,0x32,0xBD,0x93, + 0x48,0x42,0x30,0x33,0xD5,0x7B,0x00,0x32,0x60,0x96,0x42,0xB8,0x5B,0x32,0x41,0xB8, + 0x37,0x32,0x40,0xB8,0xBB,0x93,0x03,0x32,0x02,0x33,0x02,0x31,0x00,0x30,0xD5,0x7B, + 0x60,0x96,0x02,0x30,0x22,0x13,0xBD,0x11,0x64,0x93,0xCD,0x7B,0x61,0x13,0x09,0x32, + 0x47,0xA3,0x41,0x83,0xA0,0x3A,0x41,0xA3,0x60,0x96,0x61,0x93,0xCD,0x7B,0x22,0x33, + 0x75,0xA4,0x14,0x33,0x74,0xA4,0x90,0x30,0x72,0x11,0x05,0x40,0x60,0x93,0x5C,0x93, + 0x40,0xB7,0x59,0x12,0x41,0xB7,0x5E,0x93,0x42,0xB7,0x58,0x12,0x43,0xB7,0x5F,0x93, + 0x44,0xB7,0x57,0x12,0x45,0xB7,0x80,0x32,0x8C,0x60,0x20,0x92,0x42,0x92,0x48,0xB7, + 0x26,0xB7,0x54,0x12,0x34,0x12,0x49,0xB7,0x4A,0x93,0x4A,0xB7,0x27,0xB7,0x5F,0x6C, + 0x52,0x12,0x4B,0xB7,0x4B,0x93,0x4C,0xB7,0x51,0x12,0x4D,0xB7,0x4C,0x93,0x4E,0xB7, + 0x50,0x12,0x4F,0xB7,0x53,0x93,0x50,0xB7,0x4F,0x12,0x51,0xB7,0x4E,0x93,0x52,0xB7, + 0x4E,0x12,0x53,0xB7,0x52,0x93,0x54,0xB7,0x4D,0x12,0x55,0xB7,0x5A,0x93,0x56,0xB7, + 0x4C,0x12,0x57,0xB7,0x5B,0x93,0x58,0xB7,0x4B,0x12,0x59,0xB7,0x55,0x93,0x76,0x93, + 0x7C,0xB7,0x5A,0xB7,0x69,0x12,0x4A,0x12,0x7D,0xB7,0x5B,0xB7,0x03,0x32,0x69,0x12, + 0x7E,0xB7,0x69,0x12,0x7F,0xB7,0x71,0x10,0x60,0x93,0x41,0xB8,0x00,0x32,0x40,0xB8, + 0x8D,0x93,0x10,0x32,0x00,0x33,0xD1,0x7B,0x6A,0x10,0x85,0x11,0xC4,0xB8,0x69,0xB8, + 0x64,0x11,0x65,0xB8,0x60,0x11,0x68,0xB8,0x64,0x11,0x67,0xB8,0x68,0x98,0x97,0x23, + 0x6A,0xB8,0x67,0x98,0xFF,0x23,0x6B,0xB8,0x60,0x84,0x77,0x04,0x04,0x01,0x01,0x00, + 0xE4,0x54,0x00,0x00,0x14,0x3C,0x00,0x00,0xD0,0x51,0x00,0x00,0x00,0x28,0x00,0x00, + 0xB8,0x01,0x01,0x00,0xC8,0x02,0x01,0x00,0x18,0x3C,0x00,0x00,0xE0,0x3B,0x00,0x00, + 0x98,0x3C,0x00,0x00,0x70,0x17,0x00,0x00,0xF4,0x3C,0x00,0x00,0x88,0x54,0x00,0x00, + 0x9C,0x05,0x00,0x00,0x9E,0x05,0x00,0x00,0xEE,0x0A,0x00,0x00,0x0E,0x0E,0x00,0x00, + 0x52,0x0E,0x00,0x00,0x54,0x0E,0x00,0x00,0x98,0x0E,0x00,0x00,0xBA,0x0E,0x00,0x00, + 0xE2,0x0E,0x00,0x00,0xE4,0x0E,0x00,0x00,0x0C,0x0F,0x00,0x00,0x70,0x14,0x00,0x00, + 0xB4,0x14,0x00,0x00,0x44,0x3B,0x00,0x00,0x08,0x52,0x00,0x00,0xD4,0x51,0x00,0x00, + 0x7C,0x54,0x00,0x00,0xC0,0x00,0x00,0x00,0xE8,0x54,0x00,0x00,0xD4,0x0F,0x00,0x00, + 0xF4,0x02,0x00,0x00,0x34,0x03,0x00,0x00,0x00,0x03,0x00,0x40,0x9C,0x02,0x00,0x00, + 0xA0,0x02,0x00,0x00,0xA2,0x02,0x00,0x00,0xA6,0x02,0x00,0x00,0x98,0x0E,0x00,0x00, + 0x00,0x20,0x00,0x40,0xFE,0x18,0x00,0x00,0x01,0x19,0x00,0x00,0x04,0x19,0x00,0x00, + 0x0A,0x19,0x00,0x00,0x07,0x19,0x00,0x00,0x0D,0x19,0x00,0x00,0x10,0x19,0x00,0x00, + 0x13,0x19,0x00,0x00,0x16,0x19,0x00,0x00,0x19,0x19,0x00,0x00,0x1C,0x19,0x00,0x00, + 0x1F,0x19,0x00,0x00,0x22,0x19,0x00,0x00,0x28,0x19,0x00,0x00,0x25,0x19,0x00,0x00, + 0x54,0x10,0x00,0x00,0x2B,0x19,0x00,0x00,0x50,0x3B,0x07,0x0C,0x51,0x3B,0xFD,0x0B, + 0x60,0x95,0x65,0x93,0xCD,0x7B,0x81,0x07,0x21,0x33,0x61,0xA4,0x0F,0x32,0x63,0x98, + 0x46,0xA3,0x67,0x83,0x40,0x3B,0x1C,0x0C,0x60,0x95,0x6E,0x93,0xCD,0x7B,0x63,0x98, + 0x00,0x32,0x47,0xA3,0x01,0x30,0x00,0x33,0x68,0xA4,0x69,0xA4,0x00,0xE0,0x6B,0x05, + 0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x02,0x30,0xCD,0x7B,0x68,0x48,0x04,0xA4, + 0x65,0xA4,0x70,0x48,0x18,0x48,0x66,0xA4,0x07,0xA4,0x00,0xE0,0xA7,0x04,0x00,0x30, + 0x00,0xE0,0x59,0x05,0x60,0x95,0x6F,0x93,0x05,0x32,0x0A,0x31,0x05,0x30,0xCD,0x7B, + 0x40,0x38,0x0B,0x0C,0x04,0x33,0x0C,0x68,0x00,0x74,0x40,0x38,0x06,0x0C,0x00,0xE0, + 0x44,0x06,0x63,0x98,0x01,0x32,0x47,0xA3,0x00,0x33,0x0E,0x1A,0x60,0xA2,0x45,0x84, + 0x23,0x33,0x61,0xA4,0x48,0x42,0x64,0x84,0x8C,0x6C,0x66,0x84,0x70,0x43,0x8C,0x6C, + 0x67,0x84,0x78,0x43,0xC8,0x6C,0x4A,0x98,0x20,0x92,0xC4,0x64,0x58,0x08,0x10,0x32, + 0x8C,0x60,0x86,0x60,0x45,0x4A,0x28,0x98,0x49,0xA9,0x4A,0x98,0x60,0xB2,0x60,0x95, + 0x70,0x93,0x0E,0x18,0xCD,0x7B,0xF0,0x33,0x5F,0x84,0xCA,0x64,0x67,0x98,0x68,0x83, + 0x48,0x08,0xA3,0x3B,0x47,0x98,0x68,0xA2,0x6B,0x98,0x70,0x93,0x66,0xB8,0x69,0x98, + 0x60,0x93,0x66,0x93,0x5F,0x6C,0x06,0x98,0xCD,0x7B,0xDF,0x38,0x02,0x0C,0x00,0x30, + 0xC0,0x74,0x66,0xB8,0x4E,0xD8,0x18,0x00,0x63,0x98,0x45,0xA3,0x71,0x84,0x40,0x3B, + 0x0F,0x08,0x60,0x95,0xFA,0x30,0x68,0x93,0x02,0x40,0xCD,0x7B,0x63,0x98,0x6D,0x83, + 0x40,0x3B,0x06,0x08,0x64,0x98,0x60,0x93,0x6F,0x93,0x00,0x30,0xCD,0x7B,0x00,0x33, + 0x63,0xA4,0xFF,0x32,0x7F,0x84,0x8E,0x64,0x1E,0x08,0x70,0x84,0x40,0x3B,0x0B,0x08, + 0x0F,0x33,0x54,0x84,0x8C,0x68,0x60,0x95,0x72,0x93,0x8F,0x6D,0x26,0x98,0x01,0x33, + 0x1F,0x6C,0xD9,0x7B,0x60,0x95,0x71,0x93,0x01,0x32,0x26,0x98,0x1F,0x6C,0xCD,0x7B, + 0x20,0x04,0x00,0x00,0x00,0x80,0xFF,0xFF,0x00,0xA5,0xFF,0xFF,0x0F,0x32,0xA9,0x07, + 0x83,0x3B,0xB9,0x07,0xF0,0x32,0x8E,0x64,0x14,0x08,0x6F,0x01,0x13,0x83,0x00,0x31, + 0x01,0x29,0x02,0x74,0x42,0x64,0x6D,0xB8,0x2C,0xB8,0xE5,0x0F,0x63,0x98,0x01,0x32, + 0x45,0xA3,0x40,0x95,0x00,0x74,0x53,0x92,0xC9,0x7B,0x2C,0x98,0x6D,0x98,0x33,0xA3, + 0x7B,0x84,0x5A,0x84,0x68,0x43,0xC8,0x6C,0x40,0x3B,0x08,0x08,0x63,0x98,0x65,0x83, + 0x40,0x3B,0x04,0x08,0x70,0x84,0x40,0x3B,0x56,0x0C,0x00,0x33,0x68,0xA4,0x69,0xA4, + 0x24,0x33,0x61,0xA4,0x00,0x32,0x63,0x98,0x52,0xA3,0x64,0x98,0x40,0x93,0x80,0x36, + 0x98,0x60,0x76,0x92,0xCD,0x7B,0x64,0x98,0x60,0x93,0xD8,0x60,0x77,0x93,0xCD,0x7B, + 0x7E,0x84,0x4A,0x3B,0x11,0x0C,0x00,0x32,0x28,0x30,0x6A,0x02,0xC8,0x60,0x2A,0x02, + 0xCA,0x02,0x4C,0x60,0xD8,0x60,0x20,0x89,0x60,0x8B,0x4E,0x60,0x3E,0x39,0x52,0x0D, + 0x01,0x22,0x0A,0x64,0xF3,0x0B,0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x02,0x30, + 0xCD,0x7B,0x68,0x48,0x59,0x84,0x65,0xA4,0x70,0x48,0x66,0xA4,0x48,0x42,0x78,0x84, + 0x8C,0x6C,0x04,0xA4,0x40,0x3A,0x18,0x48,0x07,0xA4,0x46,0xB8,0x28,0x0C,0x60,0x95, + 0x66,0x93,0x0A,0x30,0xCD,0x7B,0x64,0x98,0x60,0x93,0x65,0x93,0x01,0x32,0x21,0x31, + 0x08,0x30,0xCD,0x7B,0x79,0x84,0x58,0x84,0x68,0x43,0xC8,0x6C,0x00,0x2B,0xCD,0x74, + 0x78,0xA4,0x68,0x4B,0x79,0xA4,0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x01,0x30, + 0xCD,0x7B,0x80,0x04,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x48,0x03,0xC8,0x64, + 0xA8,0x0F,0x00,0x23,0xCD,0x74,0x68,0xA4,0x68,0x4B,0xA2,0x07,0x63,0x98,0x60,0x83, + 0x40,0x3B,0x10,0x08,0x63,0x98,0x63,0x83,0x40,0x3B,0x0C,0x0C,0x63,0x98,0x00,0x32, + 0x45,0xA3,0x00,0x33,0x68,0xA4,0x00,0x33,0x7F,0x2B,0x69,0xA4,0x00,0x33,0x78,0xA4, + 0x79,0xA4,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x40,0x3B,0x05,0x08,0x60,0x95, + 0x66,0x93,0x0A,0x30,0xCD,0x7B,0x63,0x98,0x60,0x83,0x40,0x3B,0xB4,0x08,0x69,0x84, + 0x48,0x84,0x68,0x43,0xC8,0x6C,0xCF,0x74,0xDF,0x3B,0xAD,0x0C,0x60,0x95,0x66,0x93, + 0xC8,0x30,0xCD,0x7B,0x60,0x95,0x6C,0x93,0x9F,0x6C,0x00,0x31,0x01,0x30,0xCD,0x7B, + 0x63,0x98,0x60,0x83,0x40,0x3B,0x23,0x08,0x63,0x98,0x00,0x32,0x52,0xA3,0x60,0x95, + 0x6C,0x93,0x9F,0x6C,0x28,0x31,0x00,0x30,0xCD,0x7B,0x63,0x98,0xC3,0x83,0x40,0x3E, + 0x52,0x08,0x65,0x98,0x47,0x83,0x68,0x83,0x68,0x43,0xC8,0x6C,0x45,0x98,0x25,0x82, + 0x46,0x82,0x48,0x42,0x84,0x6C,0xCA,0x60,0xCF,0x74,0xDF,0x3B,0x03,0x0C,0x00,0x32, + 0x6D,0x5A,0x4F,0x32,0xC9,0x64,0x60,0x0C,0x43,0x3E,0x49,0x08,0x60,0x95,0x66,0x93, + 0x0A,0x30,0xCD,0x7B,0x00,0x33,0x02,0x2B,0x68,0xA4,0x7F,0x33,0x69,0xA4,0x63,0x98, + 0x61,0x83,0x00,0x2B,0xCC,0x74,0xFD,0x32,0xC8,0x64,0x03,0x0C,0x43,0x98,0x61,0xA2, + 0x64,0x98,0x60,0x93,0x68,0x93,0x00,0x31,0x01,0x30,0xCD,0x7B,0x63,0x98,0x00,0x32, + 0x52,0xA3,0x26,0x33,0x61,0xA4,0x70,0x84,0x40,0x3B,0x7C,0x0C,0x01,0x33,0x71,0xA4, + 0x69,0x98,0x60,0x93,0x7F,0x23,0x68,0x93,0x38,0x32,0x00,0x31,0x14,0x12,0xCD,0x7B, + 0x60,0x95,0x0B,0x93,0xC1,0x7B,0x40,0x38,0x04,0x0C,0x60,0x95,0x6A,0x93,0xCD,0x7B, + 0x60,0x95,0x07,0x93,0xC1,0x7B,0x40,0x38,0x6C,0x0C,0x00,0x32,0x63,0x98,0x00,0x2A, + 0x4A,0xA3,0x67,0x04,0x60,0x95,0x07,0x93,0xC1,0x7B,0xC6,0x98,0x64,0x98,0x60,0x93, + 0x68,0x93,0x00,0x31,0x01,0x30,0xCD,0x7B,0xC6,0xB8,0x93,0x07,0x60,0x95,0x6C,0x93, + 0x9F,0x6C,0x28,0x31,0x00,0x30,0xCD,0x7B,0x65,0x98,0x47,0x83,0x68,0x83,0x68,0x43, + 0xC8,0x6C,0x45,0x98,0x25,0x82,0x46,0x82,0x48,0x42,0x84,0x6C,0xCA,0x60,0x00,0x26, + 0xCF,0x74,0x98,0x75,0x9B,0x07,0x43,0x3E,0xA2,0x0F,0x00,0xE0,0x55,0x02,0x64,0x98, + 0x60,0x93,0x65,0x93,0x01,0x32,0x22,0x31,0x0A,0x30,0xCD,0x7B,0x75,0x11,0x09,0x32, + 0x47,0xA3,0x61,0x83,0xA0,0x3B,0x53,0x11,0x61,0xA2,0x02,0x33,0x0C,0x68,0x00,0x74, + 0x40,0x38,0x8D,0x0B,0x66,0x98,0xC2,0x5B,0x46,0x98,0xC7,0x33,0x8C,0x64,0x99,0x75, + 0xC6,0x0B,0x85,0x07,0x69,0x84,0x48,0x84,0x68,0x43,0xC8,0x6C,0x4A,0x11,0xC8,0x64, + 0x05,0x08,0x60,0x95,0x66,0x93,0x28,0x30,0xCD,0x7B,0x64,0x98,0x60,0x93,0x65,0x93, + 0x01,0x32,0x21,0x31,0x0A,0x30,0xCD,0x7B,0x08,0x33,0x0C,0x68,0x00,0x74,0x40,0x38, + 0x77,0x0B,0x64,0x98,0x60,0x93,0x65,0x93,0x01,0x32,0x21,0x31,0x08,0x30,0xCD,0x7B, + 0x6F,0x07,0x00,0x33,0x71,0xA4,0x60,0x95,0x0B,0x93,0xC1,0x7B,0x40,0x38,0x13,0x08, + 0x00,0xE0,0xA4,0x02,0x6B,0x84,0x4A,0x84,0x68,0x43,0xC8,0x6C,0xFE,0x32,0xC8,0x64, + 0x03,0x08,0x00,0xE8,0x53,0xFD,0x00,0x23,0xCD,0x74,0x6A,0xA4,0x68,0x4B,0x6B,0xA4, + 0x00,0xE8,0x4C,0xFD,0x60,0x95,0x6A,0x93,0xCD,0x7B,0x60,0x95,0x07,0x93,0xC1,0x7B, + 0xE8,0x07,0x00,0x33,0x79,0x2B,0x68,0xA4,0x01,0x33,0x69,0xA4,0x60,0x95,0x66,0x93, + 0x0A,0x30,0xCD,0x7B,0xD1,0x06,0x00,0x00,0x28,0x55,0x00,0x00,0xF4,0x3C,0x00,0x00, + 0xE4,0x0E,0x00,0x00,0xBA,0x0E,0x00,0x00,0xFE,0x7F,0x00,0x00,0x9C,0x28,0x00,0x00, + 0x00,0x20,0x00,0x40,0x8F,0x01,0x00,0x00,0xD4,0x14,0x24,0x14,0x88,0x12,0x41,0x84, + 0x01,0x35,0x94,0x68,0x40,0x3A,0x0D,0x0C,0x47,0x84,0xFE,0x33,0x8C,0x68,0x47,0xA4, + 0x64,0x12,0xCD,0x7B,0x67,0x84,0xD4,0x6C,0xCC,0x74,0x67,0xA4,0x04,0x14,0x94,0x14, + 0x61,0x12,0x63,0xB8,0x53,0x6C,0x41,0x12,0x67,0x84,0xCE,0x74,0xDF,0x3B,0x04,0x08, + 0x63,0x98,0x40,0x3B,0x4B,0x08,0x67,0x81,0x64,0x4B,0x07,0x32,0xC8,0x68,0x60,0xB8, + 0xBB,0x11,0x00,0x33,0x66,0xA5,0x38,0x33,0x9A,0x11,0xD0,0x60,0x00,0x36,0x61,0xB8, + 0x60,0x98,0x8E,0x65,0xE4,0x0F,0x52,0x11,0x67,0x82,0x0F,0x31,0xC4,0x68,0x24,0x46, + 0xC4,0x6C,0xCC,0x74,0x67,0xA2,0xE3,0x82,0x46,0x85,0x01,0x3A,0xDC,0x75,0x2B,0x85, + 0x4D,0x08,0x10,0x8C,0xDD,0x74,0x08,0x40,0x0C,0x6C,0x01,0x74,0x40,0x39,0x10,0xAC, + 0x36,0x0C,0x40,0x3A,0x19,0x08,0x4D,0x94,0x53,0x92,0x1F,0x6C,0x62,0xB8,0xC9,0x7B, + 0x40,0x38,0x62,0x98,0x08,0x0C,0x01,0x32,0x4A,0xA5,0x00,0x32,0x4B,0xA5,0x01,0x31, + 0x4B,0x94,0x20,0xA2,0x53,0x85,0xCA,0x65,0x19,0x08,0x00,0x33,0x67,0xA5,0x00,0x33, + 0x74,0xAC,0x65,0x94,0xCD,0x7B,0x66,0x85,0x41,0x3B,0x04,0x08,0x61,0x98,0x00,0x32, + 0x54,0xA3,0x66,0x94,0x1F,0x6C,0xCD,0x7B,0x16,0x04,0xA0,0x33,0x62,0xAA,0x00,0x33, + 0x62,0xAA,0x63,0x98,0x00,0x2B,0x63,0xB8,0xA8,0x07,0x54,0x8C,0x89,0x74,0x48,0x42, + 0x89,0x74,0x54,0xAC,0x54,0x8C,0x89,0x74,0xC8,0x6C,0xE3,0x07,0x40,0x3A,0x09,0x08, + 0x61,0x94,0xCD,0x7B,0x66,0x85,0x00,0x23,0x66,0xA5,0x00,0x26,0x98,0x75,0xA9,0x07, + 0x62,0x94,0x08,0x48,0xCD,0x7B,0x62,0x94,0xDE,0x07,0x40,0x39,0x05,0x0C,0x66,0x94, + 0x1F,0x6C,0xCD,0x7B,0xF3,0x07,0x62,0x94,0xFC,0x07,0x00,0x00,0x00,0x20,0x00,0x40, + 0x68,0x1E,0x01,0x00,0x10,0x27,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x3C,0x00,0x00, + 0xE0,0x3B,0x00,0x00,0xD4,0x14,0x27,0x14,0x61,0xB8,0x6E,0xD8,0x1A,0x10,0x51,0x3B, + 0x87,0x6D,0x4B,0x6D,0xEE,0xD8,0x18,0x10,0x60,0xB8,0x31,0x08,0x68,0x4F,0x08,0x3B, + 0x2E,0x0C,0x73,0x03,0x60,0x32,0x20,0x31,0x8C,0x60,0x4C,0x60,0x51,0x82,0x32,0x81, + 0x7E,0x93,0x48,0x7C,0x4C,0x60,0x77,0x03,0x02,0x1C,0x60,0x93,0x7F,0x23,0x67,0x93, + 0x13,0x6C,0xCD,0x7B,0x11,0x75,0x7A,0x03,0x83,0xAB,0x5B,0x03,0x62,0x8A,0xCD,0x74, + 0xA4,0x3B,0x62,0xAA,0x6E,0xD8,0x02,0x10,0xCD,0x74,0x99,0x75,0x55,0x75,0xC4,0xAA, + 0xA5,0xAA,0x66,0xAA,0x6E,0xD8,0x00,0x10,0xE1,0xAA,0x10,0x31,0x60,0xAA,0x62,0x8A, + 0xCD,0x74,0xC4,0x68,0x40,0x3B,0xFC,0x0F,0x07,0x14,0x94,0x14,0x01,0x74,0x77,0x13, + 0x03,0xAB,0xE4,0x07,0xD1,0x14,0x74,0x13,0x0A,0x32,0x60,0x93,0x83,0x93,0x03,0x31, + 0x73,0x13,0xD1,0x7B,0x00,0x30,0x91,0x14,0xD4,0x14,0x23,0x14,0x83,0x6D,0x4B,0x6C, + 0x40,0xB8,0x70,0x13,0x63,0x83,0x0F,0x32,0xC9,0x68,0x40,0x3B,0x55,0x0C,0x6E,0x13, + 0x80,0x83,0x40,0x3C,0x51,0x0C,0x6B,0x13,0x77,0x83,0x62,0xB8,0xA3,0x5C,0xA1,0xB8, + 0xDF,0x3D,0x46,0x08,0x69,0x13,0x0C,0x61,0x84,0x44,0x04,0x61,0x11,0x04,0x00,0x33, + 0x1E,0x04,0x00,0x32,0x24,0x04,0x61,0x98,0xD5,0x64,0x32,0x08,0x61,0x98,0x00,0x2B, + 0x61,0xB8,0x00,0x2D,0x0F,0x2C,0x00,0x33,0x00,0x2B,0xD6,0x64,0x31,0x0C,0x13,0x6C, + 0x41,0x8C,0x8B,0x74,0x47,0x52,0x20,0x8C,0x47,0x74,0x27,0x51,0x20,0x3A,0xE8,0x0B, + 0x75,0x86,0xCE,0x74,0x00,0x2B,0xC9,0x64,0x02,0x0C,0xCB,0x6C,0x20,0x39,0xE2,0x0B, + 0x54,0x86,0x8A,0x74,0x00,0x2A,0x85,0x64,0x02,0x0C,0x87,0x6C,0x22,0x98,0x61,0x43, + 0xE1,0x96,0xDC,0x60,0x60,0x8B,0xCF,0x74,0xC5,0x64,0xD6,0x0F,0x22,0x98,0x62,0x96, + 0x41,0x42,0x8C,0x60,0x60,0x8A,0xCF,0x74,0xC5,0x64,0xD4,0x0B,0xCD,0x07,0x21,0x98, + 0x24,0x41,0x60,0x98,0x4C,0x60,0x10,0x32,0x00,0xE0,0x06,0x03,0xC8,0x07,0x61,0x98, + 0x00,0x23,0x45,0x12,0x60,0xA2,0x00,0x30,0x03,0x14,0x94,0x14,0x64,0x12,0x05,0x12, + 0x25,0x12,0x49,0x80,0x8A,0x74,0xDF,0x3A,0x09,0x08,0x00,0x2B,0xA0,0x32,0xCD,0x74, + 0x42,0xA9,0x40,0x3B,0x00,0x32,0x42,0xA9,0xF5,0x0B,0x3C,0x78,0xD4,0x14,0x26,0x14, + 0xBE,0x11,0x83,0x6D,0x6D,0x95,0x07,0x6D,0x04,0x30,0x3E,0x93,0x64,0x93,0x41,0xB8, + 0xCD,0x7B,0x6D,0x95,0x7F,0x23,0x63,0x93,0x08,0x30,0xCD,0x7B,0x78,0x11,0x01,0x32, + 0x40,0xAB,0x74,0x11,0x61,0x32,0x48,0xA3,0x60,0x32,0x49,0xA3,0x75,0x11,0x01,0x32, + 0x42,0xA3,0x0C,0x32,0x44,0xA3,0x30,0x32,0x43,0xA3,0x61,0x98,0x18,0x61,0x00,0x37, + 0x60,0xB8,0x82,0xB8,0x7F,0x2F,0x62,0x98,0xDA,0x64,0x03,0x08,0x06,0x14,0x94,0x14, + 0x60,0x86,0x6E,0xDC,0x17,0x00,0x6D,0x95,0x7F,0x23,0x05,0x18,0x64,0x93,0x02,0x32, + 0x01,0x31,0x02,0x20,0xCD,0x7B,0x00,0x34,0x07,0x32,0x40,0x33,0x0C,0x6D,0x53,0x6C, + 0x5C,0x6C,0x63,0xB8,0x44,0x74,0x63,0x11,0x44,0xB8,0x25,0xA3,0x2D,0x95,0x27,0x91, + 0x14,0x30,0xC5,0x7B,0x7F,0x10,0x26,0x83,0x40,0x30,0x40,0x68,0x40,0x39,0x63,0x98, + 0x44,0x98,0x03,0x08,0x0D,0x69,0x10,0x75,0x00,0x2A,0x40,0x3A,0x61,0x4B,0xE7,0x0B, + 0x6D,0x95,0x7F,0x23,0x05,0x18,0x64,0x93,0x08,0x32,0x01,0x31,0x02,0x20,0xCD,0x7B, + 0x61,0x98,0x40,0x3B,0x04,0x0C,0x00,0x24,0x60,0x98,0x80,0xAB,0x6D,0x95,0x68,0x93, + 0x00,0x31,0x01,0x30,0xCD,0x7B,0x60,0x98,0x01,0x23,0x60,0xB8,0x00,0x26,0xBC,0x07, + 0x18,0x3C,0x00,0x00,0xE4,0x54,0x00,0x00,0x00,0x11,0x00,0x40,0x68,0x10,0x00,0x00, + 0xE8,0x54,0x00,0x00,0x30,0x55,0x00,0x00,0xFF,0xFF,0xFF,0x0F,0x20,0x4E,0x00,0x00, + 0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0xE0,0x3B,0x00,0x00,0x00,0x10,0x00,0x40, + 0x60,0x12,0x00,0x40,0xC1,0x14,0x21,0x14,0x72,0x00,0x31,0x00,0x60,0xB8,0x11,0x00, + 0xC7,0x6C,0x44,0x81,0x08,0x34,0x90,0x68,0x40,0x3A,0x04,0x0C,0x40,0x98,0x40,0x3A, + 0x0B,0x08,0x41,0x83,0xFE,0x31,0x84,0x68,0x41,0xA3,0x00,0x32,0x46,0xA3,0x0B,0x32, + 0x47,0xA3,0x01,0x14,0x81,0x14,0xA0,0x32,0x42,0xA8,0x00,0x32,0x42,0xA8,0x40,0x98, + 0x00,0x2A,0x40,0xB8,0xE7,0x07,0xD4,0x14,0x21,0x14,0x7F,0x00,0xB8,0x35,0x4C,0x61, + 0x21,0x95,0xC0,0x01,0x82,0x8E,0x6D,0x93,0x20,0xB8,0x02,0x31,0x22,0xAE,0x3E,0x93, + 0x7F,0x23,0x83,0x6C,0x21,0xB5,0xEB,0x93,0x01,0x31,0x01,0x33,0x01,0x30,0x11,0x75, + 0xDD,0x7B,0x10,0x75,0x60,0x98,0x82,0xAE,0x61,0xB5,0x01,0x14,0x94,0x14,0xD4,0x14, + 0x22,0x14,0x8D,0x01,0x80,0x35,0x61,0xB8,0x6D,0x94,0xC3,0x6D,0xD4,0x60,0x40,0xB8, + 0xD4,0x93,0x08,0x32,0x00,0x33,0x07,0x6C,0x5F,0x6C,0xD9,0x7B,0x83,0x6D,0xFF,0xE3, + 0x1F,0xFF,0x01,0x30,0xFF,0xE3,0xD1,0xFF,0x6D,0x94,0xD4,0x60,0x01,0x30,0x75,0x93, + 0xCD,0x7B,0x6D,0x94,0x4C,0x61,0x77,0x95,0xCD,0x7B,0x79,0x01,0x60,0x93,0x19,0x01, + 0xA3,0x93,0x10,0x60,0x60,0x98,0x41,0x98,0x5B,0x6C,0xD5,0x7B,0x02,0x14,0x94,0x14, + 0x00,0x74,0x7D,0x01,0x01,0xA3,0x01,0x31,0x43,0x83,0x84,0x68,0x40,0x3A,0xFD,0x0F, + 0x01,0x32,0x00,0x30,0x43,0xA3,0x3C,0x78,0xD3,0x14,0x00,0x33,0x83,0x02,0x7F,0x2B, + 0x68,0xA4,0x00,0x33,0x69,0xA4,0x47,0x6D,0x6B,0x02,0x83,0x6D,0x6D,0x93,0x0A,0x30, + 0x66,0x93,0xCD,0x7B,0xC8,0xA4,0x00,0x30,0xA9,0xA4,0x50,0x02,0x2A,0x02,0x69,0x84, + 0xCE,0x74,0xDF,0x3B,0x09,0x08,0x00,0x20,0xA0,0x33,0x01,0x74,0x62,0xAA,0x42,0x64, + 0x00,0x33,0x62,0xAA,0xF5,0x0B,0x93,0x14,0xD4,0x14,0x21,0x14,0x8A,0x30,0x98,0x02, + 0x01,0x40,0x10,0x60,0x60,0x80,0x60,0xB8,0x8F,0x6C,0xF2,0x33,0xF5,0x02,0x64,0x43, + 0x4C,0x31,0xA1,0x80,0x40,0x60,0x80,0x36,0x0C,0x60,0x60,0x97,0x94,0x7C,0xD8,0x60, + 0x41,0x42,0x67,0x93,0xCD,0x7B,0x60,0x97,0xD8,0x60,0x3B,0x02,0x1B,0x02,0x41,0x45, + 0x50,0x60,0x10,0x60,0x67,0x93,0xCD,0x7B,0x60,0x98,0x41,0x43,0x60,0x97,0x8C,0x61, + 0x3F,0x02,0x1E,0x02,0x50,0x60,0x10,0x60,0x67,0x96,0xCD,0x7B,0x01,0x14,0x94,0x14, + 0xD4,0x14,0x3E,0x15,0x04,0xB8,0x0E,0x32,0x87,0x6D,0x05,0x18,0x24,0x03,0x00,0xE0, + 0xA3,0x01,0x22,0x32,0x00,0x31,0x09,0x18,0x00,0xE0,0xA8,0x01,0x00,0x33,0x05,0x1A, + 0x8C,0x60,0x40,0x82,0x09,0x19,0x00,0x23,0x84,0x60,0x4E,0x3B,0x01,0x31,0x20,0xA2, + 0xF7,0x0B,0x2C,0x03,0x84,0x91,0xA2,0x91,0x00,0x32,0x00,0x33,0x23,0xB8,0x09,0x19, + 0x48,0x60,0x20,0x81,0x04,0x98,0x06,0x64,0x17,0x08,0x28,0x5C,0x24,0x18,0x20,0x81, + 0x0C,0x60,0x20,0xA0,0x28,0x5D,0x1B,0x18,0x0C,0x60,0x20,0x81,0x40,0x3E,0x20,0xA0, + 0x09,0x08,0x17,0x03,0x23,0x98,0x08,0x60,0x04,0x60,0x12,0x19,0x4C,0x60,0x00,0x80, + 0x00,0xA1,0x00,0x23,0xCC,0x74,0x00,0x22,0x22,0x31,0x4A,0x64,0xE1,0x0B,0x40,0x3B, + 0x47,0x0C,0xB2,0x13,0x80,0x34,0x4D,0x95,0x61,0xB8,0x12,0x1B,0x90,0x60,0xC2,0xB8, + 0x60,0xB8,0x6D,0x92,0xCF,0x6D,0x1B,0x1A,0x2D,0x1B,0x24,0x19,0x1A,0x13,0xDD,0x7B, + 0x7A,0x13,0x26,0x83,0x6D,0x95,0xD0,0x60,0x00,0x32,0x6E,0x93,0x30,0x30,0xCD,0x7B, + 0xFF,0xE3,0x56,0xFE,0x00,0x30,0xFF,0xE3,0x08,0xFF,0x6D,0x95,0xD0,0x60,0x6F,0x93, + 0xCD,0x7B,0x6D,0x95,0x0C,0x61,0x71,0x94,0xCD,0x7B,0x00,0x33,0x00,0x32,0x22,0x30, + 0x09,0x19,0x4C,0x60,0x20,0x81,0x84,0x98,0x06,0x65,0x17,0x08,0x8C,0x13,0x21,0x43, + 0x50,0x60,0x83,0x98,0x50,0x60,0x2D,0x1D,0x81,0x42,0x14,0x61,0x80,0x8C,0x40,0x3E, + 0x80,0xA9,0x09,0x0C,0x23,0x13,0x83,0x98,0x4C,0x60,0x50,0x60,0x12,0x1C,0x08,0x61, + 0x80,0x84,0x80,0xA1,0x00,0x22,0x88,0x74,0x00,0x23,0x0E,0x64,0xE2,0x0B,0x1E,0x15, + 0x94,0x14,0xD4,0x14,0x25,0x14,0x8A,0x35,0x8C,0x12,0xA1,0x45,0x7D,0x12,0x40,0x38, + 0xC3,0x6D,0x50,0x61,0x64,0xB8,0x80,0x0C,0x6D,0x94,0x7F,0x23,0x79,0x93,0xCD,0x7B, + 0xE2,0xB8,0x40,0x85,0x41,0xB8,0x58,0x12,0x6D,0x94,0x94,0x60,0x40,0xB8,0x7F,0x23, + 0x6D,0x93,0x8F,0x6D,0x41,0x95,0x75,0x12,0x23,0x95,0x0F,0x12,0xD9,0x7B,0x71,0x12, + 0x1F,0x23,0x26,0x83,0x6D,0x94,0x7F,0x23,0x00,0x32,0x6E,0x93,0x30,0x30,0xCD,0x7B, + 0xFF,0xE3,0xFE,0xFD,0x00,0x30,0xFF,0xE3,0xB0,0xFE,0x6D,0x94,0x7F,0x23,0x6F,0x93, + 0xCD,0x7B,0x6D,0x94,0x7F,0x23,0x71,0x93,0xCD,0x7B,0x5F,0x6C,0x00,0x30,0xFF,0xE3, + 0x41,0xFF,0x5F,0x6C,0x01,0x30,0xFF,0xE3,0x3D,0xFF,0x40,0x3F,0x15,0x0C,0x60,0x85, + 0x63,0xB8,0x00,0x31,0x00,0x32,0x3F,0x36,0xC4,0x74,0x03,0x98,0x0C,0x64,0xA1,0x0C, + 0xFF,0x31,0x85,0x64,0xCB,0x6C,0x02,0x0C,0xFF,0x33,0x8F,0x74,0xDF,0x3A,0x02,0x0C, + 0x00,0x33,0x5B,0x11,0x61,0xA2,0x80,0x36,0x6D,0x94,0x3A,0x11,0x20,0xB8,0x97,0x6C, + 0xD8,0x60,0xE1,0xB8,0xB2,0x93,0x4B,0x22,0x77,0x11,0x2D,0x11,0x17,0x11,0xD5,0x7B, + 0x57,0x11,0x60,0x33,0xC8,0x60,0x0A,0x31,0x31,0xA3,0x03,0x31,0x30,0xA3,0x75,0x11, + 0x7D,0xB2,0x63,0x23,0x7E,0xB2,0x64,0x98,0x1F,0x23,0x26,0x83,0x6D,0x94,0xD8,0x60, + 0x08,0x32,0xB4,0x93,0x30,0x30,0x00,0x33,0xD5,0x7B,0xFF,0xE3,0xB1,0xFD,0x01,0x30, + 0xFF,0xE3,0x63,0xFE,0x6D,0x94,0xD8,0x60,0x75,0x93,0x00,0x30,0xCD,0x7B,0x40,0x3F, + 0x09,0x0C,0x6D,0x94,0xD8,0x60,0x76,0x93,0xCD,0x7B,0x6D,0x94,0x8C,0x61,0x77,0x96, + 0xCD,0x7B,0x05,0x14,0x94,0x14,0x3B,0x10,0x6D,0x94,0x77,0x21,0x01,0xB8,0x20,0xB8, + 0x7F,0x23,0x72,0x93,0x8F,0x6D,0x4C,0x32,0x3E,0x04,0x00,0x00,0x10,0x27,0x00,0x00, + 0x00,0x20,0x00,0x40,0x00,0x02,0x00,0x40,0xE0,0x3B,0x00,0x00,0x00,0x10,0x00,0x40, + 0xD0,0x51,0x00,0x00,0x34,0x10,0x00,0x00,0x20,0x20,0x00,0x40,0x00,0x03,0x00,0x40, + 0x50,0xC3,0x00,0x00,0xE4,0x54,0x00,0x00,0x22,0x0F,0x00,0x00,0x84,0x15,0x00,0x00, + 0xCE,0x0F,0x00,0x00,0xC8,0x15,0x00,0x00,0x28,0x18,0x00,0x00,0xF4,0x3C,0x00,0x00, + 0x98,0x0E,0x00,0x00,0xE4,0x01,0x00,0x00,0xF4,0x51,0x00,0x00,0x0E,0x0E,0x00,0x00, + 0xD4,0x51,0x00,0x00,0x0C,0x0F,0x00,0x00,0xAE,0x4B,0x00,0x00,0x7C,0x54,0x00,0x00, + 0x4C,0x52,0x00,0x00,0xE2,0x47,0x00,0x00,0xD4,0x01,0x00,0x00,0x18,0x3C,0x00,0x00, + 0x36,0x18,0x00,0x00,0x62,0x11,0x94,0x60,0xD0,0x60,0x57,0x6C,0x01,0x11,0xD9,0x7B, + 0x6D,0x94,0x7F,0x23,0x8F,0x6D,0x90,0x33,0x61,0xB8,0xE0,0xB8,0x00,0x33,0xDA,0x96, + 0x32,0x32,0x20,0x31,0x0F,0x30,0xD9,0x7B,0x7B,0x10,0x1F,0x23,0x06,0xA3,0x29,0x07, + 0x7A,0x10,0xC4,0x60,0xD4,0x60,0x60,0x83,0x0E,0x74,0xDF,0x38,0x08,0x0C,0x40,0x30, + 0x0C,0x68,0x40,0x38,0xD8,0x68,0x05,0x0C,0x8E,0x60,0x8B,0x74,0x00,0x21,0x4D,0x07, + 0xC8,0x60,0x8F,0x74,0xFC,0x07,0xD3,0x14,0xB1,0x10,0x80,0x34,0x60,0x95,0xD1,0x10, + 0xD0,0x60,0xAA,0x32,0x68,0x93,0x43,0x42,0x00,0x31,0x14,0x96,0xCD,0x7B,0x60,0x95, + 0xD0,0x60,0x68,0x93,0x44,0x32,0x00,0x31,0x15,0x96,0xCD,0x7B,0x60,0x95,0xD0,0x60, + 0x16,0x96,0x68,0x93,0x28,0x32,0x00,0x31,0xCD,0x7B,0x93,0x14,0x02,0x0C,0x00,0x00, + 0xD4,0x01,0x00,0x00,0xD4,0x51,0x00,0x00,0x0C,0x0F,0x00,0x00,0xE4,0x54,0x00,0x00, + 0x88,0x54,0x00,0x00,0xD0,0x14,0x64,0x10,0x60,0x93,0x7F,0x23,0x67,0x93,0xCD,0x7B, + 0x90,0x14,0x00,0x00,0xE4,0x54,0x00,0x00,0xD0,0x14,0x64,0x10,0x60,0x93,0x7F,0x23, + 0x68,0x93,0xCD,0x7B,0x90,0x14,0x00,0x00,0xE4,0x54,0x00,0x00,0x00,0x00,0x00,0x00, + 0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x00,0x41,0x25,0x0D,0x70,0x73,0x67,0x1E,0x00, + 0x11,0x30,0x0F,0x08,0x02,0x02,0x30,0x30,0x00,0x46,0x73,0x67,0x04,0x0F,0x70,0x14, + 0xFF,0x25,0x26,0x27,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x30,0x31,0xFF,0x32, + 0x33,0x34,0x35,0x36,0x37,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x60,0x61,0x62, + 0x63,0x64,0x65,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x20,0x21,0x22,0x23,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0x05,0x98,0x08,0xDA,0x0B,0xA1,0x0F, + 0xED,0x13,0xB8,0x18,0xFD,0x1D,0xAF,0x23,0xC1,0x29,0x22,0x30,0xBE,0x36,0x7D,0x3D, + 0x48,0x44,0x04,0x4B,0x95,0x51,0xE1,0x57,0xCD,0x5D,0x3D,0x63,0x19,0x68,0x4C,0x6C, + 0xC0,0x6F,0x66,0x72,0x32,0x74,0x1A,0x75,0x1A,0x75,0x32,0x74,0x66,0x72,0xC0,0x6F, + 0x4C,0x6C,0x19,0x68,0x3D,0x63,0xCD,0x5D,0xE1,0x57,0x95,0x51,0x04,0x4B,0x48,0x44, + 0x7D,0x3D,0xBE,0x36,0x22,0x30,0xC1,0x29,0xAF,0x23,0xFD,0x1D,0xB8,0x18,0xED,0x13, + 0xA1,0x0F,0xDA,0x0B,0x98,0x08,0xD9,0x05,0x00,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, + 0x10,0x1D,0x1E,0x1F,0x20,0x21,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF, + 0x01,0x00,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x00,0x01,0xFF,0x01, + 0xFF,0x01,0xFF,0x01,0x01,0x01,0x01,0x00,0xFF,0xFF,0x01,0x01,0x01,0xFF,0x01,0x01, + 0xFF,0xFF,0x00,0x01,0x01,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0x00,0x01,0x01, + 0xFF,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x00,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01, + 0xFF,0x01,0x01,0x00,0x01,0x01,0xFF,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x00,0x01, + 0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x01, + 0x01,0x81,0x81,0x81,0x01,0x00,0x01,0x01,0x01,0x81,0x81,0x81,0x01,0x01,0x01,0x01, + 0x00,0x01,0x81,0x01,0x81,0x01,0x81,0x01,0x01,0x01,0x01,0x00,0x81,0x81,0x01,0x01, + 0x01,0x81,0x01,0x01,0x81,0x81,0x00,0x01,0x01,0x81,0x01,0x01,0x01,0x81,0x01,0x81, + 0x01,0x00,0x01,0x01,0x81,0x01,0x01,0x81,0x81,0x01,0x01,0x01,0x00,0x01,0x01,0x81, + 0x81,0x81,0x01,0x01,0x81,0x01,0x01,0x00,0x01,0x01,0x81,0x01,0x81,0x01,0x01,0x81, + 0x01,0x01,0x00,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x00,0x42,0x30, + 0x00,0x43,0x31,0x00,0x4D,0x30,0x00,0x46,0x32,0x00,0x47,0x32,0x00,0x6F,0x31,0x00, + 0x6F,0x32,0x00,0x70,0x30,0x00,0x70,0x38,0x00,0x70,0x32,0x00,0x70,0x36,0x00,0x71, + 0x31,0x00,0x71,0x32,0x00,0x72,0x31,0x00,0x72,0x32,0x00,0x71,0x30,0x00,0x00,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,0x48,0xBE,0xA8, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst3xx_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst3xx_fw.h new file mode 100644 index 000000000000..7ae27e41f013 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst3xx_fw.h @@ -0,0 +1,1561 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst3xx_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { + 0x98,0xE0,0x07,0x01,0x20,0x48,0x05,0x00,0x00,0x00,0x00,0x00,0x28,0x09,0x06,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xD0,0x69,0x05,0x00,0x28,0x29,0x05,0x00,0x00,0x00,0x00,0x00, + 0xD0,0x28,0x01,0x00,0x00,0x00,0x00,0x00,0x28,0x49,0x06,0x00,0x80,0x07,0xC0,0x17, + 0x82,0x07,0xC0,0x07,0x01,0x65,0x40,0x86,0xC1,0x41,0xC0,0x20,0xC5,0x68,0x31,0x12, + 0xF5,0x38,0x33,0x5A,0x32,0xA2,0x32,0xEA,0x10,0x62,0x8D,0x0E,0x81,0x07,0xC0,0x97, + 0x30,0xF2,0xF3,0x79,0x65,0x7E,0x30,0xB2,0x31,0x09,0x10,0x9A,0x87,0x06,0xD0,0xD8, + 0x35,0x12,0x35,0x5A,0x18,0x9A,0x39,0xC2,0x40,0xC2,0x04,0x00,0x40,0xC2,0x05,0x00, + 0xD0,0x81,0x98,0x16,0x43,0xC6,0x0B,0xC6,0xC2,0xD6,0x3F,0x90,0x99,0x0E,0x40,0x86, + 0x08,0x86,0xA9,0x0E,0x40,0x23,0x00,0x63,0x38,0x82,0x03,0x00,0x18,0x01,0x20,0x01, + 0x28,0x01,0x30,0x01,0xD0,0x81,0x98,0x0E,0x0F,0xC6,0xC3,0xDE,0x38,0x90,0x9A,0x06, + 0x08,0x86,0xA9,0x06,0x03,0x5B,0x38,0x82,0xAE,0xFD,0x30,0x02,0x30,0x02,0xEE,0xFD, + 0xA8,0x85,0xE8,0x85,0x82,0x07,0xC8,0xA7,0x37,0x8A,0xB8,0xFF,0xF8,0xAF,0x87,0x17, + 0xE0,0x5F,0x86,0x07,0xCF,0x67,0xBB,0xFF,0xF8,0x9F,0x87,0x07,0xC8,0x7F,0x03,0x00, + 0xA8,0x85,0x33,0x2A,0x30,0x62,0x30,0xB2,0x00,0x17,0x60,0x7E,0x28,0x7E,0xF0,0x81, + 0x77,0x81,0x90,0xD6,0x70,0x41,0x98,0x16,0x60,0x1E,0x28,0x1E,0xF0,0x41,0x70,0x21, + 0x98,0x3E,0x60,0x0E,0x29,0x0E,0xF8,0xB0,0x01,0x1F,0xC0,0x0B,0x83,0x4B,0xE1,0x20, + 0xE3,0x68,0xF3,0xB0,0x93,0xCE,0xEF,0x85,0x43,0x02,0x38,0x82,0x58,0x40,0x01,0x01, + 0xA9,0x85,0x50,0x01,0xD8,0x26,0x30,0x0A,0xD0,0x01,0x19,0x01,0x00,0x8A,0x04,0x37, + 0x31,0x1A,0x20,0x01,0x04,0x9A,0x04,0x8A,0xD6,0x10,0x05,0x82,0x18,0x0A,0x30,0xC2, + 0xEE,0x85,0x90,0x95,0xA8,0x85,0x10,0x98,0xC0,0xD0,0x24,0x98,0xC0,0xD0,0x84,0x07, + 0xC0,0x7F,0xEA,0x85,0xA8,0xC5,0x57,0x21,0x9C,0x66,0x39,0x18,0x80,0x96,0xC0,0x5B, + 0xE0,0x48,0x82,0x1B,0xE2,0x00,0xF2,0x90,0x38,0x18,0x84,0x5E,0xC2,0x5B,0xE0,0x48, + 0x82,0x1B,0xE0,0x00,0xF4,0x90,0x3A,0x18,0x80,0x26,0xC0,0x5B,0xE0,0x48,0x82,0x1B, + 0xE2,0x00,0xF2,0x90,0x3C,0x58,0x7C,0xD8,0x8F,0x16,0xB8,0xFF,0xFF,0x4F,0xED,0xC5, + 0xD6,0x48,0x06,0xF0,0x1C,0x01,0xD9,0xE8,0x48,0x46,0x00,0x3F,0x00,0x9A,0x37,0xE2, + 0x48,0x46,0x30,0xFA,0x01,0x7A,0x1D,0x3A,0x00,0x06,0xFC,0x90,0x57,0x21,0x90,0xAE, + 0x46,0x58,0xD7,0x48,0xF7,0x90,0xA2,0x56,0xC2,0x5B,0xE0,0x48,0x82,0x1B,0xE0,0x00, + 0xF7,0x90,0xA2,0x26,0xC2,0x5B,0xE0,0x48,0x82,0x1B,0xE0,0x00,0xF6,0x90,0xA2,0xF6, + 0xC0,0x4B,0x80,0x0B,0xE8,0xC5,0x07,0x0F,0x00,0x26,0xF8,0x48,0x4F,0x21,0x90,0xDE, + 0x38,0x58,0xAC,0x0E,0x04,0x14,0xE0,0x00,0x38,0x48,0x86,0x06,0x83,0x13,0x38,0x82, + 0x48,0x01,0x80,0x5E,0x38,0x18,0x86,0x16,0x82,0x13,0xE0,0x00,0xF0,0x48,0x4A,0x11, + 0x9C,0x26,0x38,0x18,0xA8,0x16,0x00,0x14,0xE4,0x00,0xF4,0x48,0x38,0x1F,0x17,0x01, + 0x38,0x77,0x17,0x01,0x38,0xFF,0x16,0x01,0x4C,0x18,0x10,0x5A,0x98,0x66,0x51,0x18, + 0x10,0x5A,0x9C,0x8E,0x1C,0x01,0x30,0xE2,0x00,0x77,0x32,0x1A,0x19,0x5A,0xA0,0xE6, + 0x12,0x01,0x40,0x18,0x11,0x5A,0x9C,0x8E,0x4C,0x18,0x10,0x5A,0x98,0xE6,0x50,0x18, + 0x10,0x5A,0x9C,0x0E,0x31,0xA2,0x04,0xFF,0x4C,0x18,0x16,0x5A,0x9E,0x0E,0x08,0x58, + 0xD2,0x00,0x0E,0x92,0x4C,0x18,0x14,0x5A,0x9C,0x0E,0x08,0x58,0xD2,0x00,0x0E,0x92, + 0x4C,0x18,0x12,0x5A,0x9A,0x0E,0x08,0x58,0xD2,0x00,0x0E,0x92,0x4C,0x18,0x10,0x5A, + 0x98,0x0E,0x08,0x58,0xD2,0x00,0x0E,0x92,0x44,0x18,0x16,0x5A,0x9E,0x0E,0x00,0x58, + 0xD2,0x00,0x0E,0x92,0x44,0x18,0x14,0x5A,0x9C,0x0E,0x00,0x58,0xD2,0x00,0x0E,0x92, + 0x44,0x18,0x12,0x5A,0x9A,0x0E,0x00,0x58,0xD2,0x00,0x0E,0x92,0xD0,0x08,0x92,0x06, + 0x32,0x0A,0x08,0x92,0x33,0x82,0x38,0x82,0x06,0xEF,0x7A,0x50,0x82,0x06,0x10,0x4A, + 0x80,0x18,0x98,0x06,0x12,0x02,0x02,0x9A,0x14,0x01,0x30,0xE2,0x4C,0x18,0x10,0x5A, + 0x98,0x6E,0x51,0x18,0x10,0x5A,0x9C,0x96,0x14,0xE1,0x0F,0x48,0xD0,0x95,0x50,0x18, + 0x10,0x5A,0x9C,0x66,0x0C,0x48,0x8C,0x90,0x10,0x5A,0x9C,0x46,0x0C,0x48,0x8C,0x90, + 0x10,0x5A,0x9C,0x26,0x09,0x48,0x84,0xD6,0x88,0x90,0x04,0x07,0x4E,0x48,0x4C,0x18, + 0x10,0x5A,0x9C,0x0E,0x0E,0x58,0xD6,0x00,0x0C,0x92,0x4A,0x18,0x10,0x5A,0x9C,0x0E, + 0x0E,0x58,0xD4,0x00,0x0A,0x92,0x4A,0x18,0x10,0x5A,0x9C,0x0E,0x0E,0x58,0xD2,0x00, + 0x08,0x92,0x4A,0x18,0x10,0x5A,0x9C,0x0E,0x0E,0x58,0xD0,0x00,0x0E,0x92,0x42,0x18, + 0x10,0x5A,0x9C,0x0E,0x06,0x58,0xD6,0x00,0x0C,0x92,0x42,0x18,0x10,0x5A,0x9C,0x0E, + 0x06,0x58,0xD4,0x00,0x0E,0x92,0x92,0xCE,0x44,0x18,0x12,0x5A,0x9A,0x0E,0x00,0x58, + 0xD2,0x00,0x0E,0x92,0xD0,0x08,0x92,0x06,0x33,0x0A,0x30,0x1A,0x0A,0x92,0x82,0xD8, + 0x30,0x82,0x98,0x0E,0x10,0x02,0x5A,0x01,0xAA,0x06,0x10,0x4A,0x3B,0x82,0x33,0x1A, + 0x80,0xD8,0x9A,0x06,0x10,0x02,0xAA,0x0D,0x06,0x01,0x30,0x02,0x30,0x02,0xEE,0x15, + 0x37,0xAA,0xBB,0xFF,0xF5,0x8F,0x36,0x72,0x03,0x28,0x30,0x4A,0x36,0x9A,0x42,0x00, + 0x04,0x00,0x36,0x2A,0x81,0xC5,0xA8,0x05,0x84,0x07,0xC0,0x8F,0xE0,0x05,0x3B,0x01, + 0x45,0x48,0x32,0xB2,0x36,0x01,0x28,0x06,0x2E,0x06,0x2E,0x06,0x2E,0x06,0x2E,0x06, + 0x2E,0x06,0x2E,0x06,0x2A,0x06,0xEE,0x01,0x04,0x48,0x32,0x6A,0x38,0x82,0x33,0x22, + 0x36,0x02,0x36,0x02,0x37,0x02,0xB9,0xFF,0xF0,0x77,0x04,0x00,0x40,0x12,0x48,0x1A, + 0xF3,0x5D,0x3D,0x82,0x00,0x68,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x30,0x01,0x10, + 0x38,0x82,0x03,0x00,0xA8,0xBD,0x37,0x2A,0x31,0x72,0x40,0x42,0x48,0x42,0x41,0x03, + 0x80,0x15,0x44,0x4B,0xF8,0x13,0x18,0x01,0x98,0x0C,0x90,0x04,0x82,0x01,0xCC,0x03, + 0xFC,0x24,0x88,0x01,0x43,0x63,0xE2,0xF8,0x48,0x00,0x40,0x09,0x8F,0x2E,0x90,0xD5, + 0x08,0x01,0x80,0x1F,0xD0,0x8F,0x02,0x09,0x80,0x0C,0x08,0x01,0x00,0x09,0xD0,0x24, + 0x82,0x1F,0xD0,0x57,0x00,0x11,0xC8,0x24,0x86,0x1F,0xC0,0x27,0x10,0x01,0x30,0x8A, + 0x30,0x02,0x81,0x1F,0xC0,0x0F,0x08,0x01,0x00,0x19,0x80,0x1F,0xC0,0xDF,0x0D,0x09, + 0x30,0x42,0xD0,0x24,0x81,0x1F,0xD0,0xC7,0xC0,0x0C,0x40,0x09,0x88,0x26,0x08,0x09, + 0x90,0xD5,0x37,0x42,0x81,0x1F,0xD0,0x87,0x41,0x72,0x00,0x44,0x01,0x01,0x00,0x84, + 0x30,0x0A,0x00,0x77,0x00,0x01,0x10,0x01,0xF5,0x02,0xF1,0x52,0x10,0x12,0xEC,0x06, + 0x00,0x44,0x11,0x01,0xF4,0x92,0x15,0x12,0xD1,0x06,0x00,0x84,0xE2,0x20,0xE5,0x48, + 0x90,0x4D,0xC6,0x04,0x17,0x0A,0x9C,0x6E,0x87,0x2D,0xE8,0x85,0x00,0x40,0x00,0x01, + 0x00,0x20,0x00,0x01,0xF8,0xFB,0x07,0x00,0xA8,0x85,0x80,0x0F,0xCF,0x0F,0xBC,0xFF, + 0xE8,0xAF,0xEE,0x85,0xA3,0x85,0x31,0xA2,0xF1,0x20,0xC3,0x2B,0xE5,0x20,0x13,0x5A, + 0x90,0x06,0x30,0xEA,0xEA,0x1A,0x03,0xD8,0xC1,0x18,0xE7,0x85,0x38,0xC2,0x30,0x52, + 0x33,0x1A,0x38,0x82,0xAC,0xFD,0x47,0xDA,0x40,0x03,0x30,0x0A,0x8A,0x01,0x44,0x63, + 0x44,0x53,0x4E,0xCA,0x41,0x6B,0xE8,0x73,0xE9,0x5B,0xF3,0x4B,0x18,0xF2,0x4A,0x01, + 0xB0,0x14,0x80,0x1E,0xD2,0x98,0xC7,0xC8,0x90,0x4D,0x8C,0x14,0x32,0x4A,0x89,0x01, + 0x34,0x5A,0xF8,0x4B,0xEC,0x33,0x16,0x72,0xED,0x26,0x40,0xB0,0x07,0xB8,0xCB,0xB0, + 0x43,0x48,0xC4,0x88,0xA8,0x0B,0x0E,0x01,0x24,0x0C,0x22,0x0C,0xBC,0x0B,0xBA,0x0B, + 0x2A,0x0C,0xF2,0x70,0x3A,0x33,0x38,0x0B,0xF0,0xCB,0x18,0x01,0x30,0x62,0x9C,0x0C, + 0x98,0x04,0x08,0x01,0x32,0x11,0xF1,0x8A,0xFC,0x32,0x14,0x72,0xD2,0x0E,0x20,0x0C, + 0x01,0x27,0x30,0x21,0xFC,0x32,0x14,0x72,0xEC,0x06,0x20,0x0C,0xF3,0x0C,0xE0,0xB0, + 0x90,0xB5,0xB5,0x0C,0xE8,0x73,0xFB,0x0C,0x10,0xF2,0xC5,0x0E,0x30,0x01,0xB0,0x0C, + 0xF0,0x70,0xD0,0x06,0x13,0x72,0x2A,0x32,0xE8,0x6E,0x4A,0x01,0xEA,0x1E,0xF8,0x0B, + 0xE2,0x48,0xBA,0x0B,0x04,0xDF,0xF8,0x0B,0x3A,0xF1,0xE0,0x48,0xB9,0x0B,0x34,0x0A, + 0xCE,0x01,0xF9,0x7A,0xEA,0x4B,0x03,0x48,0xD0,0x30,0x0B,0x01,0xF0,0x8A,0x33,0x01, + 0xFD,0x32,0x15,0xBA,0xED,0x5E,0x10,0x8A,0xEB,0x4E,0xC0,0xC8,0x04,0xB0,0xDB,0x48, + 0x93,0x4D,0x28,0x0A,0xE8,0x1E,0xC8,0x04,0xE4,0x48,0x92,0x4D,0x88,0x04,0x30,0xB2, + 0xF0,0x01,0x09,0xF1,0xF0,0x8A,0x3B,0xE1,0xF8,0xBA,0x4F,0x01,0xD2,0x06,0x10,0x4A, + 0x78,0x01,0xD0,0x06,0x16,0xFA,0xCB,0x48,0x90,0x4D,0x88,0x1C,0xE8,0x4B,0x33,0x01, + 0x06,0x78,0xDA,0x88,0xFE,0x72,0xFC,0x8A,0x70,0x01,0xD0,0x06,0x10,0xB2,0x4B,0x01, + 0xD2,0x06,0x10,0x4A,0xC0,0x88,0x93,0x4D,0x28,0x0A,0xEB,0x3E,0xF4,0x1C,0xC8,0x48, + 0x85,0x48,0x14,0x8A,0xD2,0x16,0xE0,0xD8,0x90,0xDD,0x00,0x27,0x6C,0x0C,0x12,0xCA, + 0xD2,0x06,0x28,0x1C,0x18,0x01,0xC8,0x14,0xE4,0x20,0xE5,0x90,0xF0,0x48,0x22,0x48, + 0x60,0x48,0x88,0x14,0x8A,0x6E,0x4C,0x62,0xF8,0x23,0x40,0x53,0x48,0x4A,0x1A,0x11, + 0x44,0x4B,0x90,0x01,0x88,0x01,0x61,0x09,0x88,0x9E,0x20,0x41,0xB0,0x23,0x3A,0x01, + 0xBA,0x3B,0xE6,0x63,0x62,0x41,0xC8,0x56,0x20,0x21,0xF9,0x22,0x33,0x32,0x13,0xB2, + 0x12,0xA2,0xED,0x26,0xCB,0xA3,0x3A,0x20,0xA8,0x0E,0xB8,0x1B,0x00,0xFF,0xB9,0x3B, + 0x00,0xEF,0x61,0x11,0x8A,0x66,0xF9,0x23,0x60,0x11,0xC8,0xC6,0x20,0x21,0xF9,0x22, + 0x34,0x11,0xF9,0x32,0x60,0x01,0xD0,0x06,0x13,0x22,0x23,0x22,0x10,0x32,0xED,0x76, + 0x20,0xF9,0xB8,0x22,0x60,0x01,0xD0,0x0E,0x26,0x01,0xB8,0x23,0xFB,0x23,0xE6,0x20, + 0x96,0x25,0xBB,0x23,0x61,0x11,0xE8,0x16,0x20,0x01,0xB8,0x23,0x00,0x77,0x20,0xF9, + 0xB8,0x22,0x60,0x01,0xEB,0x0E,0xF0,0x20,0xBE,0x23,0xFE,0x23,0xF3,0x20,0x93,0x25, + 0xBD,0x23,0xE6,0x30,0xD0,0x9E,0x20,0x19,0xB0,0x23,0x22,0x01,0xB8,0x23,0x06,0x77, + 0xE1,0x63,0x32,0x32,0xF2,0x21,0x71,0x01,0x9B,0x1E,0x38,0x30,0x78,0xB0,0x73,0x19, + 0x8B,0x2E,0x60,0x21,0x90,0x0E,0x20,0x21,0x00,0x07,0x20,0x09,0xB2,0x23,0xCA,0x93, + 0x38,0xA0,0x86,0xBE,0x38,0xA0,0xA8,0xAE,0x11,0x61,0xA9,0x01,0xF7,0x12,0xC4,0x63, + 0x11,0x12,0xD5,0x0E,0x16,0x11,0xE9,0x23,0xF3,0x12,0x44,0x20,0x10,0x12,0xED,0xDE, + 0xC2,0x53,0xE0,0x90,0x90,0x95,0x86,0x53,0x50,0x41,0xC8,0x0E,0x16,0x09,0x98,0x53, + 0xB0,0x1B,0x02,0x9F,0x38,0x90,0xAA,0x8E,0xF0,0x13,0x56,0x01,0x88,0x76,0xD0,0x04, + 0x50,0x09,0xC8,0x4E,0x14,0x21,0xF1,0x12,0x20,0x11,0xF9,0x22,0x50,0x01,0xD0,0x06, + 0x13,0x92,0x22,0x12,0x17,0xA2,0xDC,0x1E,0x10,0x01,0x80,0x53,0xE9,0x0B,0x16,0x11, + 0xF2,0x12,0x04,0x58,0xC4,0x58,0x16,0xD2,0xE8,0x16,0x88,0x90,0xC6,0x48,0xAC,0x0B, + 0xE8,0xFD,0x07,0x00,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0xA8,0x85,0x40,0x52, + 0xE0,0x03,0x44,0x51,0x8E,0x7E,0x00,0x41,0x82,0x1F,0xC0,0xF7,0x60,0x32,0x00,0x01, + 0xA1,0x01,0x8F,0x03,0x81,0x0F,0xF8,0xF7,0x80,0x07,0xC8,0x97,0x01,0x19,0x88,0x03, + 0x00,0x01,0x80,0x17,0xC0,0x4F,0xEE,0x85,0x00,0xC0,0x03,0x01,0xAC,0x85,0x47,0x02, + 0x80,0x4D,0x44,0x03,0x50,0xFA,0xFB,0x0B,0x88,0x1C,0x40,0x8B,0xF0,0x23,0x36,0x52, + 0x94,0x01,0x54,0x9B,0x57,0x93,0x8E,0x01,0xA0,0x24,0x98,0x14,0x96,0x0C,0xC8,0x4B, + 0x48,0x01,0x80,0x26,0xC8,0x88,0x88,0x0C,0x5E,0x0C,0xC6,0x40,0x80,0x14,0x30,0x01, + 0x03,0x07,0x4F,0xAA,0x04,0x01,0x00,0x43,0x10,0xF9,0xC9,0x1C,0xC7,0x14,0xB8,0xFF, + 0xE4,0x87,0x26,0x01,0x31,0x2A,0x31,0x3A,0x46,0x82,0x0B,0x23,0x30,0x92,0x49,0x2D, + 0x47,0x35,0xB8,0xFF,0xF3,0x7F,0x40,0x5A,0x47,0x03,0x80,0x01,0xC8,0x03,0x42,0x31, + 0x83,0xF6,0x33,0x5A,0x00,0xC1,0xF0,0xC2,0x40,0xE1,0xD1,0x1E,0x68,0x41,0x80,0x4E, + 0x18,0x62,0x05,0x1F,0x78,0x01,0x8C,0x0E,0x30,0x7A,0x01,0x1F,0x41,0x68,0x1B,0x62, + 0x6F,0x01,0x88,0x0E,0xC8,0x1C,0xC0,0x14,0xB8,0xFF,0xEF,0x8F,0x30,0xEA,0x21,0x01, + 0x01,0x0F,0x18,0xE2,0x40,0xF8,0x7B,0x01,0x8A,0xDE,0x47,0xCA,0x42,0x03,0x80,0x01, + 0x59,0x04,0xC4,0x41,0x90,0x3D,0x00,0xC7,0x45,0xC2,0x1A,0x62,0x09,0x23,0x36,0x92, + 0x48,0x2D,0x40,0x35,0xBE,0xFF,0xEF,0xF7,0x40,0x92,0x42,0x03,0x82,0x01,0xCF,0x03, + 0x42,0x31,0x80,0x6E,0x30,0x5A,0x03,0xA1,0xF5,0xC2,0x10,0xC2,0xE9,0x06,0x18,0x62, + 0x60,0x41,0x90,0x0E,0x20,0x41,0x00,0x17,0x40,0x68,0x6B,0x01,0x88,0x26,0xC7,0x0C, + 0x14,0xF9,0xA9,0x22,0xC8,0x1C,0xC0,0x14,0xBB,0xFF,0xE7,0xDF,0x46,0x3A,0x0A,0x23, + 0x42,0x03,0x66,0x22,0x90,0x05,0x3C,0x10,0x78,0x90,0x48,0x00,0x19,0x12,0x42,0x03, + 0xE2,0x0B,0x18,0x52,0xE2,0x0B,0xC2,0x80,0xF7,0x00,0xBC,0xFF,0xE6,0xF7,0x96,0x05, + 0x48,0xDA,0x81,0x44,0x42,0x43,0x80,0x01,0x58,0x14,0xC4,0x44,0x00,0x00,0xC2,0x80, + 0x90,0x3D,0x00,0x19,0x81,0x3C,0x60,0xB2,0x44,0x03,0x81,0x01,0xC8,0x03,0x4A,0x00, + 0x40,0x09,0x88,0x2E,0xE6,0x80,0x93,0x15,0x08,0x01,0x00,0x09,0x80,0x1F,0xC0,0x27, + 0x30,0x92,0x09,0x01,0x00,0x09,0x80,0x17,0xF9,0xFF,0x37,0x8A,0x00,0x11,0x80,0x17, + 0xF1,0xCF,0x43,0x62,0x44,0x03,0x80,0x01,0x12,0x01,0x40,0x03,0x30,0x8A,0x00,0x07, + 0x00,0x67,0x82,0x17,0xE8,0x8F,0x0D,0x01,0x00,0x19,0x80,0x17,0xF0,0x5F,0x0B,0x09, + 0x30,0x92,0x31,0x42,0x87,0x17,0xF8,0x47,0x44,0x03,0x81,0x01,0xC8,0x03,0x4A,0x00, + 0x40,0x09,0x88,0x2E,0xE6,0x80,0x93,0x15,0x08,0x09,0x30,0x42,0x86,0x17,0xF8,0xE7, + 0x29,0x01,0x30,0x62,0x00,0xE7,0x40,0xDA,0x00,0x08,0x43,0x03,0x82,0x01,0x44,0x03, + 0xD5,0x02,0x12,0xC2,0xEE,0x3E,0xD8,0x00,0x90,0x05,0xCC,0x44,0xBC,0xFF,0xE7,0x1F, + 0xE4,0x00,0x94,0x05,0x03,0x17,0xE0,0x68,0x90,0x6D,0x05,0x01,0xC8,0x14,0xE8,0x4A, + 0x10,0x0A,0x94,0x06,0x30,0x42,0xD0,0x40,0xC8,0x14,0xA8,0x42,0xE7,0x20,0x93,0x25, + 0xC4,0x1C,0x10,0x22,0x9D,0xFE,0xE6,0x68,0x10,0x2A,0x94,0x2E,0xC2,0x3C,0xF0,0x00, + 0x30,0x00,0x70,0x00,0x84,0x3C,0x88,0xF6,0xC8,0x1C,0xC0,0x14,0xC3,0x00,0xE2,0xB0, + 0x90,0xB5,0x87,0x14,0xC4,0x24,0x10,0x32,0x90,0x06,0x38,0xD7,0x87,0x4D,0xE8,0x85, + 0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0x10,0x00,0x00,0x42,0x00,0x01,0x00,0x42, + 0xA9,0xC5,0x47,0x6A,0x40,0x0B,0x10,0x11,0x18,0x8A,0x00,0x0B,0x21,0x01,0x68,0x5A, + 0x01,0x37,0x30,0x12,0x08,0x09,0x00,0x01,0x84,0x17,0xF8,0x77,0xE7,0x20,0x93,0x25, + 0x42,0x43,0xE9,0x0B,0xEA,0x03,0xC0,0x00,0x17,0x02,0xC5,0x96,0x70,0x22,0x09,0x01, + 0x47,0x83,0x81,0x01,0x88,0x0B,0x06,0x19,0x87,0x17,0xE8,0xE7,0x44,0x43,0x81,0x01, + 0xC8,0x03,0x4A,0x00,0x40,0x11,0x88,0x3E,0x40,0x83,0x09,0x09,0x86,0x01,0x8F,0x0B, + 0x08,0x01,0x00,0x19,0x87,0x17,0xE8,0x77,0x7F,0xD2,0x40,0xC3,0x91,0x25,0x44,0x43, + 0x84,0x01,0xCC,0x03,0x38,0x00,0xA8,0x36,0x43,0x8B,0x41,0x00,0x48,0x00,0xE8,0x4B, + 0x08,0x00,0x18,0x42,0x01,0xC3,0x47,0x83,0x0F,0x01,0x80,0x01,0x88,0x0B,0x06,0x11, + 0x83,0x17,0xF0,0x17,0xBD,0xFF,0xF7,0x97,0x00,0x01,0x80,0x17,0xF1,0xEF,0x42,0x43, + 0x82,0x01,0xCC,0x03,0x48,0x00,0x40,0x11,0x89,0x5E,0x40,0x83,0x0F,0x09,0x80,0x01, + 0x88,0x0B,0x06,0x11,0x82,0x17,0xF0,0x87,0xBD,0xFF,0xF7,0x07,0x00,0x01,0x80,0x17, + 0xF7,0x5F,0x02,0xE3,0xE8,0xC5,0x07,0x00,0x18,0x00,0x04,0x42,0x00,0x40,0x00,0x01, + 0x00,0x20,0x00,0x01,0x00,0x01,0x00,0x42,0xA8,0x85,0x48,0x9A,0x10,0x41,0x45,0x4B, + 0x1A,0x01,0xC0,0xA2,0x12,0xA1,0xA1,0x9A,0x8C,0x01,0xCF,0x53,0x44,0x98,0x3A,0x90, + 0x06,0xD8,0x7A,0x90,0x1E,0x9A,0x90,0xD5,0x18,0xE9,0x07,0xD2,0x88,0x53,0x84,0x07, + 0xD8,0x5F,0x07,0x01,0x50,0x4A,0x00,0x3F,0xC1,0x1B,0x31,0x0A,0xE2,0x20,0xE3,0x00, + 0x34,0xD8,0x74,0xD8,0x84,0x5B,0x90,0x05,0x44,0x8B,0xE8,0x5B,0xEA,0x4B,0x1E,0xCA, + 0x17,0x0A,0xC4,0x8E,0xE8,0x85,0x00,0x00,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01, + 0xAF,0xFD,0x47,0xD2,0x80,0x3D,0x46,0x03,0x14,0x09,0xE8,0x0B,0xE9,0x23,0x5E,0x45, + 0x81,0xD3,0x88,0xBC,0xA2,0xC4,0xE1,0x48,0x81,0xCB,0xCA,0xBC,0x81,0xCB,0xCC,0xBC, + 0x82,0x01,0xF2,0x48,0x87,0xCB,0x4E,0x92,0x18,0x11,0x40,0x4B,0x8C,0x01,0xCF,0x53, + 0x1C,0xD2,0x88,0x53,0xF9,0x03,0x4C,0xAD,0x41,0x00,0x82,0xCC,0x00,0x01,0x30,0x12, + 0x08,0x2E,0x80,0xFC,0xC2,0x54,0xCA,0x84,0x92,0x05,0x82,0x34,0xC0,0x4C,0x4A,0x11, + 0x92,0x05,0x82,0x2C,0x80,0xA6,0x13,0x01,0x4C,0x45,0xB1,0x4A,0x8F,0x24,0x4A,0x2A, + 0x04,0x01,0xB0,0x4A,0x8F,0x1C,0x4A,0x1A,0xEC,0x48,0xB0,0x4A,0x8C,0x14,0x02,0x08, + 0xC6,0x48,0x94,0x4D,0x62,0x95,0xD9,0x54,0xA1,0x1A,0x63,0x7D,0xDB,0x4C,0xA2,0x1A, + 0xD9,0x1C,0x9A,0x34,0xD9,0x14,0x9A,0x2C,0xD9,0x24,0x9A,0x24,0x40,0x09,0x88,0x5E, + 0xDA,0x34,0x11,0xDA,0x91,0xDD,0x9A,0x34,0xDA,0x2C,0x11,0xDA,0x91,0xDD,0x9A,0x2C, + 0xDA,0x24,0x11,0xDA,0x91,0xDD,0x9A,0x24,0xDA,0x3C,0xE2,0x34,0x32,0xE2,0xDC,0x44, + 0x9A,0x5C,0xD9,0x2C,0xE9,0x2C,0xF1,0x24,0xC9,0xD8,0xEA,0x34,0x93,0xDD,0xCA,0x20, + 0xEB,0x5C,0x91,0x25,0xC9,0x68,0xAD,0x5C,0x5B,0x01,0xD8,0x4E,0xED,0xC4,0x11,0x5A, + 0xD0,0x36,0x63,0x01,0xD9,0x26,0xEB,0xBC,0x13,0x62,0xD5,0x0E,0xE9,0x5C,0xC1,0x6B, + 0x49,0x68,0x8D,0xEE,0x33,0x32,0xFB,0xBA,0xF3,0x24,0x01,0xB0,0x23,0xA2,0x35,0x32, + 0xF9,0xAA,0xF3,0xCC,0x12,0xAA,0xED,0x9E,0xF0,0x84,0x72,0x09,0x8B,0x0E,0xD9,0xF0, + 0x90,0xB5,0xB1,0x9C,0xF8,0x3C,0x32,0x01,0xFD,0xF2,0x15,0x72,0xD9,0x06,0x30,0xAA, + 0x83,0x68,0x05,0x68,0xFB,0x9C,0x10,0x72,0x12,0xF2,0xE5,0x0E,0x73,0x95,0xA1,0xA2, + 0x73,0x7D,0xA1,0x9A,0x01,0xB0,0x7A,0xAD,0xC9,0xB0,0xE7,0xBA,0xE1,0xF8,0xA3,0xBA, + 0xF3,0xFC,0xE0,0xB0,0x90,0xB5,0xB7,0xFC,0xF5,0x9C,0x10,0xAA,0xD1,0xD6,0x05,0x7F, + 0x09,0x07,0x6B,0x95,0xA1,0x62,0x6B,0x7D,0xA2,0x5A,0x03,0xA8,0x75,0xAD,0xC9,0x68, + 0xE3,0x72,0xE1,0xB0,0xA0,0x72,0xE9,0xFC,0xE7,0x68,0x93,0x6D,0xAD,0xFC,0x38,0x4F, + 0xE9,0x5C,0xC1,0x6B,0x48,0x68,0x6D,0x19,0x8A,0x76,0x00,0xB0,0x7F,0xAD,0xC9,0xB0, + 0xE0,0xB2,0x71,0x09,0xC2,0x46,0xC0,0x44,0x08,0x01,0xC6,0x03,0x1A,0x42,0xC8,0x44, + 0x80,0x43,0x00,0x01,0x87,0x5D,0xEA,0x85,0x68,0x11,0x88,0x4E,0x6B,0x95,0xA1,0x62, + 0x63,0x7D,0xA1,0x1A,0x01,0x98,0x4A,0xAD,0xC0,0xC8,0xE2,0x5A,0xE0,0xD8,0xA2,0x5A, + 0xE6,0x00,0x92,0x05,0x40,0x11,0x90,0x06,0x3A,0x0F,0xE3,0x90,0x90,0x95,0x56,0x21, + 0x92,0x06,0x38,0x8F,0x01,0x01,0x80,0x64,0xC0,0x84,0x42,0x09,0x88,0xF6,0x23,0x01, + 0x01,0x01,0x80,0x74,0x43,0xAD,0x01,0x08,0xC2,0x40,0x80,0x0C,0xC4,0x74,0x01,0x00, + 0xCE,0x00,0x90,0x05,0x81,0x4C,0xC9,0x74,0xC2,0x0C,0xE2,0x2A,0x68,0x09,0xC0,0x26, + 0xC2,0x64,0xE1,0x00,0x91,0x05,0x86,0x64,0x00,0xA7,0x4F,0x09,0x88,0x0E,0x60,0x01, + 0x89,0xD6,0x0F,0x81,0x47,0x45,0xB8,0xFF,0xD2,0x27,0xC6,0x4C,0x82,0x3C,0xC0,0x54, + 0x82,0x34,0xC0,0x3C,0x82,0x0C,0xC0,0x44,0x85,0x04,0xE0,0x00,0x3B,0x00,0x4C,0xCA, + 0x78,0x00,0xB4,0x52,0x30,0xA2,0xEC,0x50,0xB1,0x9A,0x98,0x2C,0x58,0x45,0xB1,0xC2, + 0xB8,0x4A,0x88,0x24,0xB8,0x8A,0x88,0x1C,0xB8,0xCA,0x88,0x14,0xC8,0x74,0x49,0x09, + 0x88,0x5E,0xC8,0x24,0x12,0x4A,0x92,0x4D,0x88,0x24,0xC8,0x1C,0x12,0x4A,0x92,0x4D, + 0x88,0x1C,0xC8,0x14,0x12,0x4A,0x92,0x4D,0x88,0x14,0x08,0x01,0xE0,0x68,0x33,0x5A, + 0xA8,0xEC,0x89,0x2C,0x00,0xD7,0x5D,0x61,0x98,0x66,0xC8,0x24,0xC1,0x34,0xD0,0x4C, + 0xD1,0x00,0x4A,0x95,0xA0,0x42,0xCC,0x1C,0xC1,0x3C,0xD0,0x4C,0xD1,0x00,0x4A,0x7D, + 0xA5,0x42,0x04,0x7F,0xD0,0x0C,0x08,0x01,0xF4,0x8A,0x02,0xF0,0x54,0x45,0x88,0x8A, + 0x09,0x01,0x88,0x6C,0xCA,0x3C,0x90,0x4D,0x88,0x04,0xCA,0x34,0x91,0x4D,0x8A,0xFC, + 0x00,0x5F,0x48,0x09,0x8B,0x4E,0x30,0x0A,0x12,0x4A,0x92,0x4D,0x31,0x62,0xCC,0x2C, + 0x12,0x4A,0x92,0x4D,0x12,0x02,0x92,0x05,0x88,0x2C,0xE9,0x0C,0xA9,0x1C,0xD1,0xFC, + 0xE9,0x04,0xA8,0x5C,0x02,0x28,0xCA,0x04,0xA8,0xF4,0x01,0x07,0x01,0xE7,0xEE,0x2C, + 0xFA,0x1C,0xC9,0x48,0xEA,0xF4,0x91,0x4D,0xC9,0x68,0xAF,0x1C,0xEB,0x5C,0x21,0x12, + 0xC2,0x68,0x91,0x95,0xA8,0x5C,0x49,0x01,0xD9,0xBE,0xE8,0xC4,0x10,0x4A,0xD5,0xA6, + 0x50,0x01,0xD8,0x96,0xED,0xBC,0x11,0x52,0xD1,0x7E,0xF8,0x1C,0x2B,0x01,0xF8,0xEA, + 0xF9,0x5C,0xC1,0xFB,0x48,0xF8,0x8D,0x46,0xFD,0xCC,0x11,0xEA,0xE8,0x2E,0x78,0x45, + 0xCB,0xFA,0xCD,0xE8,0x7D,0x45,0x88,0xEA,0x39,0xBF,0xCE,0x6C,0xE6,0x48,0x92,0x4D, + 0x88,0x6C,0x49,0x11,0x98,0xEE,0x5D,0x01,0x81,0x1E,0x6A,0xAA,0x55,0x45,0xC0,0x88, + 0x42,0x6B,0xC9,0x01,0x5A,0x4B,0xAE,0x01,0xC0,0x6B,0x37,0x7A,0xCA,0x92,0xCC,0x48, + 0x11,0x8A,0x94,0x96,0xC8,0x2C,0x48,0x09,0x88,0x9E,0xD1,0x24,0xC9,0x34,0xD8,0x4C, + 0xD1,0x48,0x54,0x95,0xA0,0x8A,0xDE,0x1C,0xD1,0x3C,0xE8,0x4C,0xD1,0x90,0x5E,0x7D, + 0xA8,0xD2,0xEA,0x14,0xD8,0x04,0x38,0x01,0xD9,0xE8,0xDA,0x2C,0xD3,0x90,0x36,0x1A, + 0xD2,0x48,0x96,0x5D,0xD2,0x48,0x91,0x95,0x30,0x01,0x54,0x01,0xD9,0x56,0xE8,0xC4, + 0x10,0x52,0xD5,0x3E,0x58,0x01,0xD8,0x2E,0xED,0xBC,0x11,0x5A,0xD0,0x16,0xC0,0x6B, + 0x18,0xAA,0x81,0x6B,0xEB,0x2C,0x21,0x1A,0xCB,0x90,0xE2,0xE8,0xC7,0x48,0x90,0x7D, + 0x92,0x95,0x92,0xDD,0x7F,0x11,0xC8,0x46,0x05,0xE7,0x10,0xD2,0x90,0x0E,0x08,0x09, + 0x88,0x2C,0xD0,0x24,0xCC,0x34,0xC0,0x48,0x90,0x4D,0x8E,0x34,0xD0,0x1C,0xC8,0x3C, + 0xC6,0x48,0x94,0x4D,0x88,0x3C,0xC8,0x14,0xD2,0x0C,0x00,0x48,0xC0,0x48,0x8C,0x0C, + 0xD0,0x14,0xC8,0x04,0xC2,0x48,0xE4,0xD8,0x90,0xDD,0x8E,0x04,0xCC,0xEC,0x11,0x5A, + 0x92,0x06,0x38,0x07,0xC2,0x74,0xE1,0x00,0x91,0x05,0x86,0x74,0x40,0x11,0x90,0x06, + 0x33,0xA7,0xE7,0x20,0x90,0x25,0x67,0x21,0x97,0x36,0x30,0x4F,0x00,0x40,0x00,0x01, + 0x00,0x20,0x00,0x01,0x28,0xA2,0x03,0x00,0xC0,0x64,0x41,0x41,0x88,0xE6,0x11,0x01, + 0x78,0x95,0x01,0x17,0x01,0x41,0x80,0x64,0x3F,0xCF,0x4F,0x0A,0x00,0x01,0xE8,0x58, + 0xB4,0x4A,0xB4,0xF2,0x33,0x62,0x34,0x0A,0x30,0x9A,0x41,0x09,0x8A,0x1E,0x10,0x4A, + 0x12,0xDA,0x92,0x4D,0x92,0xDD,0xE2,0x4C,0xC2,0x18,0xE7,0x54,0x93,0xDD,0xC2,0x08, + 0x94,0x65,0x02,0x08,0xC6,0x48,0x94,0x4D,0x58,0x01,0xD8,0x4E,0xED,0xC4,0x11,0x5A, + 0xD0,0x36,0x60,0x01,0xD9,0x26,0xE8,0xBC,0x10,0x62,0xD5,0x0E,0xA0,0xE2,0x03,0x17, + 0xDB,0x54,0xA2,0xDA,0xDA,0x4C,0xE2,0x00,0x66,0x7D,0x91,0x05,0xA0,0x1A,0x43,0x11, + 0x9A,0xCE,0xE6,0x90,0x90,0x95,0x56,0x21,0x99,0x7E,0x5E,0x85,0xD0,0xC3,0xA0,0xC3, + 0x58,0x45,0xF9,0xC3,0x58,0x85,0x89,0xC3,0x58,0x85,0xD1,0xC3,0xA1,0xC3,0x58,0x45, + 0xF9,0xC3,0x58,0x85,0x88,0xC3,0x00,0x01,0x80,0xE4,0x80,0xEC,0x86,0xF4,0x40,0x0A, + 0x40,0x0B,0x00,0x01,0x8E,0x01,0xFA,0x4B,0x88,0xCC,0x79,0xA5,0x06,0x18,0xCE,0xD0, + 0x0A,0x01,0x00,0x20,0x93,0xE4,0xC1,0x10,0x91,0x95,0x6E,0x95,0xF5,0xE4,0xE1,0x6A, + 0xA1,0xAA,0x6B,0x7D,0xE1,0x52,0xED,0xE4,0xC2,0x68,0xE3,0x48,0x91,0x4D,0x8E,0x53, + 0x4F,0x19,0x98,0x86,0x40,0x09,0x80,0x0E,0x40,0x19,0x88,0x6E,0xD1,0xE4,0xE9,0xE4, + 0xE0,0xCA,0xCF,0x93,0xC7,0x6B,0xA5,0xEA,0xD9,0xE4,0xE1,0xE4,0xC9,0xDB,0x8C,0x1B, + 0xDC,0xE4,0x81,0xCB,0xCC,0xE4,0x89,0x53,0x09,0x09,0x88,0x0C,0x09,0x01,0x88,0x74, + 0xD1,0x74,0xC9,0xE4,0xDC,0x74,0xE1,0x4A,0xD1,0xE4,0xE9,0x74,0xC2,0x90,0xC6,0xA3, + 0xCA,0x9B,0xC8,0x93,0x6D,0x01,0x30,0x22,0x91,0x14,0x89,0x0E,0x40,0x01,0x80,0x0E, + 0x40,0x19,0x88,0x5E,0x28,0x0A,0x9B,0x4E,0x11,0x09,0x90,0x04,0x40,0x01,0x88,0x16, + 0xF1,0x10,0x92,0x0C,0x00,0xF7,0x10,0x09,0x90,0x0C,0x01,0xCF,0x40,0x09,0x80,0x0E, + 0x40,0x11,0x88,0x56,0x28,0x0A,0xC3,0x46,0x11,0x09,0x90,0x04,0x40,0x09,0x88,0x16, + 0xF1,0x10,0x94,0x0C,0x00,0xA7,0x10,0x09,0x00,0x3F,0x10,0x01,0x90,0x04,0x01,0x2F, + 0x11,0x09,0x90,0x04,0x47,0x11,0x90,0x36,0xF1,0x90,0x94,0x0C,0x40,0x01,0x80,0x0E, + 0x40,0x19,0x88,0x0E,0x2B,0x0A,0x93,0x1E,0x40,0x09,0x80,0x0E,0x43,0x11,0x88,0x56, + 0x2B,0x0A,0xC3,0x46,0x01,0xE7,0x92,0x54,0x92,0x55,0x92,0xE5,0x94,0x3C,0x51,0x32, + 0xF0,0xBC,0x41,0xAB,0x33,0x12,0x19,0x92,0x31,0x72,0xF9,0x3C,0xB1,0x01,0xAC,0xDC, + 0x95,0xD4,0x51,0xAB,0xC6,0x50,0xCD,0x90,0x90,0x5C,0xC1,0x93,0x30,0xA8,0x32,0xBA, + 0xA1,0xB6,0xD1,0xD4,0xEA,0x3C,0x01,0x90,0x02,0x68,0xCB,0x90,0x41,0xB3,0xEF,0xCC, + 0xF5,0x92,0x15,0x52,0xD1,0x26,0xE8,0x64,0x68,0x41,0x88,0x96,0x50,0x01,0xD8,0x86, + 0x48,0xE8,0x87,0x06,0x80,0x90,0xEA,0xE4,0xF5,0xF4,0xC0,0x68,0xA9,0xE4,0xE8,0x3C, + 0x1D,0xAA,0xCA,0x68,0xA8,0xF4,0xE8,0xEC,0x1A,0x12,0xCB,0x90,0x97,0xEC,0x48,0xD0, + 0x89,0xB6,0xD0,0xDC,0xEA,0xFC,0x90,0x01,0xC5,0x93,0x12,0x52,0x30,0xD2,0xC1,0x0E, + 0x28,0x01,0x06,0x07,0x29,0x01,0x1A,0x52,0xE9,0x5C,0x81,0x53,0xD0,0x04,0x51,0x09, + 0x8A,0x36,0xD0,0x4C,0x10,0xA2,0x84,0x1E,0xD5,0x0C,0xC1,0x10,0x95,0xA5,0x3A,0xB7, + 0x28,0x0A,0x8B,0x16,0xD4,0x14,0x11,0x9A,0x81,0xBE,0xD0,0x54,0x50,0x01,0x88,0x4E, + 0x28,0x0A,0xCB,0x0E,0xF0,0x48,0x02,0x17,0x28,0x0A,0x93,0x0E,0xE6,0x48,0x92,0x4D, + 0x15,0x09,0x38,0x07,0xD4,0x14,0x11,0x9A,0xCA,0x0E,0xF0,0xD8,0x04,0x17,0x10,0x9A, + 0x92,0x0E,0xE0,0xD8,0x90,0xDD,0x16,0x01,0x39,0xAF,0xCC,0x74,0xE6,0x48,0x92,0x4D, + 0x88,0x74,0x49,0x11,0x92,0x06,0x38,0x5F,0xE6,0x00,0x92,0x05,0x40,0x21,0x90,0x06, + 0x38,0xDF,0x20,0x01,0x60,0x01,0x88,0x56,0x52,0x5A,0xDA,0x54,0x42,0x93,0x68,0x5A, + 0x00,0xD8,0xFA,0xF4,0xCA,0xBC,0xC1,0x34,0xF2,0x6A,0x47,0xB3,0x02,0x4F,0x50,0x32, + 0x68,0x3A,0x42,0x9B,0xD0,0x4C,0xFA,0xEC,0x01,0x90,0xCA,0xC4,0xC5,0x2C,0xF2,0x6A, + 0x40,0xF3,0x44,0x01,0x82,0x16,0xF0,0x48,0x10,0x42,0x8C,0x96,0xD0,0x54,0x92,0x04, + 0x91,0x05,0x36,0x0A,0xDA,0x4C,0xD2,0x3C,0x87,0x07,0xE8,0x47,0x08,0xF9,0x8F,0x09, + 0x10,0x42,0xEC,0x0E,0x30,0x42,0x00,0x17,0x40,0x01,0xD0,0x06,0x02,0x01,0xC8,0x28, + 0x04,0x07,0xA8,0x01,0x10,0xC0,0xC9,0xE4,0xBA,0xFF,0xC7,0xEF,0xCB,0x00,0x1A,0x82, + 0x40,0x01,0xD0,0x06,0x01,0x01,0x48,0x82,0xA0,0x00,0x40,0x4B,0x60,0x01,0x88,0x56, + 0x44,0x54,0x10,0x12,0xD0,0x06,0x30,0x82,0x12,0xA1,0xC5,0x92,0x88,0x01,0xE9,0x4B, + 0x1A,0x31,0x18,0xCA,0x02,0x57,0x40,0x54,0x10,0x12,0xD4,0x06,0x35,0x82,0x10,0xA1, + 0xC1,0x92,0x8A,0x01,0xE8,0x4B,0x18,0x31,0x1C,0xCA,0xE2,0x48,0xE7,0x20,0x93,0x25, + 0x90,0x82,0x62,0x09,0xC9,0x36,0x5D,0x02,0x08,0xA1,0x41,0xC3,0xE0,0x52,0x50,0x01, + 0x89,0x3E,0x48,0x02,0xE2,0xE4,0xE0,0x68,0x10,0x62,0x95,0x06,0x32,0x0A,0x21,0xE1, + 0x90,0x0A,0x49,0xC2,0x80,0x01,0x44,0x4B,0xE2,0xE4,0xF0,0x4B,0x5E,0x03,0x02,0x62, + 0x90,0x0D,0x27,0x31,0x18,0x12,0xEB,0x90,0xA0,0x0A,0x44,0xC3,0x10,0xA1,0xE1,0x92, + 0x83,0x01,0x1C,0x12,0x58,0x03,0xEA,0x90,0x48,0x51,0x90,0x0E,0x0C,0x51,0xA0,0x0A, + 0x45,0xC3,0x10,0x81,0xC1,0x92,0x80,0x01,0xEA,0x03,0xC8,0x54,0x00,0x00,0xA2,0x8A, + 0x45,0xC3,0x10,0x81,0xC1,0x92,0x80,0x01,0xEA,0x03,0xC8,0x4C,0x02,0x00,0xE2,0x00, + 0xA0,0x8A,0x40,0xC3,0x80,0x01,0xE9,0x0B,0xE0,0x48,0xAA,0x0B,0xC7,0xFC,0x20,0xCF, + 0x28,0xA2,0x03,0x00,0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0x48,0x62,0x00,0x00, + 0x40,0x42,0x06,0x00,0xF8,0xF7,0x07,0x00,0xAB,0x8D,0x47,0xCA,0x80,0x75,0x44,0x0B, + 0x54,0xC2,0xEB,0x43,0x86,0x54,0xE8,0x5B,0x40,0x83,0x08,0x01,0x98,0x5C,0x88,0x14, + 0xEC,0x1B,0x86,0x01,0x50,0x0B,0x9C,0x4C,0x40,0x23,0x06,0x01,0x88,0x44,0x80,0x6C, + 0x00,0x07,0x36,0x12,0x08,0x01,0x00,0x09,0xBA,0xF7,0xFF,0xD7,0x50,0x6A,0x43,0x93, + 0x7A,0x9B,0x78,0x93,0x00,0xC2,0x18,0x01,0x02,0x8A,0x00,0xCA,0x00,0xC2,0x1A,0x42, + 0x88,0x3E,0xC0,0x54,0xCA,0x54,0x00,0x00,0xC8,0x20,0xC0,0x44,0xC0,0x00,0x82,0x44, + 0x00,0x27,0x05,0x01,0x00,0xEF,0xC4,0x44,0xC4,0x03,0x48,0x00,0x89,0xF6,0xF3,0x02, + 0xCC,0x4C,0x10,0x42,0xD8,0xD6,0xCB,0x54,0x32,0x5A,0x03,0x48,0x33,0x7A,0xD0,0x28, + 0x31,0x4A,0xC9,0x01,0x5C,0x74,0x0E,0xF4,0xC8,0xC8,0x31,0x5A,0x30,0xE2,0x35,0xFA, + 0x30,0x12,0xD9,0x64,0xD1,0x01,0xC9,0x01,0x59,0x01,0x40,0x74,0x36,0x5A,0x0B,0xF4, + 0x40,0x6C,0x13,0xEC,0x5A,0x94,0x16,0xD4,0x13,0xC4,0x44,0x14,0x16,0xD4,0x5E,0x4C, + 0x1B,0xCC,0x30,0x0A,0xD2,0x0A,0x1B,0xCC,0x44,0xCC,0x1B,0xCC,0x88,0x26,0x08,0x01, + 0x0A,0xCC,0x14,0xCC,0x18,0xCC,0x00,0x4F,0xC8,0x54,0xD0,0x64,0xF4,0x48,0x12,0x52, + 0x88,0x26,0x08,0x01,0x30,0x5A,0x13,0xCC,0x14,0xCC,0x1E,0xCC,0xC8,0x6C,0x48,0x01, + 0x8B,0x26,0x30,0x5A,0x0E,0xCC,0x0C,0xCC,0x10,0xCC,0x00,0x4F,0x30,0x52,0xC8,0x5C, + 0xF4,0x48,0x12,0x52,0x88,0x26,0x08,0x01,0x30,0x5A,0x1B,0xCC,0x1C,0xCC,0x1A,0xCC, + 0x30,0x5A,0x0B,0x61,0xF4,0xCA,0x12,0x0A,0xE0,0x26,0x0A,0x71,0xF4,0xCA,0x12,0x0A, + 0xD0,0x06,0x0A,0x81,0xF4,0xCA,0x12,0x0A,0xE0,0xE6,0x09,0x91,0xF4,0xCA,0x12,0x0A, + 0xD0,0xC6,0x09,0xB1,0xF4,0xCA,0x12,0x0A,0xE0,0xA6,0x09,0xC1,0xF4,0xCA,0x12,0x0A, + 0xE0,0x86,0x09,0xD1,0xF4,0xCA,0x12,0x0A,0xE0,0x66,0x09,0xE1,0xF4,0xCA,0x12,0x0A, + 0xE0,0x46,0xD1,0x74,0x91,0x04,0x30,0x02,0xD8,0x64,0xD0,0x6C,0xCF,0x44,0xB8,0xFF, + 0xD8,0x3F,0xCC,0x14,0x10,0x0A,0xD4,0x0E,0x90,0x05,0x84,0x14,0x47,0x2A,0x09,0x31, + 0x40,0x03,0xE0,0x4A,0x38,0x48,0xAC,0x56,0x80,0x01,0x01,0x07,0x00,0x97,0xE8,0x0B, + 0x40,0xFA,0x40,0x03,0x86,0x01,0xC3,0x03,0x10,0x0A,0x9C,0x5E,0x00,0x3F,0x48,0xEA, + 0x18,0xF1,0x47,0x4B,0x11,0x01,0x88,0x01,0xA7,0x5B,0x82,0x01,0x9F,0x13,0x00,0x81, + 0x80,0x6C,0x00,0x5F,0xC5,0x44,0xE0,0x20,0xE0,0x00,0x82,0x44,0xC2,0x64,0xE0,0x00, + 0x90,0x05,0xCE,0x54,0x84,0x64,0x10,0x42,0x92,0x06,0x38,0xE7,0xC2,0x6C,0xE0,0x00, + 0x90,0x05,0x86,0x6C,0xCC,0x5C,0x10,0x42,0x91,0x06,0x38,0xD7,0x42,0x6A,0x08,0x11, + 0x40,0x03,0xE0,0x52,0xCC,0x14,0x10,0x52,0x91,0x36,0x80,0x01,0x0A,0x09,0xB0,0x0A, + 0x48,0x81,0xD0,0x46,0xE0,0x48,0x02,0x2F,0x80,0x01,0x09,0x09,0xB0,0x0A,0x4A,0x41, + 0xD0,0x1E,0x08,0x01,0x80,0x0B,0x82,0x7D,0xEA,0x85,0xF7,0x48,0x38,0xD7,0x07,0x00, + 0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0xA8,0x85,0x40,0x4A,0x10,0x81,0x44,0x03, + 0x20,0x01,0xD0,0x92,0x37,0x8A,0xC8,0xF9,0xC8,0xA9,0x85,0x0E,0x20,0x09,0x00,0x27, + 0x81,0x17,0xD8,0xC7,0x40,0x01,0x80,0x06,0x21,0x11,0x30,0x02,0xE8,0x85,0x00,0x00, + 0x00,0x40,0x00,0x01,0xAF,0xF5,0x47,0xF9,0x82,0xF6,0x53,0x52,0x18,0x41,0x41,0x93, + 0x92,0x14,0x18,0xC2,0x94,0x01,0x5C,0x9B,0x58,0x93,0xC2,0xC0,0x1A,0x31,0x18,0xCA, + 0xC0,0x88,0x2A,0x11,0x22,0x01,0xF8,0x6A,0xF8,0x62,0x10,0x81,0x0C,0x71,0xF0,0x12, + 0xF2,0x0A,0x5A,0x1C,0xD5,0x50,0x35,0x22,0x33,0x72,0xD5,0x08,0xAA,0x06,0x10,0x4A, + 0x50,0x01,0xD0,0x06,0x14,0x92,0xC2,0x48,0x90,0x55,0x0C,0x31,0x22,0xF1,0xF0,0x0A, + 0xF8,0x22,0x30,0x41,0x3C,0x21,0xF9,0x32,0xF8,0x3A,0xDE,0x48,0xD8,0xA0,0x4F,0x01, + 0xD2,0x06,0x10,0x4A,0x60,0x01,0xD0,0x06,0x10,0x22,0xCB,0x48,0x90,0x7D,0x0C,0xC1, + 0x32,0xB1,0xF0,0x0A,0xFB,0x32,0x34,0xAA,0x33,0x22,0xD3,0x48,0xD8,0x20,0xAD,0x06, + 0x10,0x22,0x4B,0x01,0xD2,0x06,0x10,0x4A,0xC4,0x08,0x93,0x4D,0x89,0x04,0x48,0x52, + 0x00,0xA0,0x42,0x4B,0xCB,0xB0,0x88,0x01,0x57,0x64,0xCA,0xB0,0xA7,0x0C,0xC0,0x28, + 0xCF,0x60,0x1D,0x20,0xC1,0x3B,0x66,0x20,0x78,0x41,0x90,0xA6,0xE4,0x6B,0x12,0xAA, + 0x94,0x8E,0xC0,0x2B,0xCB,0x73,0xE2,0x68,0x10,0xAA,0x8D,0x66,0xF2,0x0C,0x40,0xA8, + 0x11,0xAA,0x95,0x56,0xF5,0x04,0x10,0xAA,0x90,0x3E,0xE9,0x0C,0x33,0x9A,0x00,0x68, + 0xCD,0x60,0x91,0x25,0x00,0x0F,0x79,0xA1,0x90,0xFE,0xF0,0x14,0x31,0x2A,0x43,0xB4, + 0x05,0x68,0xDB,0x68,0x4F,0xB8,0xD9,0xB0,0x68,0x01,0xD0,0x06,0x15,0x6A,0x13,0x72, + 0xE0,0x6E,0xF0,0x14,0x33,0xAA,0x43,0xB4,0x05,0x68,0xDB,0x68,0x4F,0xB8,0xD9,0xB0, + 0x68,0x01,0xD0,0x06,0x10,0x6A,0x03,0x07,0x05,0x4F,0x10,0x72,0xEC,0x2E,0xC0,0x2B, + 0xCB,0x73,0xE2,0x68,0x10,0xAA,0x95,0x06,0x44,0x98,0x12,0xD2,0xC8,0x0E,0x00,0x01, + 0xEC,0xF5,0xC7,0x13,0xCA,0x4B,0xE2,0x90,0x10,0x52,0x8C,0x06,0x18,0x24,0x02,0x09, + 0xE8,0xF5,0x07,0x00,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0x40,0x22,0x48,0x2A, + 0x44,0x03,0x10,0x42,0x80,0x0E,0x00,0x09,0x38,0x82,0x03,0x01,0x38,0x82,0x03,0x00, + 0x58,0x40,0x01,0x01,0xD2,0x2A,0x2D,0xD5,0x48,0x12,0x48,0x43,0x14,0x21,0x18,0x82, + 0x0B,0x43,0x38,0x82,0x68,0x07,0x00,0x07,0xAB,0x85,0x57,0x9A,0x80,0x4D,0x44,0x83, + 0xEC,0x0B,0xEE,0x23,0x40,0x8A,0x8B,0x0C,0x40,0x03,0x08,0x01,0x3A,0x0B,0x38,0x0B, + 0x86,0x01,0x1A,0x0C,0x30,0x42,0x88,0x24,0x00,0x1F,0x04,0x01,0x48,0x5A,0x83,0x1C, + 0x40,0x7B,0xD0,0x24,0x34,0x2A,0x00,0x61,0x1E,0x12,0xCB,0x02,0x04,0x90,0xC2,0x30, + 0x40,0x2A,0x43,0x03,0x82,0x3C,0x80,0x01,0x80,0x44,0x00,0xBF,0x01,0x01,0xF0,0x82, + 0xC8,0x1C,0xC0,0x48,0x90,0x4D,0x88,0x1C,0xCC,0x44,0xF8,0x4B,0x10,0x0A,0xD4,0x56, + 0x08,0x01,0x00,0x09,0xD7,0x24,0xB8,0xF7,0xE9,0x1F,0x7C,0xD3,0x78,0xDB,0x1B,0x82, + 0x19,0xCA,0x38,0xC3,0x3D,0xCB,0xE3,0xB0,0xE7,0x68,0x93,0x6D,0x17,0x2A,0x9D,0x2E, + 0xC4,0x3C,0x80,0x01,0xCE,0x03,0x3C,0x00,0x81,0x3E,0x32,0x0A,0xC7,0x1C,0xB8,0xF7, + 0xE8,0xA7,0x97,0x2D,0x01,0x00,0xD3,0xB8,0x80,0x58,0x0B,0x01,0x80,0x34,0x30,0x42, + 0x00,0x47,0x10,0x01,0xF5,0xD2,0xE5,0xF8,0x10,0xD2,0xEC,0x0E,0xE0,0x48,0x92,0x4D, + 0xE6,0x00,0x92,0x05,0x17,0x02,0x9D,0xA6,0xE1,0x48,0x32,0x42,0x19,0x42,0x32,0x0A, + 0xBE,0xF7,0xEF,0xDF,0x90,0x35,0xC0,0x34,0xD0,0xC8,0x11,0x01,0x00,0x17,0x01,0x01, + 0xF0,0x42,0x68,0x01,0xED,0x36,0x10,0x82,0xEC,0x0E,0xD8,0x00,0x00,0x2F,0x40,0x01, + 0xE8,0x46,0x00,0x37,0x10,0x42,0xD5,0x16,0xD8,0x00,0x92,0x05,0x00,0x17,0x40,0x01, + 0xD0,0x06,0x00,0x09,0x78,0xCA,0x31,0x1A,0x42,0xFB,0xB9,0x01,0x37,0xE2,0x5D,0xFC, + 0x40,0x01,0xD0,0x06,0x17,0xDA,0xC2,0xD8,0x37,0x3A,0x1B,0xDC,0x04,0x44,0xE0,0x48, + 0xE6,0x90,0x92,0x95,0x16,0x12,0x9D,0xD6,0x02,0x3F,0xB8,0x01,0xC7,0x1C,0x58,0xCC, + 0x40,0x01,0xD0,0x06,0x10,0x02,0xC2,0x40,0x18,0xC4,0xC7,0x24,0xE6,0x00,0x92,0x05, + 0x80,0x24,0xC8,0x0C,0x10,0x42,0x94,0x06,0x39,0xBF,0x43,0x3A,0x44,0x03,0x80,0x01, + 0xCC,0x03,0x3C,0x00,0xA8,0x2E,0x02,0x01,0x30,0x32,0x80,0x14,0x01,0xFF,0x49,0x1A, + 0x00,0x90,0x43,0x4B,0x04,0x01,0x88,0x01,0x40,0x4B,0x36,0x1A,0xC3,0x50,0x04,0x08, + 0x30,0xAA,0x88,0x2C,0x00,0x5F,0x08,0x01,0xF0,0x8A,0xFA,0x14,0xC0,0x00,0x92,0x05, + 0x10,0xCA,0xED,0x06,0x88,0x14,0xC8,0x2C,0xC2,0x50,0xE4,0xD8,0x90,0xDD,0xCE,0x0C, + 0x17,0x5A,0x9C,0x86,0xBB,0xF7,0xEF,0xCF,0x90,0x1D,0xC0,0x14,0x84,0x00,0x12,0xC2, + 0xEA,0x2E,0x18,0xDA,0x00,0xC0,0xCA,0x14,0xBB,0xF7,0xEF,0x7F,0x90,0x1D,0x10,0x01, + 0x00,0x87,0x08,0x01,0xF6,0x4A,0xD3,0x40,0x90,0x05,0x48,0x01,0xD2,0x06,0x10,0x4A, + 0xF0,0x38,0xD0,0x06,0x15,0x3A,0x12,0xCA,0xE9,0x06,0x00,0x44,0xC2,0x2C,0xC8,0x28, + 0xE6,0x90,0x92,0x95,0xC4,0x0C,0x10,0x12,0x9B,0x5E,0xE7,0xB0,0x95,0xB5,0x17,0x32, + 0x98,0xEE,0x85,0x4D,0xE8,0x85,0x07,0x00,0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01, + 0x40,0x4A,0x58,0x0B,0x10,0x21,0x18,0x8A,0x18,0x0B,0x58,0x0B,0x10,0x01,0x1A,0x8A, + 0x18,0x0B,0x58,0x13,0x08,0x01,0x1C,0x52,0x18,0x13,0x40,0x22,0x10,0x01,0x00,0x13, + 0x40,0x13,0x1A,0x52,0x03,0x13,0x3A,0x82,0x18,0x00,0x02,0x42,0x00,0x00,0x06,0x42, + 0xAB,0xF5,0x77,0x0A,0x59,0x0A,0x43,0x83,0x23,0x01,0x80,0x01,0xC0,0x13,0x46,0xC3, + 0x31,0x0A,0x80,0x01,0xEA,0x2B,0xAA,0x23,0x00,0xC1,0xAD,0x04,0xC1,0x22,0x02,0x41, + 0x18,0x12,0x92,0x0C,0x05,0x37,0xC5,0x03,0x31,0x08,0xA8,0x7E,0x08,0x71,0x00,0x81, + 0xC3,0x13,0xF1,0x0A,0xF6,0x02,0x39,0x98,0x80,0xA6,0x28,0xC1,0x1B,0xB1,0xF8,0x2A, + 0xF2,0x1A,0xDF,0x00,0xD0,0x48,0xAE,0x06,0x10,0x4A,0x42,0x01,0xD2,0x06,0x10,0x02, + 0xC1,0x40,0x40,0x8B,0x93,0x05,0x88,0x01,0xE4,0x4B,0x10,0x0A,0xD2,0x16,0x40,0x80, + 0x01,0x00,0x82,0x03,0x50,0x52,0x0A,0x41,0x41,0x93,0x30,0x02,0x39,0x82,0x44,0x83, + 0xC3,0x0B,0x87,0x01,0xCC,0x03,0x10,0x0A,0xC1,0x1E,0xC0,0x03,0x08,0xE9,0x07,0x42, + 0x01,0x17,0xC0,0x03,0x08,0x11,0x18,0x42,0x81,0x03,0x01,0xCF,0x47,0x8B,0xC1,0x13, + 0x88,0x01,0xCB,0x5B,0x10,0xD2,0xC4,0x16,0x05,0x01,0x80,0x03,0x02,0x87,0x31,0x00, + 0xCA,0x4B,0x74,0x00,0x11,0x42,0x8C,0x0E,0x50,0xCA,0x29,0x31,0x38,0x41,0x40,0x93, + 0xFF,0x2A,0xFB,0x3A,0x09,0x49,0x30,0x02,0x38,0x82,0x04,0x31,0xF2,0x02,0xD9,0x08, + 0x01,0x41,0xF0,0x02,0xD8,0x00,0x4E,0x01,0xD2,0x06,0x10,0x4A,0x40,0x01,0xD0,0x06, + 0x10,0x02,0xC2,0x40,0x40,0x8B,0x91,0x05,0x8A,0x01,0xEB,0x4B,0x10,0x0A,0xEC,0x0E, + 0x01,0x2C,0x0F,0x3C,0xC0,0x03,0x09,0x11,0x18,0x42,0x00,0x2F,0xC0,0x04,0x40,0x11, + 0x91,0x1E,0xC0,0x03,0x08,0xE9,0x07,0x42,0x85,0x03,0xC1,0x03,0x46,0x09,0x80,0x06, + 0xC2,0x03,0x35,0x00,0x75,0x00,0x82,0x03,0x82,0x2E,0xF0,0x00,0x30,0x00,0x70,0x00, + 0x80,0x03,0x8D,0x76,0x01,0x2F,0xC0,0x03,0x10,0xE9,0x0F,0x01,0x01,0x82,0x80,0x03, + 0x83,0x0B,0xC7,0x03,0x08,0x79,0x06,0x42,0x81,0x03,0x43,0x83,0x82,0x01,0x53,0x04, + 0x19,0x04,0xC3,0x03,0x38,0x00,0xAC,0xE6,0x40,0xA2,0x40,0x03,0x31,0x0A,0x88,0x01, + 0xEA,0x53,0xE2,0x90,0xA8,0x53,0x0A,0x31,0xF0,0x0A,0x4B,0x01,0xD0,0x0E,0x08,0x01, + 0x00,0x1F,0x40,0x14,0x10,0x8A,0xEC,0x0E,0x47,0x0C,0x00,0x0C,0x0B,0x41,0xF0,0x0A, + 0x48,0x01,0xD0,0x0E,0x00,0x01,0x00,0x1F,0x44,0x14,0x12,0x8A,0xEA,0x0E,0x40,0x04, + 0x09,0x04,0xA1,0x41,0x40,0x2A,0xC8,0x0C,0x44,0x03,0x80,0x01,0x5A,0x03,0xC4,0x00, + 0x10,0x02,0xCD,0x06,0x3F,0x7F,0xEA,0xF5,0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01, + 0x00,0x00,0x00,0x01,0xA9,0x85,0x5F,0x4A,0x28,0x31,0x40,0xE3,0x1C,0x52,0xA3,0x01, + 0x5B,0x1B,0x5D,0x23,0x7D,0x32,0xC1,0x10,0x43,0xE3,0xA1,0x01,0xC0,0x2B,0x47,0x09, + 0x88,0x56,0x01,0x01,0x02,0x1F,0xC1,0xCB,0x18,0x4A,0x3E,0x48,0x88,0xE6,0x40,0x8C, + 0x02,0xCC,0x46,0xB4,0x0A,0xF4,0x10,0xCC,0x16,0xF4,0x14,0xCC,0x1E,0xF4,0x18,0xCC, + 0x26,0xF4,0x0C,0xCC,0x12,0xF4,0xC0,0xCB,0x38,0x20,0x48,0x48,0x78,0x20,0x09,0x48, + 0x1A,0x0A,0x81,0xCB,0x26,0x09,0x80,0xE3,0xC1,0xCB,0x18,0x0A,0x94,0x4D,0x3E,0x48, + 0x78,0x48,0xEC,0x48,0x80,0xCB,0x00,0x27,0x9A,0x41,0xE1,0x00,0x95,0x05,0x16,0x42, + 0x9D,0xCE,0x16,0x42,0x90,0xC6,0x00,0x5F,0x02,0x41,0x19,0x0A,0x46,0x84,0xC0,0x58, + 0x0A,0xC4,0x46,0x84,0x16,0xC4,0xC0,0xC3,0x40,0xF9,0x93,0x0E,0xE6,0x00,0x82,0xC3, + 0xCA,0x83,0x88,0xC3,0xC0,0xC3,0x3A,0x00,0x79,0x00,0x80,0x81,0x81,0xC3,0x42,0xC3, + 0x82,0x01,0xCB,0x03,0x84,0x01,0x84,0xC3,0xE8,0x85,0x07,0x00,0x00,0x20,0x00,0x01, + 0x00,0x40,0x00,0x01,0xA8,0x85,0x40,0x22,0x44,0x0B,0x14,0x01,0x1C,0x8A,0x00,0x0B, + 0x87,0x0F,0xD8,0xF7,0xE8,0x85,0x00,0x00,0x00,0x01,0x00,0x42,0xA9,0xC5,0x7F,0xA2, + 0x15,0x01,0x08,0xD3,0x41,0xEB,0x4D,0x9A,0x00,0x79,0x06,0x2A,0x31,0x62,0xA0,0x01, + 0x7C,0x44,0x5E,0x5B,0x68,0x09,0x80,0x8E,0x68,0x29,0x80,0x3E,0x6A,0x41,0x88,0xA6, + 0xBF,0x13,0x41,0xE3,0x38,0x20,0x8F,0x0E,0x00,0x81,0x00,0x2F,0x08,0xD3,0xE5,0xD2, + 0x02,0xD3,0xE7,0x00,0x38,0x44,0x06,0xA1,0x07,0xC3,0xED,0xC5,0x41,0xF3,0x6F,0x32, + 0x01,0x74,0xF9,0x33,0x70,0x01,0x88,0x1E,0x44,0x22,0x19,0x43,0x41,0x44,0x01,0xBF, + 0x71,0x09,0x88,0x7E,0x31,0x5A,0x40,0x4C,0x12,0x00,0xC0,0x00,0x39,0xC4,0x06,0x44, + 0x0C,0x89,0x96,0x05,0x12,0x48,0xD0,0x08,0x48,0x01,0xC1,0x1E,0x90,0x05,0x86,0x0F, + 0xF9,0x5F,0x03,0x37,0x40,0x49,0x90,0x16,0x86,0x31,0x3A,0xC4,0x00,0x0F,0x09,0x69, + 0x1A,0x48,0xD0,0x08,0x48,0x81,0xC2,0x0E,0x38,0xCC,0x06,0xD7,0x38,0xD4,0x4E,0xA2, + 0x10,0x09,0x40,0x4B,0x18,0x90,0x28,0x09,0x8C,0x01,0x17,0x82,0x8E,0x16,0x90,0x6B, + 0x40,0x82,0x00,0x2F,0x10,0x19,0x18,0x90,0x10,0x82,0x8C,0x56,0x90,0x6B,0x46,0x72, + 0x18,0xC3,0x04,0x37,0x40,0x89,0x92,0x26,0x40,0x54,0xA1,0xD2,0x7A,0x44,0xE6,0x00, + 0x39,0x44,0xFE,0x03,0xE1,0x00,0xBA,0x03,0x3D,0x77,0x05,0xD3,0xE8,0xC5,0x07,0x00, + 0x80,0x01,0x06,0x42,0x00,0xC0,0x03,0x01,0x00,0x80,0x00,0x01,0x00,0x00,0x01,0x01, + 0x00,0x20,0x00,0x01,0x20,0x40,0x02,0x01,0x08,0x80,0x03,0x01,0xA8,0x85,0x48,0x2A, + 0x02,0x01,0x00,0x44,0x00,0x44,0x44,0x1A,0x0C,0x41,0xE8,0x00,0xBB,0xF7,0xDF,0xBF, + 0xE8,0x85,0x00,0x00,0x00,0x80,0x00,0x01,0x10,0x01,0x00,0x37,0x0A,0x01,0xE0,0x48, + 0x90,0x4D,0x4C,0xA1,0xCA,0xDE,0xE7,0x90,0x94,0x95,0x14,0x12,0xCB,0xB6,0x3F,0x82, + 0xA9,0x85,0x4F,0xE2,0x10,0xA9,0x41,0x5B,0x00,0xF1,0x37,0xCA,0xE2,0xA2,0x8E,0x01, + 0xC8,0x53,0x66,0x09,0xC8,0x16,0x10,0x41,0x03,0xF9,0x07,0x4F,0x9C,0x01,0xCF,0xE3, + 0x5D,0xAA,0x39,0x28,0x43,0xDB,0x98,0x01,0x68,0x01,0xD8,0xC6,0x38,0x20,0x87,0x5E, + 0xD8,0x63,0x60,0x11,0xC8,0x46,0x50,0x11,0x89,0x16,0x00,0x11,0x10,0x19,0x00,0x1F, + 0x50,0x19,0x88,0x0E,0x00,0x01,0x11,0x09,0xD7,0x63,0x66,0xD1,0x93,0x86,0xE2,0x20, + 0x96,0x25,0x97,0x63,0xF4,0xDB,0x12,0xE2,0xC8,0x56,0x12,0x09,0x07,0x47,0x3A,0x28, + 0x61,0x22,0x41,0x23,0xA0,0x01,0x6C,0x01,0x88,0x7E,0x18,0x01,0x90,0x5B,0x9E,0x5B, + 0x58,0x1B,0x55,0x09,0x44,0xE4,0x16,0x64,0x4E,0xE4,0x10,0x64,0x8E,0xC6,0x41,0xD4, + 0x18,0x54,0x48,0xDC,0x12,0x11,0x18,0x5C,0x00,0x97,0xD9,0x6B,0x68,0xD1,0x97,0x0E, + 0xE0,0x68,0x9B,0x6B,0x58,0x3B,0x35,0x31,0x2D,0x41,0xF8,0xF2,0xF8,0xEA,0x23,0xA1, + 0x38,0xB1,0xF8,0x62,0xF9,0x7A,0xDE,0xA0,0xD8,0x78,0x67,0x01,0xD3,0x06,0x10,0x22, + 0x78,0x01,0xD0,0x06,0x17,0xFA,0xCB,0x20,0xF5,0xFB,0x10,0xE2,0xE0,0xBE,0x20,0xC1, + 0xF9,0x62,0xD8,0xA0,0x34,0xD1,0xF8,0x72,0xD8,0x68,0x65,0x01,0xD3,0x06,0x10,0x22, + 0x68,0x01,0xD0,0x06,0x13,0x6A,0xCB,0x20,0x10,0xE2,0xE5,0x46,0xDC,0x63,0xF0,0xDB, + 0x10,0xE2,0xC4,0x26,0x5C,0x5C,0x5E,0x64,0x45,0xD8,0x14,0x1A,0xC8,0x06,0x10,0x41, + 0x8F,0x53,0xEE,0x85,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0xA8,0x85,0x6B,0x72, + 0x47,0x43,0x81,0x01,0xD0,0x03,0x46,0x01,0x80,0xAE,0x80,0x17,0xDD,0x8F,0x01,0x01, + 0x86,0x0F,0xE8,0x97,0x07,0x21,0xBB,0xFF,0xF8,0x3F,0x63,0x42,0x35,0x01,0xA0,0x33, + 0x44,0x3A,0x00,0x33,0x00,0x0F,0x80,0x17,0xDD,0x8F,0xE0,0x03,0x47,0x01,0x80,0xD6, + 0x47,0x43,0x81,0x01,0x93,0x33,0xEE,0x85,0x00,0x20,0x00,0x01,0x00,0xC0,0x04,0x01, + 0x10,0x00,0x00,0x42,0x96,0x05,0x32,0x10,0x70,0x90,0x0E,0x09,0x02,0x8A,0x4C,0x00, + 0x54,0x12,0x00,0x00,0xC0,0x00,0x04,0x0B,0x38,0x82,0x03,0x00,0x08,0x07,0x04,0x07, + 0xA8,0xC5,0x77,0xBA,0x05,0x09,0x18,0x83,0x00,0x11,0x80,0x07,0xC0,0xCF,0x6D,0xAA, + 0x50,0x43,0x39,0x41,0x19,0xC2,0x11,0x43,0x49,0x43,0x1F,0xC2,0x0B,0x43,0x17,0x7B, + 0x49,0x43,0x1D,0xC2,0x08,0x43,0x85,0x0F,0xE0,0x2F,0x63,0x7A,0xCF,0x03,0x0D,0xB9, + 0x05,0x42,0x88,0x03,0x00,0x0F,0x80,0x17,0xD5,0xCF,0xCE,0x03,0x3F,0x00,0xA8,0xD6, + 0xBB,0xFF,0xE7,0x17,0x4D,0x43,0x1D,0xC2,0x0B,0x43,0x15,0x7B,0x07,0x11,0xB8,0xFF, + 0xF8,0x4F,0x06,0x01,0x18,0x83,0x4D,0x22,0x07,0x51,0xC8,0x01,0xA7,0x43,0xEC,0xC5, + 0x18,0x00,0x02,0x42,0xF8,0x00,0x06,0x42,0x08,0xC0,0x02,0x01,0xA8,0x85,0x23,0x49, + 0x18,0x22,0x37,0x2A,0x48,0x01,0x80,0x36,0x68,0x01,0x30,0x82,0x80,0x0E,0xC0,0xE1, + 0x00,0x2F,0x80,0xE1,0x00,0x37,0x68,0x01,0x30,0x82,0x80,0x16,0xF0,0x00,0x24,0x51, + 0x04,0x07,0xE0,0x00,0x0A,0x01,0xF0,0x0A,0x48,0x01,0xD0,0x06,0x16,0x4A,0x0A,0x40, + 0x0A,0x01,0xF0,0x8A,0xBB,0xF7,0xD7,0x8F,0x40,0xF9,0xEB,0x06,0x00,0xF9,0x6B,0x01, + 0x87,0x16,0x08,0xF9,0x88,0x09,0xD0,0x40,0xCB,0x00,0xE8,0x85,0xA8,0x85,0x50,0xAA, + 0x60,0xAA,0x40,0x93,0x48,0x01,0xF8,0xA2,0x80,0x0E,0x20,0x11,0xFF,0xA2,0x78,0x10, + 0xCA,0x90,0x80,0x98,0x50,0x8A,0x40,0x93,0x94,0x01,0x13,0x1A,0xE8,0x2E,0x48,0x01, + 0x88,0x0E,0xD8,0x93,0x04,0x37,0xD8,0x93,0x00,0x27,0x48,0x01,0x8A,0x0E,0xD8,0x93, + 0x06,0x07,0xD8,0x93,0x04,0x88,0xD2,0x00,0xD3,0x08,0x1B,0x02,0xBA,0xF7,0xD7,0x2F, + 0x90,0x05,0x40,0x01,0xE0,0x0E,0x00,0x09,0xED,0x85,0x10,0x02,0xDB,0xE6,0xF7,0x20, + 0x90,0x05,0xE9,0x85,0x00,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x01, + 0xA8,0x85,0x40,0x9A,0x44,0x0B,0x10,0x01,0x18,0x8A,0x04,0x0B,0x40,0x0B,0x10,0x81, + 0x18,0x8A,0x00,0x0B,0x40,0x0B,0x10,0x09,0x18,0x8A,0x00,0x0B,0x4F,0x6A,0x20,0xF9, + 0x40,0x4B,0xA0,0x81,0xD8,0x5B,0x50,0x62,0x1E,0x1A,0x11,0x9B,0x1A,0x99,0x00,0x1B, + 0x04,0x41,0x00,0x83,0x40,0x4A,0x40,0x03,0x82,0x01,0xF2,0x03,0x40,0x01,0x80,0x0E, + 0x00,0xC9,0x00,0x07,0x00,0x89,0x00,0x83,0x07,0x01,0x88,0x01,0x88,0x43,0xEE,0x85, + 0x18,0x00,0x04,0x42,0x00,0x20,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x40,0x00,0x01, + 0x96,0x05,0x32,0x10,0x70,0x90,0x0E,0x09,0x02,0x8A,0x4C,0x00,0x54,0x12,0x00,0x00, + 0xC0,0x00,0x04,0x0B,0x38,0x82,0x03,0x00,0x08,0x07,0x00,0x07,0xB3,0x15,0x3B,0x82, + 0xA8,0x85,0x60,0x22,0x00,0x0F,0x80,0x17,0xD5,0x0F,0xE1,0x03,0x47,0x01,0x80,0xD6, + 0xE8,0x85,0x00,0x00,0x00,0xC0,0x04,0x01,0xAA,0xC5,0x57,0x4A,0xD2,0x83,0x68,0x4A, + 0x40,0x09,0x88,0x2E,0x93,0x83,0x42,0x43,0x0C,0x01,0x1C,0x42,0x07,0x43,0xEB,0xC5, + 0x35,0x01,0x08,0x73,0x46,0x7B,0x05,0x79,0x02,0x3A,0x40,0x0A,0xC0,0x01,0x37,0x22, + 0xA6,0x01,0x79,0x0C,0x58,0x1B,0x7C,0x09,0x80,0x06,0x79,0x29,0x80,0x3E,0x78,0x41, + 0x89,0x9E,0xBB,0x33,0x47,0x7B,0x3F,0xF8,0x88,0x0E,0x00,0x81,0x05,0xA7,0x08,0x73, + 0x71,0xBA,0xF9,0x3B,0xF7,0x01,0x7F,0xB4,0xE5,0xB0,0x93,0xB5,0x78,0x01,0x88,0x2E, + 0xC8,0x93,0x52,0x19,0x8E,0x16,0x00,0x51,0x00,0x43,0x07,0x17,0xE7,0xCA,0x02,0x4B, + 0x3B,0x34,0xE6,0xF8,0xB8,0x3B,0x01,0xA1,0x07,0x43,0xED,0xC5,0xFD,0x3B,0x31,0xE2, + 0x78,0x01,0x88,0x36,0x41,0x53,0x5F,0x62,0x48,0x62,0x01,0xD4,0x1E,0x0B,0x3C,0x34, + 0x03,0x37,0x32,0x3A,0x79,0x09,0x88,0x86,0x41,0x4B,0x57,0x3A,0x40,0x94,0x10,0x90, + 0xC6,0x88,0x12,0x89,0x90,0x4D,0x14,0x90,0xD1,0x50,0x54,0x01,0xC6,0x1E,0x90,0x45, + 0x81,0x0F,0xE8,0x97,0x02,0xA7,0x11,0x09,0x14,0x90,0xD2,0x50,0x50,0xA1,0xC0,0x26, + 0x4E,0xDA,0xC8,0x99,0x1E,0x0B,0x3C,0x14,0x00,0x57,0x51,0xEA,0xC1,0x50,0x54,0x19, + 0xC6,0x16,0x38,0x14,0x48,0xDA,0x00,0x3F,0x51,0xCA,0xD0,0x81,0xC1,0x50,0x54,0x01, + 0xC0,0x26,0x48,0xC2,0x39,0x14,0xCE,0x01,0x18,0x0B,0x04,0xCF,0x10,0x69,0x18,0x90, + 0xD1,0x48,0x4C,0xB1,0xC6,0xA6,0x38,0x0C,0x02,0x97,0xC8,0xBB,0x78,0x19,0x88,0x6E, + 0x30,0x3A,0x7B,0x11,0x8F,0x2E,0x40,0x4B,0x48,0x51,0x86,0x4E,0x8A,0xB3,0x0A,0x89, + 0x3F,0x8F,0x47,0x53,0xA6,0xD2,0x7A,0x0C,0xE7,0x48,0x3A,0x67,0x4F,0x89,0x9A,0xC6, + 0xFA,0x03,0xE1,0x00,0xBC,0x03,0x39,0x87,0x3D,0xFF,0x07,0x73,0xE8,0xC5,0x07,0x00, + 0x08,0xC0,0x02,0x01,0x80,0x01,0x06,0x42,0x00,0x70,0x00,0x01,0x00,0x00,0x01,0x01, + 0x77,0x81,0xF8,0xFF,0xF8,0x02,0x07,0x00,0xA8,0xFD,0x37,0x32,0x80,0x0D,0x04,0x01, + 0x01,0x2F,0x42,0x32,0x0E,0x01,0x0C,0x0B,0xC0,0x04,0x30,0x62,0x01,0x28,0x7A,0x1A, + 0x49,0xC3,0x1F,0x02,0x08,0xC3,0x17,0x09,0x30,0x82,0xC9,0x1C,0x81,0x0F,0xD0,0xA7, + 0xF8,0x82,0x33,0x0A,0xCF,0x99,0x49,0xC9,0x99,0x36,0x40,0x91,0xE7,0x16,0x48,0xC3, + 0x1F,0x02,0x0D,0xC3,0x47,0x20,0x8B,0x56,0x11,0x09,0x30,0x82,0xC8,0x1C,0x80,0x0F, + 0xD3,0x1F,0xF9,0xA2,0x11,0x09,0x30,0x82,0xC8,0x1C,0x80,0x0F,0xD3,0xEF,0xF8,0xBA, + 0x11,0x09,0x30,0x82,0xC8,0x1C,0x80,0x0F,0xD5,0xBF,0x10,0x3A,0xE9,0x16,0x30,0x02, + 0x30,0xE2,0x31,0x3A,0xFD,0x82,0x13,0xC2,0xE3,0x0E,0x98,0xBA,0x05,0x17,0x10,0x02, + 0xDB,0x06,0x98,0xA2,0x46,0x4A,0x48,0x03,0xDE,0x8A,0x0B,0x00,0xC0,0x00,0xCA,0x14, + 0x00,0x44,0xC0,0x14,0xE0,0x00,0x84,0x14,0xC2,0x04,0xE0,0x00,0x90,0x05,0xCE,0x24, + 0x84,0x04,0x10,0x42,0x98,0xAE,0x85,0x2D,0xE8,0x85,0x07,0x00,0x00,0x01,0x00,0x42, + 0xA8,0x85,0x48,0x92,0x18,0x01,0x40,0x4B,0xE2,0x10,0x8C,0x01,0x58,0x4C,0x84,0x0B, + 0x80,0x1B,0x42,0x7A,0x48,0x7A,0xD8,0x03,0xE0,0xA0,0x82,0x83,0x59,0x53,0x84,0x13, + 0x5B,0x5B,0xE2,0x00,0xE0,0x10,0x85,0x1B,0x20,0xA1,0x80,0xA3,0x02,0x11,0x80,0x83, + 0x4C,0x43,0xE6,0x90,0xE0,0x98,0x82,0x83,0x48,0x53,0x84,0xD3,0x4A,0x53,0xE2,0xC0, + 0xE0,0xC8,0x1C,0xC1,0x80,0x13,0x80,0x5B,0xE8,0x85,0x00,0x00,0x00,0x40,0x00,0x01, + 0x00,0xC0,0x03,0x01,0x00,0x01,0x00,0x42,0xA8,0x85,0x51,0x4A,0x30,0x1A,0x40,0x8B, + 0xE0,0x00,0xF2,0x63,0x80,0xE3,0x40,0xA3,0xE1,0x08,0xFA,0x23,0xE0,0x18,0x84,0x23, + 0x40,0x83,0x68,0x22,0x82,0x01,0xE1,0x03,0x87,0x43,0xE8,0x43,0x81,0xC3,0xE8,0x85, + 0x00,0x20,0x00,0x01,0x00,0xC0,0x03,0x01,0xA8,0x9D,0x37,0x22,0x47,0x0A,0x43,0x0C, + 0x44,0x03,0x80,0x2D,0x86,0x01,0x53,0x34,0x4A,0x04,0xD7,0x00,0x91,0x3D,0x50,0x04, + 0x4A,0x0C,0xD1,0x00,0x91,0x2D,0x30,0x02,0x81,0x07,0xE0,0xD7,0xC0,0x03,0x47,0x09, + 0x83,0x5E,0x48,0x0C,0x06,0x40,0xCC,0x10,0x4A,0x04,0xD5,0x88,0x02,0x18,0xCC,0xD8, + 0x90,0x4D,0xD0,0xC0,0x94,0x05,0x80,0x78,0x83,0x28,0x0C,0x3C,0x08,0x2C,0x05,0x31, + 0xF0,0x02,0x11,0x71,0xF0,0x12,0x85,0x24,0xCA,0x08,0x06,0x40,0xC4,0x40,0xC0,0x00, + 0x0B,0x41,0xF0,0x0A,0x1F,0x81,0xF0,0x1A,0xC8,0x50,0x8A,0x1C,0x02,0x88,0xC2,0x88, + 0xC4,0x48,0x86,0x00,0x80,0x48,0x94,0x05,0x50,0x3A,0x92,0x6D,0x40,0x01,0xD0,0x0E, + 0x00,0x01,0x00,0x2F,0x40,0x8B,0x40,0x5C,0x10,0x1A,0xD4,0x0E,0x00,0x01,0xF0,0x42, + 0x68,0x01,0xD0,0x0E,0x28,0x01,0x00,0x2F,0x42,0x8B,0x40,0x54,0x10,0x52,0xD5,0x0E, + 0x2A,0x11,0xF8,0x6A,0xC8,0x24,0xD0,0x58,0xC8,0x1C,0x30,0xFA,0xD8,0x50,0x5A,0x01, + 0xD2,0x06,0x10,0xDA,0x02,0xC8,0xC2,0xC8,0xF0,0x98,0xD0,0x06,0x16,0x9A,0xC2,0x48, + 0xBC,0x58,0x7E,0xD8,0xC4,0xC8,0x1A,0x48,0x60,0x48,0x50,0x01,0xD2,0x06,0x10,0x92, + 0x06,0x98,0xC2,0x90,0x78,0x01,0xD0,0x06,0x16,0xFA,0xCB,0x90,0xBC,0x98,0x7E,0xD8, + 0xC4,0xD0,0x1C,0x90,0x60,0x90,0x90,0x04,0x10,0x8A,0xCD,0x06,0x35,0x8A,0x11,0x92, + 0xC8,0x06,0xB0,0x04,0xD0,0x90,0xDB,0x24,0x32,0xBA,0x18,0xD2,0x06,0x98,0xC4,0x90, + 0x31,0xA2,0x34,0xD2,0x06,0xF8,0xCB,0x90,0x1F,0xF1,0xF0,0x1A,0x1A,0x42,0x1A,0x9A, + 0x43,0xB8,0x33,0x12,0xCC,0x00,0xC6,0xD0,0x07,0x00,0x06,0x88,0xC0,0x00,0x8C,0x14, + 0xB9,0xF7,0xC7,0x1F,0x80,0x0C,0xC0,0x04,0xC9,0x1C,0xD0,0x80,0x1C,0x0A,0x02,0x50, + 0xC1,0x48,0x14,0x21,0xF2,0x12,0x05,0x18,0xC2,0x00,0x1E,0x12,0xC0,0x80,0xCA,0x04, + 0x1F,0x6A,0xCA,0x48,0x00,0x48,0xC6,0x40,0xCF,0x14,0xB8,0xF7,0xC0,0x77,0xC8,0x34, + 0x48,0x49,0x88,0x1E,0x30,0x02,0x81,0x07,0xC0,0x0F,0x01,0x37,0xCF,0x24,0x18,0x0C, + 0xCD,0x1C,0x20,0x0C,0xCF,0x0C,0x00,0x0C,0x09,0x04,0xC1,0x03,0x40,0x00,0x44,0x09, + 0x8B,0x1E,0x50,0x04,0x05,0x04,0x57,0x04,0x00,0x57,0x40,0x49,0x97,0x2E,0x48,0x04, + 0x11,0x04,0x53,0x04,0x10,0x04,0x85,0x3D,0xEF,0x85,0x5F,0x04,0x05,0x04,0x67,0x04, + 0x0F,0x04,0x39,0xC7,0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0xA8,0xF5,0x3F,0x31, + 0x36,0x2A,0xF8,0x3A,0x01,0xF1,0xF0,0x42,0x48,0x82,0x81,0x14,0x41,0x4B,0xD0,0xC0, + 0x8E,0x01,0xCB,0x73,0x0B,0x51,0x18,0x82,0xBE,0xEF,0xFF,0xBF,0x90,0x25,0x00,0x41, + 0xF1,0x42,0x09,0x21,0x83,0x0C,0xF0,0x4A,0x8A,0x04,0xD0,0x00,0x18,0x82,0x0B,0x51, + 0xBE,0xEF,0xFF,0x5F,0x91,0x15,0xC8,0xC0,0x90,0x1D,0xC0,0x0C,0xC0,0x00,0x94,0x05, + 0x60,0x01,0xD0,0x06,0x11,0x22,0x93,0x0D,0x50,0x01,0xD0,0x06,0x11,0x92,0x62,0x02, + 0x91,0x95,0x40,0x33,0x58,0x01,0xD0,0x0E,0x30,0xE2,0x01,0x37,0x44,0xA4,0x11,0xE2, + 0xD7,0x16,0xD8,0x18,0x90,0xE5,0x00,0x07,0x30,0x62,0x40,0x01,0xD0,0x0E,0xF0,0x0C, + 0x03,0x3F,0x40,0x9C,0x10,0x1A,0xD4,0x1E,0xC0,0x0C,0xD0,0xC0,0x90,0x35,0x00,0x07, + 0x34,0xB2,0x10,0x62,0x82,0x3E,0xE0,0x80,0xE2,0x10,0x1B,0x82,0xE7,0x48,0xBA,0xEF, + 0xF8,0x97,0x94,0x35,0x04,0x47,0x10,0xB2,0x82,0x36,0xE0,0x40,0xE2,0x88,0x1B,0x42, + 0xE7,0x88,0xBA,0xEF,0xF8,0x47,0x94,0x25,0xC4,0x14,0x10,0x3A,0xE9,0x0E,0xC8,0xC0, + 0x01,0x07,0xD8,0xC0,0x00,0x44,0xCF,0x0C,0xC4,0x04,0x10,0x0A,0x30,0x42,0xE8,0x0E, + 0xC8,0x00,0x04,0x07,0xD9,0x00,0x0C,0x44,0xE8,0xF5,0x07,0x00,0x00,0x40,0x00,0x01, + 0x00,0x20,0x00,0x01,0xA8,0x85,0x63,0xB2,0xC8,0x03,0x47,0x01,0x80,0x3E,0x69,0xAA, + 0x44,0x43,0x81,0x01,0x40,0x03,0x40,0x01,0x87,0x0E,0xB9,0xFF,0xDD,0xCF,0x9F,0x03, + 0x40,0xF9,0x8F,0xE6,0x42,0x53,0x09,0xD1,0x34,0x02,0xE1,0x5A,0xC6,0x01,0xA1,0x1B, + 0x09,0x11,0x80,0x0B,0x0A,0x01,0x20,0x39,0xA3,0x0B,0x0A,0x20,0x28,0x79,0x30,0x42, + 0x5B,0x4A,0x90,0x01,0x01,0x47,0x08,0x41,0x1E,0x0A,0xC2,0x48,0xCE,0x48,0xD8,0x73, + 0x1A,0x72,0xE1,0x00,0x9E,0x73,0x96,0x05,0xC4,0x8B,0x16,0x0A,0xC3,0x9E,0xEF,0x85, + 0x00,0xC0,0x05,0x01,0x00,0x40,0x00,0x01,0x08,0x80,0x03,0x01,0xAB,0xBD,0x5F,0xBA, + 0x40,0xBA,0x43,0xCB,0x41,0x03,0x88,0x01,0x80,0x45,0xEC,0x4B,0x2B,0x01,0x80,0x01, + 0x8E,0x04,0xC0,0x23,0xC0,0x4C,0x80,0x2B,0x30,0x42,0x01,0x9F,0x48,0x7A,0x43,0x5B, + 0x0C,0x41,0x99,0x01,0x1C,0x0A,0x5A,0xDB,0xE2,0x48,0xE2,0xCA,0x18,0x4A,0x3E,0x48, + 0x80,0x36,0x80,0x83,0xCA,0x4C,0xE0,0x90,0xC0,0x4B,0xD8,0x4C,0xE0,0x48,0x82,0xCB, + 0xE6,0x00,0x92,0x05,0x17,0x02,0x9D,0x4E,0xC0,0x4C,0xC0,0x03,0x80,0x3C,0x40,0x01, + 0x88,0x0E,0x80,0x5D,0xE8,0x85,0x47,0x09,0x88,0x16,0xC0,0x04,0x47,0x09,0x80,0xC6, + 0x00,0x01,0x80,0x24,0x80,0x1C,0xC8,0x04,0xC4,0x3C,0x10,0x42,0x88,0x7E,0x02,0x01, + 0x50,0xD2,0x82,0x0C,0x40,0x93,0x30,0x32,0x90,0x01,0x34,0x3A,0x30,0x0A,0x90,0x34, + 0x00,0x57,0xD0,0x34,0x58,0x9B,0x12,0x31,0x1C,0x52,0xD2,0xEA,0xE4,0x90,0xD4,0xD2, + 0xC4,0x40,0xC9,0xB0,0xE6,0x48,0x92,0x4D,0xD4,0x04,0x10,0x8A,0x98,0x8E,0x37,0x8A, + 0xBF,0xEF,0xF7,0x9F,0x31,0x2A,0x30,0x82,0xCF,0x04,0xB8,0xEF,0xF0,0x77,0x0F,0x01, + 0x80,0x14,0x30,0x42,0x02,0xD7,0xE0,0x48,0x90,0x4D,0x06,0x0F,0xD4,0x34,0x58,0x93, + 0x1A,0x41,0x19,0x5A,0xE6,0xD8,0xE2,0x9A,0x18,0xDA,0x3E,0xD8,0x81,0x9E,0x1F,0x41, + 0x18,0x5A,0x32,0xF2,0xB4,0x71,0xF8,0xB2,0x9E,0x81,0xF0,0x92,0xDA,0x0C,0xE0,0x48, + 0xC7,0x90,0xCE,0xB8,0xE6,0x00,0x92,0x4D,0x90,0x05,0x96,0x0C,0xD4,0x3C,0x10,0x12, + 0xC0,0x26,0x37,0x8A,0x37,0xC2,0xB9,0xEF,0xF0,0x47,0x36,0x32,0xC8,0x3C,0xC0,0x0C, + 0xBE,0xEF,0xF7,0x1F,0xD8,0x48,0x8D,0x24,0xC8,0x14,0xD0,0x40,0x80,0x1C,0x08,0x01, + 0x30,0x52,0x00,0x77,0x33,0x5A,0x18,0x1A,0xE8,0x44,0x00,0x01,0x02,0xD8,0xCA,0xD8, + 0x02,0x1F,0x00,0x28,0xE2,0x00,0x9A,0xD2,0x95,0x05,0x16,0x02,0x9A,0xCE,0xE7,0x48, + 0x95,0x4D,0x16,0x0A,0x98,0x76,0x0F,0x01,0x32,0x42,0x00,0x17,0xE6,0x48,0x92,0x4D, + 0x01,0x1F,0x68,0x32,0x44,0x43,0x81,0x01,0x58,0x13,0x34,0x42,0x1A,0x41,0x19,0xC2, + 0xE4,0x18,0x32,0x32,0xE6,0x82,0x1E,0x02,0x3F,0x00,0x80,0x7E,0x01,0x01,0x00,0x47, + 0x53,0xF2,0x30,0xAA,0x40,0x9B,0xA8,0x71,0x9C,0x01,0x5C,0xD3,0x58,0xDB,0x92,0x2C, + 0xF8,0x92,0xF2,0x24,0x38,0x31,0x30,0x2A,0xCB,0x90,0x1C,0xEA,0xD9,0xF2,0x32,0x7A, + 0xD8,0x90,0xAC,0x06,0x14,0x92,0x92,0xB5,0x30,0x92,0xEB,0x2C,0x95,0x81,0xF0,0x52, + 0xEA,0x1C,0xC8,0x90,0xE2,0xE8,0xDD,0xDA,0xD0,0x90,0xAE,0x06,0x15,0x92,0xC2,0x98, + 0x33,0x12,0x1B,0x12,0xF2,0x44,0x00,0x90,0x04,0x38,0xCA,0x90,0xE6,0x00,0x9A,0x9A, + 0x90,0x05,0xD6,0x04,0x16,0x82,0x9C,0x9E,0xE3,0x48,0x32,0x02,0xE6,0x00,0x92,0x4D, + 0x94,0x05,0x36,0x22,0xC0,0x4C,0xC0,0x13,0x2D,0x12,0xC3,0xD6,0xC0,0x4C,0xC8,0x04, + 0xC4,0x03,0x10,0x42,0xC9,0x06,0x38,0xE7,0x31,0x42,0x38,0xD7,0x00,0x20,0x00,0x01, + 0x00,0x40,0x00,0x01,0x54,0x22,0x48,0x9B,0x44,0x22,0xD8,0x0B,0x1C,0x5A,0x0C,0x9B, + 0x10,0x8B,0x0A,0x09,0xA3,0x0B,0x3C,0x82,0xF8,0x00,0x06,0x42,0x00,0xC0,0x04,0x01, + 0xA8,0x85,0x80,0x0F,0xD8,0xDF,0xED,0x85,0xA8,0x85,0x40,0x2A,0xC8,0x03,0x42,0x01, + 0x8F,0x16,0xB8,0xFF,0xD0,0x9F,0xE9,0x85,0xBA,0xFF,0xE7,0x77,0xE8,0x85,0x00,0x00, + 0x08,0xC0,0x02,0x01,0x40,0x92,0x48,0x9A,0x42,0x03,0x80,0x01,0xF0,0x03,0x42,0x01, + 0x80,0x3E,0x40,0x8A,0x07,0x43,0x02,0xF9,0x57,0x72,0x80,0x89,0x90,0x01,0x12,0x83, + 0x00,0x17,0x40,0x6A,0xC2,0xE1,0x00,0x43,0x40,0x62,0x40,0x03,0xE8,0x13,0xEA,0x1B, + 0x08,0x90,0x18,0xD2,0x04,0x53,0xDE,0x13,0x0A,0x53,0xD8,0x13,0x0E,0x53,0xDC,0x13, + 0x0A,0x53,0xE2,0x13,0x18,0x53,0xE4,0x13,0x02,0x01,0x18,0x53,0x1B,0x43,0x38,0x82, + 0x00,0x40,0x00,0x01,0x00,0x01,0x00,0x42,0x80,0x60,0x05,0x00,0x00,0x20,0x00,0x01, + 0xA8,0xC5,0x47,0x92,0x78,0x92,0x40,0x03,0xEA,0x23,0xE8,0x2B,0xBE,0xFF,0xDF,0x47, + 0x30,0x01,0x00,0x37,0x09,0x09,0x30,0x92,0x30,0x42,0x80,0x0F,0xCB,0xAF,0xE1,0xB0, + 0x95,0xB5,0x17,0x32,0x98,0xB6,0x17,0x01,0x40,0xC3,0x31,0x9A,0x84,0x01,0x54,0x0B, + 0x00,0x4F,0x00,0x01,0x00,0x1F,0x80,0x5B,0xE2,0x48,0xE2,0x00,0x95,0x05,0x16,0x42, + 0x9A,0xCE,0xE7,0x90,0x95,0x95,0x16,0x12,0x9F,0x9E,0xEF,0xC5,0x00,0x40,0x00,0x01, + 0x00,0x20,0x00,0x01,0xA8,0x85,0x40,0xCA,0x40,0x0B,0x30,0x48,0xAE,0x2E,0x08,0x81, + 0x02,0x0B,0x08,0x81,0x00,0x0B,0x08,0x81,0x00,0x0B,0x48,0xA2,0x8C,0x01,0x46,0x53, + 0x38,0x90,0x78,0x90,0x04,0x53,0x44,0x53,0x18,0x81,0x19,0xD2,0x00,0x53,0x5C,0x82, + 0x12,0x09,0x06,0xD3,0x16,0x91,0x01,0x13,0x44,0x72,0x40,0x23,0x10,0x61,0x18,0xA2, + 0x02,0x23,0x44,0x23,0x1A,0xA2,0x00,0x23,0x4C,0x23,0x1A,0xA2,0x08,0x23,0x4A,0x23, + 0x18,0xA2,0x08,0x23,0x40,0x23,0x1E,0xA2,0x02,0x23,0x46,0x43,0x10,0x01,0x1A,0x82, + 0x04,0x43,0x02,0xD1,0x07,0xC3,0x00,0x01,0x08,0xC3,0xEA,0x85,0x00,0x00,0x00,0x42, + 0x80,0x01,0x06,0x42,0xF8,0x00,0x06,0x42,0xA8,0x85,0x6B,0x8A,0x41,0x43,0x81,0x01, + 0xE0,0x03,0x86,0x0F,0xC0,0x0F,0x44,0x7A,0x24,0x01,0x00,0x23,0x41,0x43,0x09,0x91, + 0xA7,0x62,0x80,0x01,0x8F,0x23,0xB8,0xFF,0xF9,0xEF,0x42,0x43,0x82,0x01,0xF3,0x0B, + 0x30,0x50,0x4A,0x4A,0x74,0x90,0x1A,0x53,0x5A,0x53,0x04,0x90,0x1E,0x53,0x0A,0x63, + 0xF0,0x03,0x32,0x00,0xAC,0x16,0x00,0x09,0x00,0x43,0x1E,0x63,0xE8,0x85,0x03,0x00, + 0x00,0x20,0x00,0x01,0x10,0x00,0x00,0x42,0x00,0x01,0x00,0x42,0xAA,0xC5,0x47,0x42, + 0x4A,0x42,0x52,0x4A,0x08,0x2E,0x30,0x2A,0x33,0x01,0xA8,0x01,0x31,0x0A,0xB0,0x73, + 0xCC,0xC1,0x1A,0x0B,0x13,0x41,0x88,0xC1,0x99,0x53,0x0C,0x81,0x98,0x0B,0x38,0x81, + 0xA0,0x3B,0x08,0x51,0xA6,0x0B,0x9A,0x3B,0x0A,0x11,0x98,0x0B,0x14,0xC1,0x98,0x13, + 0xA8,0x0B,0x08,0xA1,0xA9,0x0B,0x22,0x01,0x0C,0xC9,0xA8,0x23,0x08,0x48,0x02,0x0C, + 0x08,0x29,0x10,0x48,0x01,0x0C,0x4A,0xCA,0x01,0x0B,0x4A,0xCA,0x00,0x0B,0x34,0x0A, + 0x17,0x01,0x88,0x61,0x30,0x9A,0x08,0x66,0x37,0x12,0x90,0x01,0x8D,0xB3,0xCA,0xA1, + 0x8A,0x73,0x88,0x73,0x8D,0x73,0xBC,0x63,0x1E,0xE9,0x03,0xD8,0xC9,0x60,0x01,0x1C, + 0x18,0xF9,0x9F,0x19,0x00,0x1C,0x1B,0xF1,0x80,0x5B,0x1C,0x51,0x86,0x5B,0x1A,0x41, + 0x80,0x5B,0x0E,0x21,0xA0,0x8B,0x0A,0x31,0xA4,0x8B,0x08,0x11,0xB1,0x4B,0x4B,0x4A, + 0x1D,0x4C,0xB5,0x7B,0xAB,0x01,0x1B,0x73,0x48,0x3A,0x31,0x0B,0x8A,0x91,0x30,0x0B, + 0x8C,0xE1,0x36,0x0B,0x49,0x32,0x41,0x2A,0x01,0x43,0x40,0x32,0x08,0x81,0x30,0x32, + 0xB8,0xEF,0xEF,0x6F,0x42,0x02,0xC1,0x81,0x00,0x43,0x85,0x71,0x05,0x43,0xC3,0x71, + 0x01,0x43,0x87,0xC1,0x0E,0x43,0xC1,0xC1,0x01,0x43,0x81,0xC1,0x1F,0x03,0x87,0xF9, + 0x83,0x89,0x09,0x43,0xC3,0xF9,0xC7,0x69,0x10,0x43,0xF9,0x00,0x08,0x43,0xFF,0x00, + 0x09,0x43,0x35,0x02,0x83,0xC1,0x03,0x03,0x45,0xBA,0x00,0x03,0x41,0xBA,0x08,0x33, + 0x00,0x03,0x47,0xA2,0xE3,0x00,0x0C,0x03,0xE5,0x00,0x0C,0x03,0xE7,0x00,0x0C,0x03, + 0xE1,0x00,0x14,0x03,0xE3,0x00,0x12,0x03,0xE5,0x00,0x12,0x03,0x83,0xF9,0x87,0x69, + 0x11,0x03,0x87,0xA1,0x18,0x03,0x81,0x51,0x18,0x03,0x83,0xF1,0x1F,0x03,0xED,0xC5, + 0x00,0xC0,0x03,0x01,0x00,0x20,0x00,0x01,0x40,0xA2,0x01,0x00,0xC8,0x21,0x01,0x00, + 0x88,0xD9,0x01,0x00,0x70,0x02,0x01,0x00,0x38,0xC2,0x00,0x00,0x00,0x49,0x07,0x00, + 0x00,0x00,0x00,0x01,0x40,0x60,0x04,0x01,0x38,0x00,0x01,0x01,0x20,0x40,0x02,0x01, + 0xA8,0x85,0x41,0x9A,0x0A,0x01,0x40,0x13,0x90,0x01,0x03,0xEF,0x00,0x41,0x59,0x8A, + 0x1E,0x42,0xC2,0x20,0x02,0x39,0x0A,0x00,0xC6,0x00,0xD9,0x23,0x29,0x79,0x18,0x62, + 0x91,0x25,0x07,0x62,0x9C,0x23,0xDE,0x23,0x29,0xE9,0x07,0x62,0x98,0x23,0x24,0x01, + 0x16,0x24,0x14,0x24,0x06,0x40,0xC2,0x18,0x04,0x19,0x09,0x00,0x20,0xF9,0xC7,0xC0, + 0x8A,0x23,0xE4,0x48,0x8E,0x23,0x96,0x4D,0xC4,0x83,0x16,0x42,0xC1,0xF6,0xEE,0x85, + 0x00,0x20,0x00,0x01,0x08,0x80,0x03,0x01,0xA8,0x8D,0x0F,0x31,0x47,0xC2,0xB8,0xEF, + 0xE0,0x77,0x44,0xBA,0x36,0x01,0xC0,0x31,0xAA,0x33,0xA8,0x33,0x24,0x09,0xA0,0x23, + 0x4A,0xA2,0xA0,0x33,0x40,0x4B,0x32,0x2A,0x8E,0x01,0xF2,0x4B,0xA1,0x0B,0xAE,0x01, + 0x86,0x73,0x99,0x23,0x39,0x51,0xC0,0x01,0xA1,0x3B,0x0E,0x41,0xAC,0x0B,0xA6,0x33, + 0x08,0x99,0x80,0xC9,0xBB,0xEF,0xE7,0x9F,0x45,0x52,0x08,0x29,0x40,0x03,0xB8,0x23, + 0x80,0x01,0xA1,0x0B,0xC0,0x04,0x40,0x09,0x89,0x2E,0x30,0x42,0x8A,0x73,0xC7,0x01, + 0xA7,0x3B,0xBC,0xFF,0xF8,0x2F,0x4D,0x2A,0x40,0x1A,0x00,0x43,0xE8,0xC5,0x07,0x00, + 0x08,0xF0,0x02,0x01,0x00,0x20,0x00,0x01,0xD2,0x2A,0x2D,0xD5,0x58,0x40,0x01,0x01, + 0xAA,0x85,0x6F,0x02,0xC1,0x0B,0x40,0x6B,0x1B,0x71,0xA8,0x01,0x30,0x62,0x25,0x81, + 0xEE,0x6B,0xF1,0x1A,0xFC,0x22,0x40,0x50,0x55,0x09,0x30,0x72,0x88,0x6E,0x39,0x91, + 0x36,0xA1,0xF8,0x3A,0xFE,0x32,0xDC,0xE8,0xD8,0x10,0x6D,0x01,0xD3,0x06,0x10,0x6A, + 0x50,0x01,0xD0,0x06,0x15,0x92,0xC2,0x50,0x94,0x95,0x2C,0xB2,0x94,0x4E,0x38,0x48, + 0x78,0x48,0x8C,0x41,0x86,0x0B,0x40,0x0C,0xD2,0xC8,0x12,0x0C,0x4B,0x0C,0xD0,0x08, + 0x03,0x8F,0x30,0x0A,0xC0,0x13,0xCE,0x4B,0x10,0x52,0xC4,0x6E,0x85,0xC8,0xE4,0xF8, + 0x05,0x58,0x82,0xD0,0xC2,0x48,0xC6,0x88,0x15,0x0C,0x82,0x08,0xE2,0xB0,0x05,0x58, + 0x86,0x90,0xC5,0x48,0xC4,0x88,0x12,0x0C,0xEE,0x85,0x47,0x2C,0x4A,0x34,0xD8,0xD8, + 0xD8,0x20,0x95,0xDD,0x90,0x25,0xF1,0xE8,0xD3,0x06,0x10,0x6A,0xF0,0x30,0xD1,0x06, + 0x15,0x32,0xCB,0x68,0x29,0xAA,0xD3,0x8E,0x38,0x09,0x28,0x91,0x18,0xF8,0x37,0xF2, + 0xF9,0x2A,0x02,0xF2,0x05,0x7A,0x11,0xF2,0x8A,0x36,0xD8,0xD8,0xAA,0x06,0x10,0xDA, + 0x33,0x2A,0xEB,0x6B,0x10,0x5A,0xE5,0x7E,0x30,0x09,0x18,0xA1,0x19,0xB0,0x37,0x2A, + 0xF1,0x1A,0x06,0xAA,0x05,0xF2,0x10,0xAA,0x8F,0x7E,0xD0,0x18,0xAA,0x06,0x10,0xDA, + 0x33,0x22,0xEB,0x23,0x10,0x1A,0xED,0x46,0x56,0x11,0xC8,0x6E,0x3C,0x50,0x7C,0x90, + 0x44,0x48,0x06,0x48,0x18,0x52,0x80,0x13,0xE9,0x85,0x57,0xE1,0x94,0xE6,0x3F,0x48, + 0x7A,0x48,0xE4,0x90,0x00,0x90,0x1C,0x8A,0x87,0x0B,0xE8,0x85,0x3C,0x48,0x7C,0x48, + 0x8F,0x41,0x38,0xCF,0x00,0x40,0x00,0x01,0xA8,0x85,0x80,0x0F,0xC8,0xFF,0x60,0x32, + 0xC8,0x03,0x43,0x01,0x80,0x26,0x40,0x31,0x88,0xD6,0x87,0x0F,0xE7,0x3F,0x3A,0xBF, + 0x86,0x0F,0xE0,0x17,0x38,0xA7,0x07,0x00,0x08,0xC0,0x02,0x01,0xA8,0x85,0x67,0xD2, + 0x55,0xD2,0xC8,0x03,0x34,0x0A,0x39,0x28,0xC8,0x01,0x37,0x42,0x41,0x93,0x80,0x01, + 0x30,0x01,0x38,0x09,0xE2,0x1B,0x96,0x01,0x88,0x01,0x6A,0x01,0xD9,0x16,0xD8,0x23, + 0x48,0x20,0x87,0x46,0xA0,0x33,0x82,0x73,0xF4,0x8B,0x14,0x5A,0x8E,0x16,0xF0,0x8B, + 0xA4,0x0B,0xA6,0x3B,0xEA,0x85,0xE7,0x23,0x60,0x81,0x9F,0x16,0xF5,0xAB,0x16,0x5A, + 0x80,0x16,0xC0,0x5B,0x58,0x09,0x88,0x26,0xF6,0x93,0xA4,0x13,0xA0,0x33,0x82,0x73, + 0x04,0x37,0x58,0x09,0x88,0x06,0x80,0x7B,0x60,0x81,0x9F,0x0E,0x0A,0x21,0xA3,0x0B, + 0xE2,0x0B,0xE2,0x48,0xA7,0x0B,0xEA,0x85,0x08,0xC0,0x02,0x01,0x00,0x40,0x00,0x01, + 0xA9,0x85,0x60,0x5A,0xC8,0x03,0x43,0x01,0x88,0x1E,0x80,0x0F,0xDF,0x8F,0xBE,0xFF, + 0xCD,0xBF,0xCC,0x03,0x38,0x00,0xAA,0x1E,0x86,0x0F,0xD8,0x57,0xBE,0xFF,0xC7,0x07, + 0xB9,0xF7,0xEF,0xA7,0x48,0x1A,0x11,0x09,0x40,0x01,0x80,0x4E,0x40,0x43,0x18,0x82, + 0x00,0x43,0x40,0x43,0x18,0x82,0x04,0x43,0x40,0x43,0x18,0x82,0x07,0x43,0x38,0xF7, + 0xCC,0x03,0x35,0x00,0xA8,0x16,0x40,0x43,0x18,0x82,0x00,0x43,0xCE,0x03,0x0D,0xF9, + 0x05,0x42,0x88,0x03,0x49,0xB2,0xC8,0x01,0x5A,0x43,0xE2,0x00,0x1A,0x43,0x5A,0x5B, + 0x40,0xAA,0x70,0xD8,0x82,0x1B,0x58,0x5B,0x62,0xD8,0x80,0x1B,0x58,0x5B,0x52,0xD8, + 0x82,0x1B,0x5C,0x4B,0x80,0x0B,0xC6,0x0B,0xC4,0x23,0xC2,0x1B,0xCE,0x48,0xC0,0x23, + 0xCE,0xD8,0xC0,0x48,0x88,0x29,0x55,0x58,0x8A,0x1B,0x88,0x0B,0x0C,0x51,0x8E,0x0B, + 0x88,0x13,0x0E,0x01,0x92,0x0B,0x90,0x0B,0x0C,0x11,0x90,0x0B,0x90,0x13,0x9E,0x0B, + 0x0A,0x19,0x98,0x0B,0x0C,0x21,0x98,0x0B,0x0E,0x29,0x98,0x0B,0xE8,0x85,0x00,0x00, + 0x08,0xC0,0x02,0x01,0xF8,0x00,0x06,0x42,0x00,0x00,0x03,0x01,0xA8,0x85,0x57,0xE2, + 0x02,0x01,0x40,0x8B,0x39,0x01,0x1C,0xCA,0x00,0x8B,0x62,0xD2,0x37,0x12,0x10,0x03, + 0x6B,0xCA,0x00,0x43,0x09,0x09,0x04,0x4B,0x09,0x89,0x00,0x0B,0x58,0xBA,0x70,0xC2, + 0x34,0x0A,0x00,0xD3,0xE5,0x48,0x12,0x8A,0x98,0xDE,0x0F,0x99,0x01,0x4B,0x43,0x4B, + 0x19,0xCA,0x05,0x4B,0x40,0x4B,0x11,0x81,0x19,0x8A,0x00,0x4B,0x40,0x4B,0x11,0x09, + 0x19,0x8A,0x00,0x4B,0x4F,0x7A,0x18,0xF9,0x40,0x4B,0x98,0x81,0xD8,0x53,0x08,0x01, + 0x1F,0xD2,0x10,0x13,0xE3,0x48,0x4A,0x21,0x98,0xE6,0x4F,0x5A,0x02,0x17,0xE0,0x00, + 0x10,0x42,0x94,0x16,0x42,0x53,0x3B,0x90,0xAC,0xCE,0x97,0x05,0xE8,0x85,0x07,0x00, + 0x00,0x00,0x06,0x42,0x00,0x01,0x00,0x42,0x18,0x00,0x04,0x42,0x10,0x00,0x00,0x42, + 0x30,0x04,0x05,0x08,0x00,0x20,0x00,0x01,0x50,0x07,0x03,0x00,0xAC,0x9D,0x87,0x1D, + 0x21,0x01,0x40,0x12,0xA0,0x04,0x80,0x14,0xE0,0x03,0x6C,0x0D,0x7E,0xFA,0xB8,0x01, + 0xEE,0x00,0x92,0x35,0x00,0x0F,0x80,0x0F,0xDB,0x8F,0xD0,0xC3,0x40,0x01,0x88,0x1E, + 0xC4,0x14,0xE0,0x03,0x17,0x82,0x9D,0xB6,0xC4,0x14,0xE0,0x03,0x10,0x82,0x9D,0x06, + 0x20,0x11,0x00,0x01,0x90,0xC3,0x43,0xB2,0x46,0x0B,0x14,0x79,0x00,0x8A,0x48,0x09, + 0x88,0xA6,0x08,0x01,0x0E,0x0B,0x44,0x0B,0x33,0x52,0xE1,0x20,0xE7,0x68,0x93,0x25, + 0x80,0x8B,0x60,0x11,0x8B,0x56,0x30,0x5A,0xC8,0xCB,0xD0,0x1C,0x10,0x8A,0x8C,0x2E, + 0xC8,0xCB,0xD2,0x24,0x10,0x8A,0x8C,0x0E,0x08,0x09,0x88,0x04,0x0A,0x01,0x0F,0x0B, + 0x0C,0x01,0x08,0x0B,0x0C,0x81,0x00,0x0B,0x44,0x0B,0x12,0x01,0x1A,0x8A,0x00,0x0B, + 0x66,0x11,0x88,0x56,0xC0,0x04,0x80,0x2D,0xE8,0x85,0x07,0x00,0x00,0xC0,0x04,0x01, + 0x80,0x01,0x06,0x42,0xA8,0x85,0x53,0x7A,0x58,0x7A,0x40,0xA3,0x41,0xEB,0x30,0x32, + 0xA7,0x01,0x46,0x13,0xF8,0x5B,0x49,0x01,0x81,0x0E,0xF0,0x5B,0x4F,0x13,0xB7,0x01, + 0xC8,0x8B,0x4F,0x01,0x84,0x0E,0x00,0xC8,0xC0,0x50,0x0C,0x01,0x01,0x37,0x50,0x06, + 0x33,0x22,0x40,0x6B,0xE2,0x00,0xE4,0x48,0x91,0x4D,0x06,0x2C,0x17,0xCA,0x9C,0xB6, + 0xE8,0x85,0x03,0x00,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0xA8,0x85,0x57,0xFA, + 0x00,0x58,0x42,0x93,0x74,0xF2,0x90,0x01,0x44,0xAB,0x42,0xA3,0xC1,0x50,0x47,0x9B, + 0xC0,0x28,0x23,0x01,0xF9,0xF3,0x00,0x77,0x40,0x8C,0x40,0x3C,0x1E,0x09,0xD8,0x48, + 0x90,0x4D,0x18,0x5A,0x48,0x01,0xE0,0x16,0x10,0x5A,0x4A,0xB2,0x00,0x5A,0x90,0xCD, + 0x20,0x58,0x70,0xD8,0x84,0xCE,0xC8,0x01,0x90,0x4D,0x18,0x09,0x18,0xD8,0x22,0x78, + 0x70,0xF8,0x81,0x7E,0xC8,0x01,0x94,0x4D,0x00,0xD8,0x22,0x78,0x70,0xF8,0x81,0x4E, + 0xC8,0x01,0x94,0x4D,0x1A,0x19,0x18,0xD8,0x21,0x78,0x70,0xF8,0x86,0x16,0x90,0x4D, + 0x39,0xF1,0x1F,0xCA,0x47,0xBC,0xC0,0xD8,0x01,0x9C,0x80,0x4B,0xE3,0x00,0xE4,0x68, + 0xE3,0x90,0xE4,0x20,0x95,0x25,0x17,0xA2,0x9F,0x76,0xEE,0x85,0x00,0x20,0x00,0x01, + 0x00,0x40,0x00,0x01,0xF8,0xF7,0x07,0x00,0xAA,0x85,0x47,0x3A,0x82,0x2D,0xEC,0x33, + 0x40,0x32,0x22,0x01,0x47,0x03,0x10,0xF9,0x86,0x01,0xC3,0x2B,0x08,0x29,0x40,0x1D, + 0xBD,0xEF,0xCF,0xBF,0x42,0x12,0x4A,0x1A,0xC5,0x53,0x50,0x59,0x82,0x1E,0xF0,0x00, + 0x20,0x00,0x60,0x00,0x88,0xC6,0x77,0x01,0x80,0xBE,0x20,0x01,0x18,0x39,0x4A,0x1D, + 0x31,0x02,0x51,0xEA,0x08,0xD8,0x02,0x77,0x32,0x41,0x19,0x32,0xC7,0xB0,0xC5,0xB0, + 0xDD,0xB3,0x3D,0xB0,0xA8,0x2E,0x80,0x43,0xE7,0x20,0x93,0x25,0xE0,0x48,0x62,0x29, + 0x82,0x1E,0xE0,0x00,0x95,0x05,0x16,0x42,0x99,0x76,0x7F,0x7A,0xA0,0x0C,0x30,0x01, + 0x60,0x82,0x69,0x1D,0xB8,0x01,0x06,0xE7,0x50,0x15,0x90,0x04,0xC0,0x43,0x71,0x01, + 0x30,0x1A,0x89,0x76,0x10,0x01,0x30,0x8A,0x87,0x07,0xE0,0x97,0xD8,0xC3,0xC9,0x0C, + 0x4E,0x00,0x0E,0x00,0x1B,0x42,0x88,0x03,0x03,0x59,0xE5,0x68,0x8F,0x03,0xED,0x20, + 0x00,0x2F,0x10,0x01,0x30,0x8A,0x80,0x07,0xE3,0x1F,0xE7,0x68,0xEB,0x20,0xE3,0xB0, + 0x90,0xB5,0xC7,0x0C,0x16,0x32,0x9C,0xFE,0xDC,0xC3,0x29,0x01,0x48,0x08,0x86,0x96, + 0xC9,0x0C,0x80,0x03,0x48,0x01,0x80,0x36,0xE5,0x00,0xDB,0xCB,0xE5,0x20,0x15,0x59, + 0x81,0x0B,0x80,0x13,0x05,0x2F,0xD8,0xD3,0x83,0x13,0x8B,0x2B,0xED,0x20,0x0D,0x59, + 0x83,0x0B,0xE1,0x20,0x00,0x2F,0xC0,0x0C,0x40,0x09,0xC8,0x16,0x01,0x59,0x85,0x03, + 0x39,0xBF,0x37,0x02,0xBF,0xFF,0xC7,0xC7,0x4A,0x82,0x40,0x43,0x10,0x01,0x1A,0x82, + 0x00,0x43,0x4A,0x7A,0x41,0x43,0x1A,0x42,0x00,0x43,0x42,0x72,0x42,0x0B,0x40,0x48, + 0x00,0x48,0x02,0x0B,0x07,0x51,0xB8,0xF7,0xF5,0x7F,0xC9,0xC3,0x08,0x01,0x19,0x42, + 0x88,0xC3,0x85,0x2D,0xE8,0x85,0x07,0x00,0x00,0xC0,0x04,0x01,0x00,0x40,0x00,0x01, + 0xE8,0x60,0x02,0x00,0x00,0x00,0x01,0x01,0x08,0x80,0x03,0x01,0x00,0x00,0x06,0x42, + 0x80,0x01,0x06,0x42,0xF8,0x00,0x06,0x42,0xAC,0x85,0x87,0x4D,0x30,0x22,0x28,0x01, + 0x40,0x82,0xAA,0x24,0xA8,0x1C,0x40,0x03,0x32,0x7A,0xE9,0x0B,0xE9,0x03,0x30,0x72, + 0x18,0x42,0x62,0x09,0x80,0x14,0x80,0x46,0x60,0x29,0x88,0x5E,0x6A,0x5A,0x72,0x52, + 0xE0,0x78,0x43,0x2D,0xBD,0xFF,0xC7,0xC7,0x02,0x67,0x70,0x3A,0x6D,0x42,0xE2,0xB0, + 0xE7,0x78,0x3B,0xB7,0x60,0x21,0x88,0x2E,0x68,0x1A,0x42,0x2D,0xAF,0x51,0xB8,0xFF, + 0xC3,0xFF,0xF3,0x70,0x40,0x1A,0x0A,0x01,0x82,0x44,0x90,0x0B,0xC0,0x44,0x18,0x09, + 0x92,0x1B,0x48,0x0A,0x42,0x43,0x12,0x01,0x1A,0x82,0x00,0x43,0x42,0xFA,0x41,0x0B, + 0x10,0x01,0x1C,0x8A,0x01,0x0B,0x4A,0xF2,0x40,0x43,0x18,0xC2,0x00,0x43,0x08,0x09, + 0x37,0x82,0xB8,0xFF,0xF0,0x5F,0x43,0x09,0x88,0x96,0x62,0x21,0x88,0xE6,0x10,0x09, + 0x91,0x04,0x30,0x42,0x18,0x01,0xC8,0x14,0x83,0x0F,0xD0,0x97,0x10,0x09,0x90,0x04, + 0x10,0x01,0x08,0x59,0x40,0x2D,0x30,0x9A,0x83,0x0F,0xD0,0x57,0x10,0x09,0x90,0x04, + 0x10,0x01,0x08,0x71,0x30,0x82,0x31,0x9A,0x83,0x0F,0xD0,0x17,0x10,0x09,0x90,0x04, + 0x10,0x01,0x08,0xD1,0x41,0x5A,0x01,0x07,0x60,0x09,0x80,0x0E,0x61,0x29,0x88,0x7E, + 0x10,0x11,0x90,0x04,0x11,0x09,0x30,0x42,0x18,0x01,0xC8,0x14,0x82,0x0F,0xD0,0x87, + 0x10,0x11,0x90,0x04,0x11,0x01,0x30,0xC2,0x30,0x9A,0xC8,0x14,0x82,0x0F,0xD0,0x47, + 0x10,0x09,0x90,0x04,0x10,0x01,0x08,0x21,0x40,0x2D,0x30,0x9A,0x82,0x0F,0xD0,0x07, + 0x10,0x09,0x90,0x04,0x12,0x01,0x08,0x81,0x30,0x82,0x19,0x01,0x81,0x0F,0xD0,0xC7, + 0x10,0x09,0x90,0x04,0x10,0x01,0x08,0x71,0x30,0x9A,0xC0,0x24,0x81,0x0F,0xD0,0x87, + 0x10,0x09,0x90,0x04,0x10,0x01,0x08,0x71,0x18,0x09,0xC0,0x1C,0x81,0x0F,0xD0,0x47, + 0xC0,0x44,0x08,0x01,0x90,0x0B,0x40,0x72,0x47,0x1B,0x10,0x01,0x42,0xD8,0x02,0xD8, + 0x00,0x1B,0x40,0x52,0x0C,0x13,0x02,0x0B,0x44,0x0B,0x12,0x01,0x1A,0x8A,0x00,0x0B, + 0x87,0x4D,0xE8,0x85,0x00,0x40,0x00,0x01,0x40,0x60,0x04,0x01,0x20,0x40,0x02,0x01, + 0x08,0x80,0x03,0x01,0x08,0xC0,0x02,0x01,0x00,0x00,0x06,0x42,0x80,0x01,0x06,0x42, + 0xF8,0x00,0x06,0x42,0x50,0x10,0x00,0x01,0xA8,0xF5,0x37,0x3A,0x40,0xCA,0x81,0x0C, + 0x41,0xCA,0x49,0xD2,0x42,0x03,0xE8,0x2B,0xE8,0x23,0x00,0x01,0xA0,0x43,0x34,0x72, + 0xB3,0x01,0x96,0x83,0x11,0x09,0x90,0x93,0x4A,0xAA,0x41,0x43,0x18,0x01,0x1A,0xC2, + 0x01,0x43,0x42,0xA2,0x44,0x0B,0x1A,0x01,0x1A,0xCA,0x00,0x0B,0x48,0x92,0x41,0x43, + 0x18,0x82,0x00,0x43,0x37,0x82,0xC1,0x01,0x5A,0x03,0x84,0x01,0xE7,0x0B,0x48,0x79, + 0x80,0x8E,0xE1,0x03,0x41,0x69,0x8E,0x0E,0x08,0xA9,0x00,0x91,0xBE,0xFF,0xEF,0x37, + 0x41,0x09,0x88,0xBE,0x33,0x02,0x19,0x42,0x00,0x08,0x12,0x09,0x88,0x14,0x90,0x04, + 0x90,0x4D,0x1C,0x01,0xC0,0x0C,0x80,0x0F,0xC8,0x5F,0x16,0x09,0x90,0x04,0xC8,0x14, + 0x11,0x01,0x40,0x12,0x90,0x4D,0x34,0x9A,0x86,0x0F,0xC8,0x17,0xC8,0x08,0x13,0x09, + 0x00,0x48,0x8A,0x41,0x91,0x04,0x30,0xC2,0x10,0x01,0x00,0xC7,0x08,0xA1,0x00,0x91, + 0xBD,0xFF,0xEF,0x27,0x40,0x09,0x88,0xAE,0x13,0x09,0x18,0x62,0x20,0x00,0x63,0x08, + 0x90,0x04,0xC0,0x0C,0x00,0x5F,0x08,0xB1,0x07,0x91,0xB8,0xFF,0xE8,0xBF,0x44,0x09, + 0x88,0x46,0x10,0x09,0xCA,0x08,0x03,0x48,0x30,0xC2,0x89,0x41,0x90,0x04,0x18,0x09, + 0x84,0x0F,0xC8,0xF7,0x09,0x01,0x90,0x8B,0x40,0x5A,0x40,0x1B,0x12,0x01,0x47,0xD8, + 0x00,0xD8,0x02,0x1B,0x42,0x3A,0x08,0x13,0x02,0x0B,0x44,0x13,0x08,0x01,0x1C,0x52, + 0x07,0x13,0xEA,0xF5,0x20,0x40,0x02,0x01,0x00,0x40,0x00,0x01,0x00,0xC0,0x04,0x01, + 0x00,0x00,0x06,0x42,0x80,0x01,0x06,0x42,0xF8,0x00,0x06,0x42,0x08,0x80,0x03,0x01, + 0xA8,0x85,0x63,0xEA,0xC8,0x03,0x43,0x09,0x83,0x16,0xC8,0x03,0x40,0x29,0x88,0x6E, + 0x84,0x0F,0xC0,0xB7,0x69,0xCA,0xC0,0x43,0x40,0x11,0x98,0x26,0xCF,0x03,0xBB,0xFF, + 0xF0,0x9F,0x05,0x01,0x02,0x07,0xE0,0x00,0x83,0x43,0xE9,0x85,0xC8,0x03,0x43,0x21, + 0x8F,0x26,0xB8,0xFF,0xF0,0x4F,0x05,0x19,0x8B,0x03,0xEB,0x85,0xC8,0x03,0x43,0x31, + 0x83,0xDE,0xCF,0x03,0x47,0x19,0x80,0xC6,0x46,0x5A,0xC0,0x01,0xE8,0x03,0x42,0x01, + 0x8F,0x2E,0xD8,0x03,0x40,0x31,0x98,0x3E,0xD8,0x03,0x31,0x00,0xA8,0x26,0x40,0x32, + 0xC6,0x01,0xCD,0x03,0x40,0x01,0x80,0x1E,0x4D,0x2A,0x00,0x59,0x83,0x43,0xE8,0x85, + 0xBF,0xFF,0xEF,0x57,0xE8,0x85,0x03,0x00,0x08,0xC0,0x02,0x01,0x00,0x60,0x00,0x01, + 0x00,0x00,0x01,0x01,0xA8,0x85,0x40,0x22,0x0C,0x01,0x00,0x0B,0x44,0x1A,0xA0,0x0B, + 0xE0,0x03,0x86,0x07,0xD0,0xCF,0xEF,0x85,0x10,0x00,0x00,0x42,0x00,0xC0,0x04,0x01, + 0xAA,0x85,0x47,0xA2,0x50,0xA2,0x42,0x03,0x08,0x81,0x41,0x93,0xE4,0x62,0x08,0x29, + 0xE0,0x5A,0x34,0x0A,0x88,0x01,0x4F,0xF0,0xFE,0xAB,0xC8,0x5B,0x86,0x5D,0xF4,0x93, + 0x80,0x01,0x9C,0x4C,0x96,0x54,0x50,0x3B,0x00,0x09,0xA0,0x44,0x90,0x43,0xCC,0x43, + 0x43,0x09,0xC8,0xEE,0x09,0x09,0x30,0x12,0x30,0x42,0x80,0x07,0xD8,0x6F,0x09,0x01, + 0x37,0x42,0xBB,0xFF,0xEB,0x3F,0xE2,0x20,0x90,0x25,0x77,0x11,0x88,0xEE,0x08,0x01, + 0x00,0x19,0x80,0x07,0xC8,0xFF,0x04,0x01,0x81,0x07,0xD0,0x37,0xC0,0x4C,0x40,0x01, + 0x89,0x5E,0x40,0xE2,0x08,0x09,0x40,0x03,0x57,0xDA,0x81,0x01,0x88,0x0B,0x46,0x83, + 0xF0,0x20,0xEB,0x03,0x96,0x25,0xCF,0x38,0x01,0x27,0x40,0xB2,0x08,0x01,0x40,0x03, + 0x86,0x01,0x8F,0x0B,0x00,0x11,0x80,0x07,0xD0,0x7F,0xC0,0x54,0x11,0x22,0x94,0x0E, + 0x40,0x82,0x41,0x03,0x80,0x01,0xA1,0x23,0x30,0x12,0x09,0x01,0x00,0x09,0x80,0x07, + 0xD0,0xDF,0x77,0x09,0x8B,0x2E,0xE0,0x00,0x90,0x15,0x0E,0x01,0x00,0x09,0x80,0x07, + 0xD1,0x9F,0x37,0x0A,0x00,0x11,0x80,0x07,0xC9,0x6F,0xEB,0xC2,0x67,0x3A,0x09,0x03, + 0x86,0x07,0xF8,0xF7,0x05,0x41,0x00,0x03,0x47,0x03,0x09,0xF9,0x88,0x19,0x18,0x42, + 0x00,0x03,0x01,0xB7,0x7D,0xFA,0x08,0x29,0x41,0xC3,0x81,0x01,0xA0,0x0B,0x70,0x09, + 0x88,0x26,0x08,0x09,0x30,0x12,0x31,0x42,0x86,0x07,0xD0,0xB7,0x00,0x01,0x80,0x07, + 0xC8,0xDF,0x0E,0x01,0x00,0x19,0x80,0x07,0xC9,0x6F,0x42,0xC3,0x0F,0x01,0x80,0x01, + 0x88,0x0B,0x4E,0xA2,0x10,0x21,0x47,0x4B,0xC2,0x44,0xE0,0x92,0x50,0x11,0x88,0xA6, + 0x1A,0x42,0x03,0x10,0xC0,0x4C,0x40,0x01,0x80,0x16,0x40,0x7A,0x46,0x03,0x58,0x04, + 0x8A,0x01,0x04,0x00,0x40,0x4B,0xC2,0x80,0xC3,0x00,0x02,0x50,0x30,0x4A,0x03,0x07, + 0x07,0x0F,0xB8,0xE7,0xF8,0x3F,0x80,0x5D,0xE8,0x85,0xCF,0x4C,0x18,0x42,0x4B,0x01, + 0x80,0x16,0x48,0x2A,0x46,0x4B,0x58,0x4C,0xC4,0x00,0x92,0x0D,0x37,0x42,0xBB,0xFF, + 0xE7,0x2F,0x3F,0x87,0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0x00,0x01,0x00,0x42, + 0xAC,0xFD,0x87,0x0D,0x50,0x01,0x80,0x0E,0x00,0x01,0x00,0x07,0x00,0x09,0x30,0x01, + 0x78,0x3A,0x81,0x04,0x00,0x3F,0xC2,0x24,0x00,0x88,0xC5,0x68,0x30,0x92,0x09,0x19, + 0xC0,0x04,0x80,0x07,0xD1,0x4F,0x04,0x41,0xBE,0xF7,0xDF,0x37,0x20,0x09,0x00,0x4F, + 0x60,0x81,0x99,0x3E,0x00,0xF9,0x4F,0xF2,0x82,0x11,0xC8,0x01,0x1B,0x43,0x40,0x00, + 0x18,0x43,0x02,0x17,0x42,0xD2,0xC0,0x01,0x1F,0x23,0x02,0xF9,0x81,0x89,0x17,0xC3, + 0x07,0x11,0xB8,0xF7,0xD8,0x8F,0x45,0xBA,0x42,0x03,0x80,0x01,0xF0,0x03,0x42,0x01, + 0x80,0x3E,0x00,0x51,0xBD,0xF7,0xDF,0x47,0x40,0x43,0x41,0x03,0x30,0x00,0xA8,0x76, + 0x07,0x4F,0x00,0xF9,0x81,0x89,0x14,0xC3,0x07,0x09,0xB8,0xF7,0xD9,0xEF,0x44,0x43, + 0x40,0x03,0x30,0x00,0xA3,0x1E,0xE0,0x20,0x93,0x25,0x67,0xF9,0xC8,0x86,0xC6,0x14, + 0x30,0x92,0x01,0x24,0xC0,0x14,0x08,0x09,0xE0,0x00,0x84,0x14,0xC0,0x04,0x80,0x07, + 0xD3,0x5F,0xE2,0xB0,0x90,0xB5,0xC7,0x0C,0x15,0x32,0x9C,0xA6,0x87,0x2D,0xE8,0x85, + 0x00,0x01,0x02,0x42,0x00,0x40,0x00,0x01,0xA8,0x85,0x33,0x22,0x30,0x6A,0x30,0x82, + 0x84,0x07,0xF0,0x97,0x31,0x4A,0x31,0x02,0xBA,0xFF,0xE7,0xA7,0xE8,0x85,0x03,0x00, + 0xA8,0x85,0x6B,0xE2,0x21,0x01,0x40,0x43,0x86,0x01,0x8F,0x23,0x00,0x11,0x80,0x07, + 0xC9,0x9F,0x41,0x43,0x08,0x81,0xA1,0x62,0xE8,0x0B,0xEA,0x13,0x08,0x48,0x60,0xB2, + 0x1F,0x8A,0x00,0x0B,0x86,0x01,0x54,0x03,0xC7,0x03,0x08,0x03,0x10,0x01,0x30,0x8A, + 0x00,0x09,0x80,0x07,0xD0,0xCF,0x40,0x8A,0x44,0x03,0x80,0x01,0xC8,0x03,0x4A,0x00, + 0x40,0x09,0x88,0x26,0x10,0x09,0x08,0x01,0x30,0x82,0x80,0x07,0xD0,0x6F,0x08,0x01, + 0x00,0x11,0x80,0x07,0xC0,0x3F,0x84,0x07,0xF0,0xDF,0x4F,0x4A,0x40,0x43,0x10,0x11, + 0x18,0x82,0x00,0x43,0x05,0x41,0x00,0x03,0x47,0x03,0x09,0xF9,0x88,0x19,0x18,0x42, + 0x03,0x03,0xE9,0x85,0x00,0x20,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x40,0x00,0x01, + 0x18,0x00,0x04,0x42,0xA9,0xC5,0x6F,0x8A,0x40,0x43,0x31,0x0A,0x82,0x01,0xCF,0x13, + 0x50,0x09,0x80,0x1E,0x8E,0x01,0xD9,0x4B,0x48,0x09,0xC0,0x0E,0x08,0x11,0x00,0x07, + 0x08,0x19,0x88,0x0B,0xBD,0xFF,0xFF,0x67,0x40,0x4A,0x41,0x03,0xEA,0x0B,0xE8,0x03, + 0x19,0x0A,0x42,0x43,0x94,0x55,0x80,0x01,0x46,0x23,0x44,0x1B,0x40,0x0B,0x02,0x9F, + 0xC0,0x03,0x31,0x30,0xA8,0x3E,0x40,0x74,0x27,0xB8,0x67,0xF8,0x5F,0xB0,0x0B,0xB0, + 0xC0,0x80,0x01,0x7C,0x96,0x05,0x38,0x30,0x8A,0x06,0x10,0x02,0x04,0xC4,0xE0,0xD8, + 0xE4,0x20,0xE3,0x48,0xF0,0x90,0x92,0x95,0x57,0x01,0xE0,0x4E,0x41,0x43,0x81,0x01, + 0xD8,0x03,0x46,0x09,0x88,0x0E,0x21,0x01,0x30,0x19,0x38,0x11,0x40,0x4B,0x01,0x01, + 0x8C,0x01,0xA1,0x43,0x85,0x07,0xF0,0xA7,0x40,0x43,0x61,0x19,0x9F,0x16,0x80,0x01, + 0x88,0x33,0x00,0x0F,0x80,0x01,0x8F,0x3B,0xBB,0xFF,0xFF,0x97,0xE7,0x20,0x93,0x25, + 0x67,0x21,0x98,0x5E,0x40,0x52,0x40,0x03,0xEA,0x0B,0xE8,0x03,0x19,0x0A,0x42,0x43, + 0x04,0x48,0x82,0x01,0x47,0x03,0xBE,0xE7,0xF1,0x57,0x42,0x4B,0x8E,0x01,0xD9,0x43, + 0x40,0x41,0x96,0x0E,0xE6,0x00,0x9A,0x43,0xE8,0xC5,0x07,0x00,0x00,0x20,0x00,0x01, + 0x00,0x40,0x00,0x01,0x40,0x12,0x48,0x0B,0x10,0x21,0x18,0x8A,0x0B,0x0B,0x38,0x82, + 0x68,0x07,0x00,0x07,0xAC,0xC5,0x37,0x22,0x45,0x6A,0x19,0x41,0x41,0x2B,0x40,0x6A, + 0xF8,0x63,0x41,0x03,0x30,0x72,0x34,0x3A,0xB8,0x01,0xC6,0xDA,0x4F,0xF3,0x43,0xD3, + 0x80,0x01,0x9F,0x04,0x1E,0x0A,0xCB,0x03,0xC0,0xD8,0x42,0x01,0x85,0x2E,0x00,0x00, + 0xC7,0x10,0x5C,0x44,0xF6,0x4B,0xC7,0x18,0xC8,0x70,0x04,0x79,0x13,0x00,0x30,0x0A, + 0x49,0x01,0x80,0x0E,0x48,0x11,0x80,0x7E,0x48,0x31,0x80,0x0E,0x49,0x39,0x88,0x6E, + 0xEB,0x4B,0xE9,0x5B,0xF4,0x48,0x92,0x4D,0x18,0xCA,0xDA,0x04,0xF6,0x63,0xC1,0x58, + 0x4B,0xD3,0x37,0x0A,0x49,0x39,0x80,0x0E,0x33,0x8A,0xE3,0xAA,0x4A,0xB2,0x08,0x6B, + 0x08,0x01,0x00,0x37,0xC2,0xEB,0x50,0x06,0x19,0x2A,0x00,0xAB,0xE2,0xD8,0xE2,0x48, + 0x95,0x4D,0x16,0x0A,0x9F,0xB6,0xEF,0xC5,0x70,0x7A,0x00,0x01,0x10,0x83,0x4F,0x7A, + 0x45,0x6B,0x40,0x68,0x00,0x68,0x05,0x6B,0x01,0x43,0x02,0x83,0x40,0x5B,0x28,0x81, + 0x18,0x5A,0x05,0x5B,0x44,0x5B,0x28,0x01,0x18,0x5A,0x01,0x5B,0x08,0x01,0x00,0x1F, + 0x52,0x46,0xE0,0x48,0x06,0xC3,0x90,0x4D,0x17,0x0A,0x9D,0xCE,0xE8,0xC5,0x07,0x00, + 0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0x00,0x01,0x00,0x42,0x18,0x00,0x04,0x42, + 0x94,0x15,0x3A,0x00,0x77,0x18,0x06,0xF9,0x04,0xC2,0x3C,0x48,0x74,0x48,0x00,0xCA, + 0x50,0x01,0xD0,0x5E,0x38,0x90,0x78,0x90,0xD4,0x41,0x40,0x98,0x54,0x42,0x00,0xD8, + 0xC6,0xD0,0x4C,0x9B,0x18,0x1A,0x1C,0x5A,0x0B,0x9B,0x3E,0x82,0x40,0x98,0x54,0x2A, + 0x04,0xD8,0xC4,0xD0,0x44,0x9B,0x18,0x1A,0x18,0x5A,0x00,0x9B,0x38,0x82,0x03,0x00, + 0x68,0x07,0x00,0x07,0x20,0x07,0x00,0x07,0xAA,0x85,0x4F,0x62,0x58,0x62,0x42,0x63, + 0x41,0xDB,0x30,0x0A,0x88,0x01,0x46,0x53,0xA4,0x01,0x47,0x4B,0xFF,0xDB,0xC8,0x23, + 0x60,0x01,0x80,0x16,0x05,0xE0,0xC4,0x10,0xC0,0x48,0x46,0x01,0x88,0xE6,0x38,0x01, + 0x00,0xBF,0x40,0x83,0xE8,0x00,0x30,0x22,0xE5,0x01,0x5A,0x2B,0xC1,0x73,0x18,0xAA, + 0x1F,0x2B,0x5D,0x2B,0xC5,0x73,0x18,0xAA,0x1A,0x2B,0x47,0x23,0xC5,0x6B,0x18,0x62, + 0x00,0x23,0x42,0x23,0xC0,0x6B,0xE8,0x90,0xE5,0x48,0x1A,0x62,0x03,0x23,0xE0,0xF8, + 0x94,0xFD,0x17,0xFA,0x9F,0x2E,0xEF,0x85,0x40,0x31,0x88,0x4E,0x01,0x01,0x50,0xAA, + 0x34,0x0A,0xC0,0x18,0x00,0xCB,0xE8,0x00,0x95,0x05,0x46,0xE9,0x9F,0xCE,0xEF,0x85, + 0x40,0x09,0x88,0xE6,0x38,0x01,0x00,0xBF,0x40,0x83,0xE8,0x00,0x32,0x22,0xE0,0x01, + 0x58,0x2B,0xC5,0x73,0x1D,0xAA,0x1D,0x2B,0x58,0x2B,0xC7,0x73,0x1F,0xAA,0x1D,0x2B, + 0x40,0x23,0xC2,0x6B,0x1A,0x62,0x05,0x23,0x40,0x23,0xC0,0x6B,0xEA,0x90,0xE0,0x48, + 0x18,0x62,0x01,0x23,0xE7,0xF8,0x93,0xFD,0x17,0xFA,0x9C,0x2E,0xE8,0x85,0x47,0x11, + 0x88,0xE6,0x38,0x01,0x00,0xBF,0x40,0x83,0xE8,0x00,0x30,0x22,0xE5,0x01,0x5A,0x2B, + 0xC5,0x73,0x18,0xAA,0x1F,0x2B,0x5D,0x2B,0xC5,0x73,0x18,0xAA,0x1A,0x2B,0x47,0x23, + 0xC1,0x6B,0x18,0x62,0x00,0x23,0x42,0x23,0xC0,0x6B,0xE8,0x90,0xE5,0x48,0x1A,0x62, + 0x03,0x23,0xE0,0xF8,0x94,0xFD,0x17,0xFA,0x9F,0x2E,0xEF,0x85,0x47,0x19,0x88,0xE6, + 0x38,0x01,0x00,0xBF,0x40,0x83,0xE8,0x00,0x32,0x22,0xE0,0x01,0x58,0x2B,0xC5,0x73, + 0x1D,0xAA,0x1D,0x2B,0x58,0x2B,0xC7,0x73,0x1F,0xAA,0x1D,0x2B,0x40,0x23,0xC2,0x6B, + 0x1A,0x62,0x01,0x23,0x40,0x23,0xC0,0x6B,0xEA,0x90,0xE0,0x48,0x18,0x62,0x01,0x23, + 0xE7,0xF8,0x93,0xFD,0x17,0xFA,0x9C,0x2E,0xE8,0x85,0x07,0x00,0x00,0x20,0x00,0x01, + 0x00,0x40,0x00,0x01,0x80,0x00,0x00,0x42,0x08,0x08,0x42,0x42,0x41,0x13,0x18,0x01, + 0x04,0xD2,0x90,0x41,0x04,0x13,0x10,0xD0,0x1A,0x8A,0x08,0x0B,0x40,0x0B,0x42,0x0B, + 0x14,0x41,0x18,0x8A,0x00,0x0B,0x08,0x01,0x03,0x0B,0x3C,0x82,0x10,0x00,0x00,0x42, + 0xA8,0xC5,0x67,0xFA,0x43,0x23,0xA1,0x01,0xC4,0x23,0x17,0x22,0xC9,0xB6,0x21,0x41, + 0x18,0x02,0x63,0xE2,0x30,0xEA,0xC8,0x20,0x02,0x39,0x0A,0x00,0xC5,0x20,0x51,0x04, + 0x50,0x3C,0x4F,0x09,0x8D,0x26,0x50,0x04,0x0A,0xC9,0x08,0x48,0xD4,0x40,0x90,0x05, + 0x50,0x09,0x88,0x26,0x50,0x0C,0x17,0x29,0x12,0x90,0xD0,0x88,0x90,0x7D,0x0C,0x01, + 0x97,0x05,0xB8,0xF7,0xD0,0xDF,0x33,0x32,0x09,0x09,0x90,0xC5,0xBB,0xF7,0xD7,0xB7, + 0xD8,0x0B,0x0F,0x50,0x4A,0x48,0x00,0x48,0x19,0x52,0x80,0x53,0x4B,0x88,0x81,0x4B, + 0x4D,0x08,0x80,0x4B,0x39,0x00,0x08,0x88,0x78,0x00,0x18,0x0A,0x87,0x4B,0xE7,0x03, + 0x88,0x43,0xC1,0x34,0xC8,0x34,0xC0,0x03,0xE8,0x00,0x82,0x43,0xE8,0xC5,0x07,0x00, + 0x00,0x40,0x00,0x01,0x08,0x80,0x03,0x01,0xA9,0x85,0x5F,0x72,0x00,0xA0,0x44,0xDB, + 0x36,0xFA,0x98,0x01,0x40,0xF3,0x44,0xEB,0xC1,0xB0,0xCD,0x68,0x40,0x09,0x88,0x1E, + 0xBF,0x01,0x5C,0xC3,0x40,0xDB,0x02,0x1F,0x40,0x11,0x88,0x1E,0x48,0xC3,0x54,0xDB, + 0xCC,0x28,0xC0,0xF0,0x41,0x43,0xC1,0x93,0xF8,0x18,0x48,0x01,0x8C,0x5E,0x40,0x0B, + 0x1C,0x8A,0x04,0x0B,0x44,0x0B,0x1A,0x8A,0x00,0x0B,0x42,0x0B,0x18,0x8A,0x00,0x0B, + 0x44,0xC3,0x18,0x82,0x00,0x67,0x48,0x09,0x8A,0x66,0x40,0x0B,0x1A,0x8A,0x04,0x0B, + 0x44,0x0B,0x1C,0x8A,0x00,0x0B,0x44,0x0B,0x18,0x8A,0x04,0x0B,0x40,0xC3,0x18,0x82, + 0x07,0xC3,0xE8,0x85,0x48,0x11,0x88,0x46,0x44,0xCB,0x18,0x8A,0x00,0xCB,0x40,0x0B, + 0x18,0x8A,0x04,0x0B,0x40,0x0B,0x1A,0x8A,0x00,0x4F,0x48,0x21,0x88,0x66,0x40,0xCB, + 0x18,0x8A,0x04,0xCB,0x44,0x0B,0x18,0x8A,0x02,0x0B,0x40,0x0B,0x1A,0x8A,0x04,0x0B, + 0x44,0x0B,0x1C,0x8A,0x07,0x0B,0xEC,0x85,0x4F,0x19,0x88,0xE6,0x44,0xCB,0x18,0x8A, + 0x00,0xCB,0x40,0x0B,0x18,0x8A,0x04,0x0B,0x44,0x0B,0x1A,0x8A,0x04,0x0B,0x42,0x0B, + 0x1F,0x8A,0x38,0x7F,0x00,0x20,0x00,0x01,0xA8,0xC5,0x0F,0x01,0x60,0x12,0x8A,0x04, + 0x58,0x13,0x35,0x1A,0x31,0x0A,0x29,0x01,0x70,0x02,0x3A,0x31,0x02,0x81,0x90,0x01, + 0x8F,0x01,0xBF,0xE7,0xE9,0x3F,0x4C,0x0B,0xA3,0x90,0xB8,0x48,0x4B,0xD3,0xF8,0x48, + 0x31,0x09,0x61,0x49,0x83,0x71,0x49,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B,0x4B, + 0xAB,0x91,0xC9,0x49,0x4B,0xE3,0x32,0x4B,0x00,0x48,0x03,0x39,0x00,0xAF,0x80,0x07, + 0xCF,0xAF,0xED,0xC5,0x05,0x51,0xA0,0x03,0xEC,0xC5,0xCF,0x43,0x10,0x21,0x18,0x82, + 0x8F,0x43,0xEC,0xC5,0x10,0x11,0x00,0x2F,0x02,0x01,0x88,0x43,0x41,0x83,0x19,0x42, + 0x00,0x87,0x12,0x09,0x8A,0x53,0x02,0x17,0x02,0x19,0x88,0x43,0xE8,0xC5,0x17,0x21, + 0x38,0xC7,0x17,0x29,0x38,0xB7,0x17,0x41,0x3A,0xA7,0x8F,0x7B,0x08,0x69,0x06,0x0F, + 0x8F,0x7B,0x0A,0x79,0xA1,0x8B,0x00,0x97,0x4C,0x0A,0x01,0x43,0x45,0x83,0x19,0x42, + 0x00,0x83,0x01,0x21,0xB9,0xF7,0xCF,0xF7,0x07,0x31,0xB8,0xF7,0xC8,0xDF,0x01,0x09, + 0xB9,0xF7,0xCF,0xC7,0x07,0x11,0xB8,0xF7,0xC8,0xAF,0x41,0xD2,0x48,0x13,0x0A,0x69, + 0x1A,0x52,0x08,0x13,0x48,0x13,0x18,0x52,0x0E,0x13,0x40,0x13,0x1E,0x52,0x04,0x13, + 0x44,0x13,0x1C,0x52,0x02,0x13,0x44,0x13,0x1A,0x52,0x04,0x13,0x38,0xF7,0x4F,0x82, + 0x00,0x43,0x04,0x09,0xBE,0xFF,0xF7,0xC7,0x48,0x5A,0x00,0xC1,0x8C,0x01,0xA1,0x43, + 0x3A,0xEF,0x8F,0x7B,0x0E,0x59,0x3D,0x6F,0xC8,0x04,0x48,0x01,0x80,0xF6,0x4D,0x52, + 0x40,0x53,0x30,0x90,0xAE,0x26,0x10,0x81,0x02,0x53,0x10,0x81,0x00,0x53,0x00,0x43, + 0x45,0x83,0x19,0x42,0x07,0x83,0xE9,0xC5,0x00,0xC0,0x03,0x01,0x10,0x00,0x00,0x42, + 0x80,0x01,0x06,0x42,0xF8,0x00,0x06,0x42,0x00,0x00,0x00,0x42,0x4A,0x3A,0x40,0x53, + 0x42,0x3A,0x00,0x53,0xE7,0x13,0x54,0xF9,0x94,0x16,0xE0,0x13,0xE4,0x90,0xA2,0x13, + 0xE0,0x03,0x44,0xC1,0x90,0x0E,0x00,0x01,0x03,0x43,0x3C,0x82,0x10,0x00,0x00,0x42, + 0x00,0xC0,0x04,0x01,0x48,0x32,0x00,0x37,0xC4,0x1B,0x10,0xD2,0x80,0x0E,0x00,0x09, + 0x3A,0x82,0xE3,0x48,0xE0,0x00,0xC2,0x53,0x57,0x01,0x88,0xAE,0x03,0x01,0x38,0x82, + 0x28,0x22,0x03,0x00,0xA8,0xFD,0x0F,0x01,0x83,0x45,0x44,0x8A,0x88,0x14,0x40,0x13, + 0x8B,0x34,0x90,0x01,0x34,0x62,0x34,0x72,0xC0,0xA3,0x06,0x27,0xD7,0x4C,0x00,0xF9, + 0xA2,0x82,0xE2,0x48,0x95,0x4D,0x16,0x0A,0x98,0xC6,0xD7,0x5C,0xC4,0x54,0x10,0x12, + 0xC0,0x16,0x90,0x24,0xC0,0x54,0x00,0x0F,0x80,0x24,0x30,0x82,0x80,0x1C,0x00,0x01, + 0x82,0x2C,0x00,0xCF,0x12,0x01,0x00,0xA7,0x36,0x82,0x03,0x82,0x3A,0x00,0x8E,0x76, + 0x58,0x0A,0xF3,0x44,0x42,0xDB,0x68,0xFA,0x98,0x01,0xE9,0xFB,0x33,0x9A,0x18,0x1A, + 0x04,0xD8,0xCA,0xD8,0x98,0x3C,0x00,0x67,0xDE,0x34,0x00,0x1A,0x38,0xD8,0x8E,0x36, + 0xDA,0x3C,0x00,0x30,0xDD,0xDA,0x14,0x5A,0x90,0x0E,0x30,0xEA,0x32,0x0A,0xE0,0x00, + 0x94,0x05,0x16,0x3A,0xC0,0x86,0x07,0x01,0x5A,0x92,0x02,0x78,0x03,0x7F,0x30,0xAA, + 0x07,0x2A,0x3E,0x68,0x88,0x4E,0x30,0x2A,0x18,0x2A,0xF3,0x44,0x05,0x68,0xCB,0x68, + 0xDC,0x6A,0x17,0xEA,0xC1,0x0E,0x30,0x5A,0x32,0x22,0xE4,0x00,0x90,0x05,0xEE,0x54, + 0x17,0x42,0x9D,0x66,0x28,0xA2,0x8C,0xB6,0xC6,0x14,0xC0,0x00,0x80,0x14,0xC0,0x2C, + 0xDA,0x4C,0xE0,0x00,0x90,0x05,0x86,0x2C,0x32,0x02,0xA3,0xC2,0x18,0x09,0x30,0xC2, + 0xEC,0x34,0x00,0x42,0x1C,0x42,0x91,0x05,0x83,0x34,0x30,0x02,0x03,0x1A,0x34,0x82, + 0x1C,0x1A,0x90,0xC5,0x30,0x32,0xDC,0x24,0xC4,0x2C,0x10,0xC2,0x82,0x26,0xE0,0x90, + 0x90,0x95,0xC6,0x54,0x15,0x12,0x9C,0x3E,0xD0,0x24,0xC0,0x2C,0x15,0x82,0x9C,0x0E, + 0xC0,0x14,0x10,0x01,0x34,0x5A,0x33,0x22,0x80,0xD3,0x30,0x82,0x30,0x9A,0x08,0x01, + 0x33,0x72,0x34,0x4A,0xE0,0x4A,0x00,0x0F,0xE6,0x48,0x92,0x4D,0x36,0xEA,0x00,0x6A, + 0x3F,0x68,0x8F,0xCE,0xED,0x1C,0x10,0x4A,0x98,0xDE,0x40,0x01,0x89,0xA6,0x58,0x52, + 0x10,0xF9,0x07,0x6F,0xC8,0x4C,0xE8,0x54,0xE5,0x4A,0x10,0x4A,0x90,0x26,0x40,0xCB, + 0x88,0x01,0xE9,0x4B,0x10,0x0A,0xC4,0x0E,0xC8,0x4C,0xA0,0x52,0xE6,0x00,0x92,0x05, + 0x17,0x02,0x9D,0x7E,0x87,0x65,0xE8,0x85,0xF6,0x00,0x92,0x05,0x30,0x4A,0xE3,0x4A, + 0x00,0x2F,0x31,0x6A,0x18,0x2A,0xF3,0x44,0x05,0x68,0xCB,0x68,0x07,0x38,0xDA,0x6A, + 0x35,0x72,0xC3,0x50,0x2C,0x09,0x00,0x6A,0x1D,0xEA,0x90,0x5D,0xA3,0x8A,0x29,0x12, + 0x90,0xAE,0xF8,0x5C,0xE5,0x28,0x12,0xEA,0x9C,0x5E,0x30,0xA2,0x08,0x01,0x00,0x27, + 0xFB,0x4C,0xE0,0xAA,0xA2,0xEA,0xE3,0x48,0x95,0x4D,0x16,0x0A,0x99,0xC6,0xE7,0x8A, + 0x07,0x2F,0x90,0x45,0x29,0x01,0xA0,0xAA,0x30,0xAA,0x6B,0x01,0x80,0x7E,0x35,0x6A, + 0x18,0x2A,0xF3,0x44,0x02,0x68,0x03,0x38,0xCF,0x68,0xDD,0x6A,0xD8,0x90,0x2A,0x09, + 0x05,0x6A,0x1C,0x5A,0x31,0x6A,0xE3,0x4A,0xE1,0x48,0xA2,0x4A,0x38,0xFF,0x04,0x00, + 0x00,0x40,0x00,0x01,0xF8,0xFF,0x07,0x00,0x00,0x20,0x00,0x01,0xAF,0x85,0xB8,0xF7, + 0xE8,0x2F,0x02,0x09,0xB8,0xF7,0xF7,0xC7,0xBE,0xF7,0xE7,0xE7,0xB9,0xEF,0xFF,0x37, + 0x40,0xA2,0x40,0x13,0x08,0x09,0x18,0x52,0x00,0x13,0x48,0x13,0x18,0x52,0x0C,0x13, + 0x4C,0x13,0x1A,0x52,0x0E,0x13,0x42,0x13,0x1E,0x52,0x00,0x13,0x40,0x72,0x40,0x0B, + 0x10,0x01,0x19,0x8A,0x00,0x0B,0x00,0xA1,0xBC,0xFF,0xEF,0x37,0x08,0x09,0x00,0x31, + 0xBD,0xFF,0xE7,0xF7,0x08,0x11,0x00,0x21,0xBD,0xFF,0xE7,0xD7,0x07,0x09,0xB8,0xF7, + 0xC0,0x7F,0x04,0x31,0xBC,0xF7,0xC7,0x67,0x07,0x21,0xB8,0xF7,0xC7,0x4F,0xBC,0xF7, + 0xC0,0xAF,0xEC,0x85,0xF8,0x00,0x06,0x42,0x10,0x00,0x00,0x42,0xB0,0x95,0x43,0x1A, + 0x4E,0x1A,0x00,0x43,0x9A,0xFF,0x7D,0x04,0x38,0xF7,0x07,0x00,0x07,0x20,0x28,0xD0, + 0x68,0x07,0x00,0x07,0xAC,0x85,0x4F,0x6A,0x80,0x5D,0x44,0x4B,0x42,0x01,0xE8,0x6B, + 0xE8,0x7B,0x80,0x7E,0x40,0x52,0x0C,0x99,0x07,0x0B,0x1A,0xF9,0x50,0x4A,0x9C,0x81, + 0x10,0x9B,0x06,0x0B,0x07,0xC1,0xBB,0xEF,0xF4,0x3F,0x47,0x3A,0x44,0x03,0x80,0x01, + 0x40,0x23,0x02,0xBF,0x40,0x12,0x0C,0x19,0x04,0x0B,0x0A,0x19,0x04,0x0B,0x40,0x12, + 0x10,0x01,0x40,0x03,0x34,0x8A,0x80,0x01,0x40,0x23,0x06,0x09,0xBC,0xFF,0xEF,0xA7, + 0x30,0x01,0x10,0x09,0x08,0x01,0x40,0x0D,0xBA,0xFF,0xDF,0x77,0xE7,0xB0,0x93,0xB5, + 0x77,0x91,0x99,0xB6,0x48,0xB2,0x43,0x43,0x10,0x11,0x18,0x82,0x03,0x43,0x70,0xB2, + 0x01,0xC9,0x43,0x8B,0xE0,0x02,0x32,0x00,0xAB,0xF6,0x53,0x82,0x40,0x83,0xF0,0x1B, + 0x58,0x01,0x80,0x16,0xEA,0x1B,0xF0,0xD8,0x94,0xFD,0x16,0x29,0xE0,0x92,0x48,0x90, + 0x50,0x11,0x88,0x56,0xF8,0x2B,0x00,0x09,0x8E,0x01,0x8F,0x43,0x08,0x01,0x00,0x19, + 0xBF,0xFF,0xDF,0x47,0x07,0x01,0xB8,0xFF,0xE3,0x7F,0x73,0x3A,0x09,0x01,0x40,0x83, + 0x86,0x01,0x8F,0x0B,0x07,0x11,0xB8,0xFF,0xE0,0x3F,0x0B,0x01,0x07,0x11,0xB8,0xFF, + 0xD9,0xCF,0x46,0x83,0x84,0x01,0xF3,0x0B,0x42,0xF2,0x0A,0x0B,0x33,0x01,0x00,0x40, + 0x80,0x54,0x00,0x9F,0x30,0x92,0x09,0x01,0x07,0x09,0xB8,0xFF,0xE9,0x6F,0x32,0x5A, + 0x11,0x01,0x30,0x0A,0x47,0x0D,0xB8,0xF7,0xC0,0xFF,0xC5,0x54,0x08,0x09,0xC8,0x20, + 0x30,0x92,0x31,0x42,0xBA,0xFF,0xEF,0x07,0xE7,0xB0,0x93,0xB5,0x17,0xF2,0x9D,0x4E, + 0x08,0x01,0x00,0x19,0xBD,0xFF,0xDF,0xB7,0x07,0x01,0xB8,0xFF,0xE2,0xEF,0x41,0x5A, + 0x44,0x03,0x80,0x01,0xC8,0x03,0x4A,0x00,0x41,0x11,0x88,0x8E,0x70,0x52,0x0A,0x09, + 0x47,0x83,0x81,0x01,0x88,0x0B,0x06,0x11,0xB9,0xFF,0xE7,0x77,0x08,0x01,0x00,0x11, + 0xBD,0xFF,0xDF,0x07,0x43,0x83,0x81,0x01,0xF2,0x0B,0x44,0x12,0x08,0x0B,0x32,0x01, + 0x01,0x9F,0x30,0x92,0x08,0x01,0x00,0x09,0xB8,0xFF,0xEF,0xB7,0x30,0x5A,0x11,0x01, + 0x30,0x0A,0x41,0x0D,0xBC,0xF7,0xC7,0x47,0xC0,0x54,0x08,0x09,0xC9,0x20,0x30,0x92, + 0x37,0x42,0xB8,0xFF,0xEB,0x4F,0xE0,0xB0,0x95,0xB5,0x17,0xF2,0x98,0x4E,0x0F,0x01, + 0x07,0x19,0xB8,0xFF,0xD8,0xFF,0x03,0x07,0x00,0xC7,0x02,0x01,0xB8,0xFF,0xE7,0x27, + 0x40,0x8A,0x09,0x01,0x41,0x03,0x70,0x6A,0x86,0x01,0x8F,0x0B,0x40,0x83,0xF1,0x03, + 0x42,0x01,0x80,0x5E,0x38,0x01,0x00,0x37,0x30,0xD2,0x09,0x19,0x07,0x11,0xB8,0xFF, + 0xE3,0x5F,0xE7,0xF8,0x91,0xFD,0x47,0x83,0xF5,0x03,0x10,0xC2,0xC1,0xA6,0x47,0x83, + 0x08,0x01,0xE8,0x03,0xF6,0x00,0x92,0x15,0x07,0x09,0xB8,0xFF,0xE1,0xEF,0x46,0x83, + 0xEA,0x03,0xF0,0x00,0x90,0x0D,0x06,0x31,0xBA,0xFF,0xDF,0xA7,0x44,0x83,0x11,0x01, + 0xF1,0x1B,0x30,0x0A,0x47,0x0D,0xB8,0xF7,0xC1,0x3F,0x42,0x83,0xF0,0x0B,0xE8,0x03, + 0x00,0x48,0xCA,0x78,0xF6,0x00,0x92,0x0D,0x07,0x39,0xB8,0xFF,0xD8,0x1F,0x22,0x01, + 0x01,0x37,0x30,0x12,0x08,0x09,0x00,0x11,0xBD,0xFF,0xE7,0xF7,0xE7,0x20,0x93,0x25, + 0x40,0x83,0xF1,0x03,0x17,0x02,0xC5,0xA6,0x40,0x83,0x09,0x09,0xEA,0x03,0xF0,0x00, + 0x90,0x15,0x36,0x42,0xBD,0xFF,0xE7,0x87,0x40,0x83,0x09,0x01,0xF0,0x03,0x00,0x1F, + 0x05,0xCC,0xE1,0xF8,0xE6,0x00,0x92,0x05,0x17,0x42,0x9D,0xCE,0x50,0x22,0x40,0x83, + 0x0C,0x11,0x18,0x42,0x00,0x83,0x80,0x5D,0xE8,0x85,0x07,0x00,0x00,0x40,0x00,0x01, + 0x18,0x00,0x04,0x42,0x00,0x01,0x00,0x42,0x00,0x20,0x00,0x01,0xA9,0x85,0x67,0x7A, + 0x19,0xC9,0x42,0x0B,0x12,0xF9,0xE7,0xDA,0x94,0x09,0x80,0x2D,0x58,0x01,0x80,0x0E, + 0x30,0xAA,0x00,0x0F,0x29,0x19,0x10,0x68,0xE8,0x73,0xEA,0x4B,0x00,0x98,0x83,0x0C, + 0xC0,0xC0,0x88,0x1C,0x82,0x14,0x00,0x48,0xC0,0x00,0x82,0x04,0x45,0x22,0x09,0x81, + 0x00,0x0B,0x1A,0x13,0xC0,0x1C,0x20,0x01,0xC0,0xB8,0x01,0x77,0x45,0x0A,0x01,0x08, + 0x46,0x03,0x80,0x01,0x42,0x03,0xC6,0x00,0x40,0x03,0x00,0x2B,0x30,0x12,0x09,0x09, + 0x07,0x01,0xB8,0xFF,0xE3,0x4F,0xE3,0x20,0x95,0x25,0x17,0x3A,0xC0,0x76,0x7F,0xCA, + 0x11,0x09,0x40,0xC3,0xCE,0x0C,0x80,0x01,0x41,0x1B,0x36,0x82,0xBE,0xFF,0xCF,0x07, + 0x40,0xC3,0x11,0x01,0x80,0x01,0x4E,0x1B,0xC8,0x14,0xC0,0x1C,0xBD,0xFF,0xCF,0xC7, + 0x40,0x72,0x40,0x03,0xF0,0x0B,0x48,0x01,0x80,0x86,0x60,0x6A,0x44,0x0B,0x97,0x6D, + 0x44,0xCB,0xE9,0x53,0xE8,0x5B,0x08,0x90,0x1F,0xD2,0x00,0x13,0x8E,0x01,0x4E,0x5B, + 0xF0,0x03,0x10,0x09,0xCF,0x04,0xB8,0xFF,0xCF,0x1F,0x05,0x2B,0x48,0x22,0x00,0x01, + 0x88,0x01,0x12,0x43,0x48,0x12,0x18,0x43,0x87,0x2D,0xE8,0x85,0x00,0x40,0x00,0x01, + 0x00,0x01,0x00,0x42,0x00,0x20,0x00,0x01,0xAA,0x8D,0x77,0x0A,0x01,0x29,0x47,0x8B, + 0x82,0x25,0xE4,0x12,0x8C,0x01,0x5C,0x43,0x53,0x29,0x80,0xB6,0x6E,0xEA,0x41,0x63, + 0x43,0x4B,0x89,0x01,0xC2,0x53,0x06,0x88,0xC0,0x08,0xCB,0x90,0x88,0x0C,0x90,0x14, + 0x0F,0x01,0x10,0xF9,0x18,0x79,0x00,0x4F,0xA4,0x12,0xC3,0x3B,0x78,0x01,0x88,0x16, + 0xC0,0x3B,0x1A,0xFA,0x82,0x3B,0xE2,0x48,0x91,0x4D,0x86,0x41,0x43,0x7B,0xB9,0x01, + 0xC4,0xFB,0x17,0x7A,0xC1,0x86,0x47,0x83,0x39,0x01,0x80,0x01,0xE8,0x03,0x40,0x01, + 0x80,0x86,0x02,0x01,0x81,0x1C,0x30,0x12,0x48,0x1D,0xC0,0x0C,0xBB,0xF7,0xCF,0xB7, + 0x00,0x38,0x88,0x76,0x20,0x01,0x00,0x37,0x37,0x12,0x09,0xF9,0x07,0x09,0xB8,0xEF, + 0xE3,0x4F,0xE2,0x20,0x91,0x25,0x47,0x83,0x80,0x01,0xE9,0x03,0x17,0x02,0xC5,0x9E, + 0x00,0xC7,0x79,0x09,0x89,0x76,0xC0,0x23,0xD0,0x24,0x08,0x01,0x34,0x02,0x39,0x82, + 0x40,0x01,0x80,0x0E,0x00,0x01,0x00,0x07,0x00,0x09,0x10,0x01,0x37,0x0A,0xB9,0xEF, + 0xE1,0x8F,0x01,0x3F,0x43,0x83,0x31,0x5A,0x80,0x01,0xE9,0x2B,0xD9,0xD3,0x30,0x5A, + 0xC8,0x14,0xC0,0x0C,0xBF,0xFF,0xE7,0x37,0x28,0x01,0x00,0xAF,0xC2,0x14,0xE8,0x02, + 0x40,0xF9,0x87,0x0E,0xE0,0x32,0x01,0x07,0x30,0xF9,0xD7,0x24,0x31,0x4A,0x31,0x82, + 0x38,0x82,0x44,0x01,0x80,0x0E,0x00,0x01,0x00,0x07,0x00,0x09,0x31,0x52,0x31,0x8A, + 0xB8,0xEF,0xE7,0x87,0xE7,0x68,0x93,0x6D,0x40,0x2A,0x40,0x03,0x80,0x01,0xE9,0x03, + 0x17,0x42,0xC5,0x1E,0x37,0xC2,0xB9,0xEF,0xD8,0xDF,0x81,0x2D,0xE8,0x85,0x07,0x00, + 0x00,0x20,0x00,0x01,0x00,0x40,0x00,0x01,0xA8,0x85,0x6B,0xC2,0x19,0xE1,0x43,0x4B, + 0x12,0x01,0xD0,0xE2,0x8C,0x01,0x97,0x53,0x48,0xAA,0x40,0x53,0x30,0x90,0xA0,0x3E, + 0x40,0x01,0x80,0x1E,0x42,0x43,0x3A,0x00,0xA8,0xE6,0x07,0x0F,0x84,0x07,0xC0,0x47, + 0x50,0x82,0x00,0x41,0x00,0x83,0x44,0x83,0x08,0xF9,0x8F,0x19,0x18,0x42,0x00,0x83, + 0x40,0x5B,0x31,0xC2,0x84,0x01,0xD7,0x0B,0x48,0x01,0x88,0x26,0xF1,0x20,0x23,0x20, + 0x67,0x20,0x89,0xC6,0x00,0x0F,0x60,0x01,0x88,0x3E,0x40,0x83,0x08,0x81,0x18,0x42, + 0x07,0x83,0x00,0xF9,0x83,0x89,0x9C,0x01,0x1B,0xC4,0xEC,0x85,0x00,0x20,0x00,0x01, + 0x18,0x00,0x04,0x42,0x00,0x01,0x00,0x42,0xA9,0x85,0x47,0x72,0x60,0x72,0x41,0x03, + 0x42,0x0B,0xE9,0x3B,0xEC,0x03,0x30,0x32,0xF0,0x43,0x46,0x01,0x82,0x16,0xF0,0x00, + 0xB7,0x43,0xEE,0x85,0xF0,0x43,0x42,0x01,0x80,0xDE,0x17,0xC9,0xB2,0x52,0x44,0x00, + 0xB0,0x43,0x32,0x42,0x34,0xA2,0x84,0x01,0x18,0x31,0x29,0x01,0x46,0x13,0xF6,0x5A, + 0x41,0x03,0x32,0x72,0x58,0x91,0xD9,0x16,0x1E,0x01,0x20,0x5C,0x31,0x2A,0x1B,0x41, + 0xF3,0x5A,0x26,0x19,0x1D,0x22,0x17,0x1A,0xE0,0x16,0x18,0x01,0x2B,0x5C,0x30,0x32, + 0x18,0x01,0x00,0xAF,0x08,0x01,0x00,0x7F,0x20,0x01,0xF8,0xA2,0x60,0x01,0xE8,0x16, + 0x43,0x24,0xD8,0x20,0x00,0x1F,0x60,0x01,0xD0,0x16,0x40,0x24,0xC8,0x20,0x05,0x24, + 0xE4,0x90,0xE4,0x00,0xE6,0x48,0x92,0x4D,0x17,0xCA,0x9D,0x6E,0xE6,0xD8,0x92,0xDD, + 0x2F,0x9A,0x9B,0x3E,0x41,0x62,0x10,0x11,0x41,0x03,0x18,0x31,0xF0,0x12,0x0C,0xC9, + 0xF0,0x1A,0x56,0xC9,0xE0,0x06,0x30,0x8A,0xC6,0xC8,0x22,0x0C,0x11,0x21,0x19,0x41, + 0x0C,0x89,0xF1,0x12,0xF6,0x1A,0x1E,0x4A,0x10,0x52,0xDC,0x06,0x32,0x8A,0xC0,0xC8, + 0x2F,0x0C,0xE8,0x85,0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0xFB,0x85,0x39,0x82, + 0x48,0x32,0x40,0x2A,0x47,0x4B,0x88,0x01,0x42,0x13,0x3A,0x90,0xA2,0x16,0xC8,0x53, + 0x57,0x31,0x88,0xCE,0x38,0x82,0x03,0x00,0x18,0x00,0x04,0x42,0x00,0x20,0x00,0x01, + 0xA8,0x85,0x6B,0xA2,0x09,0x81,0x41,0x43,0xE0,0x62,0x00,0xD7,0x1A,0x29,0xE7,0xDA, + 0x58,0x31,0x88,0x46,0x40,0x82,0x40,0x0B,0x10,0x81,0x18,0x8A,0x00,0x0B,0x40,0x0B, + 0x18,0x8A,0x00,0x0B,0xE8,0x85,0xE3,0x9B,0x10,0x1A,0x8D,0x16,0xF4,0x00,0x92,0x05, + 0x00,0x17,0xE0,0xA3,0x8C,0x01,0x5B,0x44,0x40,0x01,0x88,0x26,0xBC,0xF7,0xFF,0x87, + 0x43,0x43,0x81,0x01,0x59,0x04,0x44,0x4B,0x31,0x52,0x90,0x01,0xE5,0x9B,0x58,0x29, + 0x8B,0xE6,0xEE,0x85,0x00,0x20,0x00,0x01,0x00,0x01,0x00,0x42,0xA9,0x85,0x47,0xCA, + 0x80,0x9D,0x45,0x0B,0x42,0x48,0x02,0x48,0x07,0x0B,0xB8,0xF7,0xE0,0x7F,0x32,0x22, + 0xBB,0xF7,0xCF,0xF7,0x01,0xF7,0x32,0x0A,0x53,0x9A,0xC9,0x29,0x11,0x8A,0x94,0x7E, + 0xBE,0xF7,0xCF,0xD7,0x6D,0x8A,0x59,0x43,0x80,0x01,0xE2,0x03,0x40,0x79,0x87,0xF6, + 0x07,0x01,0xB8,0xFF,0xE0,0xBF,0x07,0x09,0xBF,0xFF,0xE7,0xA7,0x5A,0x43,0x85,0x01, + 0xE5,0x03,0x40,0x59,0x89,0x9E,0x58,0x52,0x40,0x8B,0x41,0xDB,0x88,0x01,0xEC,0xF3, + 0x42,0x43,0xEE,0xDB,0x40,0x4B,0x12,0x01,0x18,0x9A,0x43,0x74,0x42,0x3C,0xE0,0x90, + 0xD8,0xB0,0x07,0x34,0xE4,0x00,0xE4,0x48,0x94,0x95,0x14,0xD2,0x9D,0xAE,0x5F,0x43, + 0x80,0x01,0xE2,0x03,0x41,0x59,0x85,0x56,0x47,0x0D,0xB8,0xFF,0xE9,0xBF,0x07,0x37, + 0x86,0x01,0x44,0x1B,0x40,0x0B,0x42,0x0D,0x28,0x01,0x78,0xCA,0x00,0x9F,0x10,0x01, + 0x00,0x5F,0x30,0x11,0x03,0xF4,0x60,0x21,0xC0,0x0E,0x30,0x71,0x00,0x07,0x30,0x51, + 0x04,0x74,0xE0,0xD8,0xE2,0x48,0xE4,0x90,0x91,0x95,0x44,0xF3,0xEC,0xB3,0x13,0xB2, + 0xC3,0x7E,0xE7,0x68,0x91,0x6D,0x45,0xD3,0xED,0x93,0x10,0x52,0xC0,0x3E,0x0F,0x01, + 0x10,0x11,0x00,0x14,0xE4,0x48,0xE2,0x00,0x93,0x4D,0x4C,0x21,0x98,0xCE,0x47,0x0D, + 0xBA,0xF7,0xF7,0x17,0x77,0x3A,0x08,0x29,0x40,0x83,0xE1,0x4A,0x4C,0x31,0x80,0xD6, + 0x87,0x9D,0xE9,0x85,0xF8,0x00,0x06,0x42,0x30,0x59,0x05,0x00,0x00,0xC0,0x03,0x01, + 0x00,0x40,0x00,0x01,0x00,0x20,0x00,0x01,0xAF,0x85,0xB8,0xEF,0xC0,0x6F,0x60,0xB2, + 0x41,0x01,0x88,0x46,0x07,0x27,0xB9,0xF7,0xF7,0x6F,0xBF,0xFF,0xFF,0x4F,0xBA,0xF7, + 0xC7,0x8F,0xBE,0xEF,0xE7,0x6F,0xBE,0xE7,0xCF,0x0F,0xBC,0xFF,0xC3,0x5F,0xCA,0x03, + 0x40,0x09,0x80,0x8E,0xB9,0xE7,0xC7,0xF7,0xBE,0xFF,0xF7,0x37,0xBF,0xEF,0xDF,0xF7, + 0xBD,0xEF,0xC7,0xD7,0x07,0x09,0xB8,0xE7,0xD7,0xBF,0xBF,0xF7,0xD8,0xFF,0x40,0x3A, + 0xBF,0xFF,0xEF,0xD7,0xBB,0xEF,0xFF,0x77,0xBC,0xF7,0xF7,0x57,0xBA,0xF7,0xDF,0x87, + 0xC8,0x03,0x43,0x31,0x88,0xBE,0xEE,0x85,0x08,0xC0,0x02,0x01,0xA0,0xA8,0x03,0x00, + 0xAC,0xFD,0x87,0x1D,0x31,0x32,0x40,0x8A,0xF8,0x64,0x80,0x14,0xE0,0x03,0x34,0x62, + 0xE9,0x00,0x6A,0x72,0x96,0x05,0xAE,0x01,0x80,0x0C,0x50,0x09,0x88,0x66,0x00,0x37, + 0xC4,0x14,0xE0,0x03,0xCC,0x0C,0x10,0x42,0xC7,0xD6,0xB9,0xFF,0xF3,0xBF,0xD7,0x43, + 0x47,0x01,0x80,0xAE,0x03,0x01,0x90,0x43,0x04,0x09,0x30,0x22,0x49,0x22,0x01,0xC7, + 0x60,0x01,0xC1,0x2E,0xF7,0x00,0x13,0x01,0x1A,0x82,0x08,0x43,0x30,0x1A,0x01,0x17, + 0x02,0xF9,0x0F,0x43,0x18,0x01,0x11,0x01,0x08,0x53,0x34,0x82,0x00,0x57,0x78,0x01, + 0x88,0x0E,0x10,0x01,0x01,0x0F,0xC0,0x93,0xCE,0xB0,0x07,0x53,0xF2,0x20,0xE3,0x00, + 0x94,0x25,0x95,0x05,0x17,0xC2,0x9C,0x96,0x30,0x02,0x43,0x01,0x80,0x26,0x00,0xA1, + 0x00,0x43,0x04,0x01,0x30,0x22,0x04,0x0F,0x04,0x21,0x00,0x43,0x44,0x43,0x12,0x01, + 0x1A,0x82,0x00,0x43,0x00,0x47,0xC0,0x14,0xE0,0x03,0xD4,0x0C,0x10,0x82,0xCC,0x1E, + 0x03,0x01,0x90,0x43,0x87,0x3D,0xE8,0x85,0xD0,0x43,0x43,0x01,0x80,0x9E,0x07,0x01, + 0x90,0x43,0x63,0x01,0x88,0x26,0xC6,0x34,0x47,0x09,0x88,0x9E,0x04,0x01,0x00,0x43, + 0x44,0x43,0x12,0x01,0x1A,0x82,0x00,0x43,0x38,0x67,0x07,0x00,0x00,0xC0,0x04,0x01, + 0x80,0x01,0x06,0x42,0xCB,0x43,0xFB,0x72,0xC3,0x8B,0x61,0xC3,0x12,0x4B,0x93,0xF9, + 0x91,0x71,0x01,0xA0,0x08,0x08,0xF8,0x07,0x08,0x00,0x08,0x08,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xA0,0x05,0x42,0x80,0xA0,0x05,0x42, + 0x80,0xA0,0x05,0x42,0x80,0x20,0x05,0x42,0x80,0x20,0x05,0x42,0x80,0x20,0x05,0x42, + 0x80,0x20,0x05,0x42,0x80,0xA0,0x04,0x42,0x80,0xA0,0x04,0x42,0x80,0xA0,0x04,0x42, + 0x80,0xA0,0x04,0x42,0x80,0x20,0x04,0x42,0x80,0x20,0x04,0x42,0x80,0x20,0x04,0x42, + 0x80,0x20,0x03,0x42,0x80,0x20,0x03,0x42,0x80,0xA0,0x02,0x42,0x80,0xA0,0x02,0x42, + 0x80,0xA0,0x02,0x42,0x80,0xA0,0x02,0x42,0x80,0x20,0x02,0x42,0x80,0x20,0x02,0x42, + 0x80,0x20,0x02,0x42,0x80,0x20,0x02,0x42,0x80,0xA0,0x01,0x42,0x80,0xA0,0x01,0x42, + 0x80,0xA0,0x01,0x42,0x80,0xA0,0x01,0x42,0x80,0x20,0x01,0x42,0x80,0x20,0x01,0x42, + 0x80,0x20,0x01,0x42,0x80,0x20,0x01,0x42,0x80,0xA0,0x00,0x42,0x80,0xA0,0x00,0x42, + 0x80,0xA0,0x00,0x42,0x80,0xA0,0x00,0x42,0x80,0x20,0x00,0x42,0x80,0x20,0x00,0x42, + 0x80,0x20,0x00,0x42,0x80,0x20,0x00,0x42,0x08,0x81,0x03,0x42,0x08,0x41,0x03,0x42, + 0x08,0x01,0x03,0x42,0x08,0xC1,0x02,0x42,0x08,0x81,0x02,0x42,0x08,0x41,0x02,0x42, + 0x08,0x01,0x02,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,0x41,0x02,0x42,0x08,0x01,0x02,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,0xC1,0x03,0x42,0x08,0x81,0x03,0x42, + 0x08,0x41,0x03,0x42,0x08,0x01,0x03,0x42,0x08,0xC1,0x02,0x42,0x08,0x81,0x02,0x42, + 0x08,0x41,0x02,0x42,0x08,0x01,0x02,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,0x10,0x20,0x40,0x08,0x10,0x20,0x40,0x08, + 0x10,0x20,0x40,0x08,0x10,0x20,0x08,0x10,0x20,0x40,0x08,0x10,0x20,0x40,0x08,0x10, + 0x20,0x40,0x08,0x10,0x20,0x40,0x08,0x10,0x20,0x40,0x08,0x10,0x20,0x40,0x08,0x10, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x08,0xF8,0x0F,0xFF,0x07,0xF8,0xFF, + 0x07,0xF8,0x0F,0xF8,0x08,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, + 0x03,0x00,0x28,0xB5,0x39,0xC5,0x08,0x1D,0x1B,0x2B,0x3A,0x28,0x53,0xB5,0x0A,0xC5, + 0x00,0x08,0x01,0x00,0x01,0x00,0x50,0x0D,0x52,0x1D,0x52,0xB5,0x39,0x0D,0x04,0x08, + 0x51,0x3D,0x53,0x1D,0x51,0x3D,0x54,0x95,0x51,0x3D,0x54,0x95,0x51,0x3D,0x54,0x95, + 0x0B,0x3D,0x34,0x88,0x51,0x3D,0x54,0x1D,0x51,0x3D,0x54,0x95,0x04,0x00,0x50,0x3D, + 0x50,0x1D,0x01,0x00,0x00,0x00,0x00,0x00,0x54,0x2D,0x53,0x3D,0x32,0x8D,0x32,0x38, + 0x01,0x28,0x0A,0x45,0x50,0xB5,0x53,0x95,0x00,0x00,0x00,0x00,0x52,0xA5,0x51,0xB5, + 0x09,0xC5,0x03,0x08,0x03,0x00,0x50,0x3D,0x55,0x1D,0x51,0x0D,0x51,0x3D,0x54,0x95, + 0x51,0x3D,0x53,0x1D,0x51,0x3D,0x54,0x95,0x51,0x0D,0x55,0x0D,0x54,0xB5,0x3A,0x0D, + 0x00,0x08,0x01,0x00,0x53,0xA5,0x51,0x2D,0x52,0x3D,0x34,0x8A,0x1D,0x38,0x52,0x45, + 0x52,0x0D,0x51,0x1D,0x54,0xB5,0x3A,0x0D,0x53,0xA5,0x29,0xB5,0x39,0xC5,0x08,0x1D, + 0x19,0x2D,0x22,0x1D,0x44,0x0D,0x31,0x3D,0x23,0x95,0x09,0xC1,0x29,0xB5,0x0B,0x1D, + 0x1B,0x2B,0x3A,0x28,0x00,0x00,0x00,0x08,0xFF,0x07,0x00,0xF8,0x08,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,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x00,0x00,0xCB,0x43,0xFB,0x72,0xC3,0x8B,0x61,0xC3,0x12,0x4B,0x93,0xF9, + 0x91,0x71,0x01,0xA0,0x00,0x00,0x00,0x00,0x70,0xD0,0xD0,0x70,0x20,0x00,0xD0,0x00, + 0x03,0x70,0x08,0x60,0x37,0xC0,0x40,0x11,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x07,0x00,0xF0,0x40,0xA0, + 0x01,0x40,0x6E,0x40,0x82,0x6A,0x29,0x80,0x20,0x10,0x78,0x10,0x57,0xB0,0x57,0xB0, + 0x50,0x50,0x50,0x50,0x69,0xA8,0x01,0xA8,0x16,0x88,0x00,0x40,0xF1,0xA8,0x41,0xE0, + 0xB0,0x10,0x00,0x18,0x00,0x00,0x00,0x04,0x30,0x00,0x00,0x48,0x10,0x08,0x20,0x18, + 0x30,0x28,0x00,0x38,0x08,0xA0,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x48,0x82,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x05,0x00, + 0x48,0x82,0x03,0x00,0x00,0x00,0x01,0x01,0x58,0x40,0x03,0x00,0x00,0xE0,0x05,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xD1,0xDA,0xAA,0xA9,0x2E,0x2D,0x55,0x56,0xBB,0x43,0xAC,0x32, + 0x99,0x21,0x8A,0x10,0x00,0xD0,0x00,0x70,0x18,0x00,0x29,0x00,0x06,0x78,0x50,0x56, + 0xFF,0xFF,0xFF,0xFF,0x44,0x09,0x02,0x60,0x00,0x00,0x10,0x08,0xDB,0xEE,0x35,0x2A, + 0x0F,0x00,0xCA,0xCA,0xFF,0xFF,0xFF,0xFF,0x41,0x28,0x8C,0x00,0x00,0x00,0x01,0x02, + 0xBD,0xDB,0x65,0x46,0x98,0xC3,0x04,0xC4 +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw1.h b/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw1.h new file mode 100644 index 000000000000..3f78f205eee4 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw1.h @@ -0,0 +1,2584 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst66xx_fw1.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE1_H +#define HYNITRON_FIRMWARE1_H + +static const uint8_t fw_module1[] = { + 0xF8,0x5F,0x00,0x20,0xFD,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0x45,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xD9,0x1C,0x00,0x00,0x4D,0x65,0x00,0x00,0xFD,0x48,0x00,0x00, + 0xB1,0x1C,0x00,0x00,0x35,0x64,0x00,0x00,0x75,0x45,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x48,0x85,0x46,0x00,0xF0,0x76,0xF8,0x00,0x48,0x00,0x47,0xA5,0x4E,0x00,0x00, + 0xF8,0x5F,0x00,0x20,0x30,0xB5,0x0B,0x46,0x01,0x46,0x00,0x20,0x20,0x22,0x01,0x24, + 0x09,0xE0,0x0D,0x46,0xD5,0x40,0x9D,0x42,0x05,0xD3,0x1D,0x46,0x95,0x40,0x49,0x1B, + 0x25,0x46,0x95,0x40,0x40,0x19,0x15,0x46,0x52,0x1E,0x00,0x2D,0xF1,0xDC,0x30,0xBD, + 0x70,0xB5,0x00,0x24,0x25,0x46,0x00,0x28,0x01,0xDA,0x01,0x24,0x40,0x42,0x00,0x29, + 0x01,0xDA,0x01,0x25,0x49,0x42,0xFF,0xF7,0xDD,0xFF,0xAC,0x42,0x00,0xD0,0x40,0x42, + 0x00,0x2C,0x00,0xD0,0x49,0x42,0x70,0xBD,0x10,0xB5,0x43,0x1A,0x93,0x42,0x09,0xD2, + 0x83,0x18,0x88,0x18,0x03,0xE0,0x40,0x1E,0x01,0x78,0x5B,0x1E,0x19,0x70,0x52,0x1E, + 0xF9,0xD2,0x10,0xBD,0x03,0x46,0x0B,0x43,0x9B,0x07,0x0A,0xD1,0x02,0xE0,0x08,0xC9, + 0x12,0x1F,0x08,0xC0,0x04,0x2A,0xFA,0xD2,0x03,0xE0,0x0B,0x78,0x03,0x70,0x49,0x1C, + 0x40,0x1C,0x52,0x1E,0xF9,0xD2,0x10,0xBD,0xD2,0xB2,0x01,0xE0,0x02,0x70,0x40,0x1C, + 0x49,0x1E,0xFB,0xD2,0x70,0x47,0x00,0x22,0xF6,0xE7,0x10,0xB5,0x04,0x46,0x08,0x46, + 0x11,0x46,0x02,0x46,0x20,0x46,0xFF,0xF7,0xEF,0xFF,0x20,0x46,0x10,0xBD,0x02,0x1D, + 0x03,0x21,0x52,0x1E,0x13,0x78,0x00,0x02,0x18,0x43,0x49,0x1E,0xF9,0xD5,0x70,0x47, + 0x03,0x46,0x03,0x22,0x08,0x70,0x49,0x1C,0x00,0x0A,0x52,0x1E,0xFA,0xD5,0x18,0x46, + 0x70,0x47,0x00,0x00,0x06,0x4C,0x01,0x25,0x06,0x4E,0x05,0xE0,0x20,0x46,0xE3,0x68, + 0x07,0xC8,0x2B,0x43,0x98,0x47,0x10,0x34,0xB4,0x42,0xF7,0xD3,0xFF,0xF7,0x7C,0xFF, + 0x58,0x6F,0x00,0x00,0x68,0x6F,0x00,0x00,0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40, + 0x40,0x09,0x02,0x4A,0x80,0x00,0x80,0x18,0x01,0x60,0x70,0x47,0x80,0xE1,0x00,0xE0, + 0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40,0x40,0x09,0x02,0x4A,0x80,0x00,0x80,0x18, + 0x01,0x60,0x70,0x47,0x00,0xE1,0x00,0xE0,0x83,0x07,0xFF,0x22,0xDB,0x0E,0x9A,0x40, + 0x89,0x07,0x09,0x0E,0x99,0x40,0x00,0x28,0x0B,0xDA,0x00,0x07,0x00,0x0F,0x08,0x38, + 0x83,0x08,0x08,0x48,0x9B,0x00,0x18,0x18,0xC3,0x69,0x93,0x43,0x0B,0x43,0xC3,0x61, + 0x70,0x47,0x83,0x08,0x04,0x48,0x9B,0x00,0x18,0x18,0x03,0x68,0x93,0x43,0x0B,0x43, + 0x03,0x60,0x70,0x47,0x00,0xED,0x00,0xE0,0x00,0xE4,0x00,0xE0,0x10,0xB5,0x01,0xF0, + 0x2F,0xFD,0xFF,0xF7,0x35,0xFF,0x10,0xBD,0x30,0xB4,0x74,0x46,0x64,0x1E,0x25,0x78, + 0x64,0x1C,0xAB,0x42,0x00,0xD2,0x1D,0x46,0x63,0x5D,0x5B,0x00,0xE3,0x18,0x30,0xBC, + 0x18,0x47,0x02,0xE0,0x08,0xC8,0x12,0x1F,0x08,0xC1,0x00,0x2A,0xFA,0xD1,0x70,0x47, + 0x70,0x47,0x00,0x20,0x01,0xE0,0x01,0xC1,0x12,0x1F,0x00,0x2A,0xFB,0xD1,0x70,0x47, + 0xF8,0xB5,0x31,0x4F,0x00,0x25,0xB8,0x7A,0x81,0x06,0x14,0xD5,0x2F,0x4C,0x21,0x28, + 0x05,0xD1,0x40,0x22,0x2E,0x49,0x20,0x46,0xFF,0xF7,0x3E,0xFF,0x09,0xE0,0x22,0x28, + 0x07,0xD1,0x2C,0x48,0x40,0x22,0x01,0x68,0x29,0x48,0xA8,0x31,0xFF,0xF7,0x34,0xFF, + 0xEF,0xE7,0x00,0x20,0xB8,0x72,0x25,0x4C,0x01,0x26,0x38,0x34,0xA0,0x7A,0x05,0x28, + 0x01,0xD9,0xA6,0x74,0x01,0x25,0x24,0x49,0x20,0x48,0x0A,0x68,0x78,0x30,0xC2,0x60, + 0x4A,0x68,0x42,0x62,0x89,0x68,0xC1,0x63,0x01,0x46,0x80,0x39,0x1E,0x48,0x06,0xF0, + 0x79,0xF9,0x00,0x20,0xA0,0x74,0x60,0x7B,0x0A,0x28,0x00,0xD9,0xA6,0x74,0x04,0xF0, + 0x0F,0xFD,0x1A,0x48,0x40,0x78,0x80,0x07,0x05,0xD1,0xF8,0x7B,0x00,0x28,0x02,0xD0, + 0xA6,0x74,0x00,0x20,0x60,0x74,0x10,0x49,0xA0,0x7E,0x20,0x39,0x48,0x75,0x0F,0x49, + 0x62,0x7E,0x08,0x39,0x08,0x46,0x20,0x30,0x0A,0x2A,0x01,0xD8,0x00,0x2D,0x04,0xD0, + 0x03,0x22,0xC2,0x70,0x02,0x71,0x0E,0x77,0x06,0xE0,0x09,0x4A,0xD3,0x7E,0xC3,0x70, + 0x13,0x7F,0x03,0x71,0x10,0x7D,0x08,0x77,0x60,0x7C,0x05,0x28,0x02,0xD9,0x00,0x20, + 0xC0,0x43,0xF8,0xBD,0x00,0x20,0xF8,0xBD,0xB8,0x04,0x00,0x20,0x20,0x06,0x00,0x20, + 0xCE,0x05,0x00,0x20,0x10,0x06,0x00,0x20,0x60,0x1F,0x00,0x20,0xF6,0x04,0x00,0x20, + 0x03,0x48,0x00,0x21,0x41,0x74,0xFF,0x22,0x20,0x30,0x42,0x76,0x01,0x77,0x70,0x47, + 0x58,0x06,0x00,0x20,0x10,0xB5,0x04,0x46,0x08,0x49,0x09,0x48,0x06,0xF0,0x7F,0xF9, + 0x06,0x49,0x40,0x31,0x0A,0x7A,0x22,0x70,0x04,0x4A,0x92,0x68,0x92,0x07,0x04,0xD5, + 0x0A,0x7A,0x00,0x2A,0x01,0xD0,0x01,0x22,0x8A,0x74,0x10,0xBD,0x18,0x06,0x00,0x20, + 0x60,0x1F,0x00,0x20,0xF0,0xB5,0x8D,0xB0,0x5A,0x48,0xFF,0x22,0x40,0x21,0x0C,0x90, + 0xFF,0xF7,0xD2,0xFE,0x57,0x48,0x90,0x21,0x6C,0x30,0xFF,0xF7,0xD4,0xFE,0x03,0x21, + 0x55,0x48,0xC9,0x02,0xC1,0x83,0x01,0x46,0x28,0x31,0x20,0x30,0x53,0x4B,0x01,0x60, + 0x50,0x4A,0x18,0x7D,0x08,0x3A,0x50,0x70,0x5C,0x7D,0x51,0x49,0x14,0x70,0x09,0x68, + 0xC0,0x01,0x8D,0x7E,0x95,0x70,0xD5,0x78,0x2D,0x09,0x2D,0x01,0xAD,0x1C,0xED,0xB2, + 0x2D,0x07,0x2D,0x0F,0xD5,0x70,0x90,0x80,0xE0,0x01,0xD0,0x80,0x08,0x46,0xD4,0x1D, + 0xE8,0x30,0xF9,0x34,0x60,0x60,0x34,0x30,0xA0,0x60,0xE8,0x38,0xE0,0x60,0x34,0x30, + 0x20,0x61,0x10,0x46,0x80,0x30,0x9E,0x6A,0x06,0x61,0x5E,0x6A,0x46,0x61,0x56,0x78, + 0x12,0x78,0x96,0x46,0x72,0x43,0x82,0x83,0x01,0x22,0x82,0x77,0x0A,0x46,0xFF,0x32, + 0x81,0x32,0x02,0x62,0x2A,0x09,0x94,0x46,0xD7,0x07,0x02,0x46,0x00,0x25,0x40,0x32, + 0x00,0x2F,0x05,0xD0,0x9F,0x6C,0x17,0x60,0x5F,0x6C,0x57,0x60,0x96,0x81,0x00,0xE0, + 0x95,0x81,0x66,0x46,0xB7,0x07,0x33,0x4E,0x06,0xD5,0x9F,0x6B,0x87,0x62,0x5F,0x6B, + 0xC7,0x62,0x77,0x46,0xB7,0x82,0x00,0xE0,0xB5,0x82,0xFF,0x31,0x95,0x73,0x88,0x31, + 0x11,0x61,0xB5,0x75,0x81,0x63,0x27,0x49,0x2B,0x48,0x08,0x39,0x4A,0x78,0x02,0x75, + 0x09,0x78,0x41,0x75,0x19,0x6D,0x01,0x60,0x59,0x6D,0x41,0x60,0x99,0x6D,0x81,0x60, + 0x23,0x4F,0x40,0x22,0x25,0x49,0x0C,0x98,0xFF,0xF7,0x3E,0xFE,0x30,0x22,0x24,0x49, + 0x68,0x46,0xFF,0xF7,0x39,0xFE,0x1B,0x48,0x06,0x22,0x69,0x46,0x08,0x38,0x00,0x23, + 0x06,0xF0,0xFE,0xF9,0x17,0x4D,0xFE,0x20,0x38,0x35,0xE8,0x74,0x29,0x46,0x28,0x22, + 0xD6,0x31,0x1C,0x48,0xFF,0xF7,0x28,0xFE,0x1A,0x48,0x29,0x46,0xBC,0x31,0x22,0x30, + 0x0A,0x7E,0x82,0x71,0x49,0x7E,0x18,0x4E,0xC1,0x71,0x30,0x1D,0xFF,0xF7,0x4F,0xFE, + 0x29,0x46,0x44,0x39,0x08,0x60,0x28,0x7E,0x00,0x28,0x01,0xD0,0x01,0x20,0xB0,0x74, + 0x0D,0x48,0x14,0x22,0x7A,0x21,0x18,0x30,0x05,0xF0,0x34,0xFD,0x38,0x68,0x00,0x79, + 0x03,0x28,0x02,0xD1,0x20,0x7D,0x03,0x28,0x02,0xD0,0x03,0x20,0x03,0xF0,0xB2,0xFB, + 0x0D,0xB0,0xF0,0xBD,0x20,0x06,0x00,0x20,0x38,0x07,0x00,0x20,0xAC,0x03,0x00,0x20, + 0x10,0x06,0x00,0x20,0xB8,0x06,0x00,0x20,0x60,0x1F,0x00,0x20,0xCE,0x05,0x00,0x20, + 0x14,0x6E,0x00,0x00,0x50,0x01,0x00,0x20,0x98,0x04,0x00,0x20,0x38,0xB5,0x00,0x23, + 0x1C,0xE0,0x54,0x22,0x5A,0x43,0x54,0x18,0x22,0x7C,0x12,0x07,0x15,0xD0,0x22,0x46, + 0x24,0x68,0x00,0x94,0x40,0x32,0x6C,0x46,0x24,0x88,0x15,0x89,0x64,0x19,0x0C,0x25, + 0x55,0x5F,0x6D,0x10,0x64,0x19,0x14,0x80,0x6C,0x46,0x64,0x88,0x55,0x89,0x64,0x19, + 0x0E,0x25,0x55,0x5F,0x6D,0x10,0x64,0x19,0x54,0x80,0x5B,0x1C,0x82,0x78,0x9A,0x42, + 0xDF,0xDC,0x38,0xBD,0xFF,0xB5,0x85,0xB0,0x9F,0x88,0x00,0x97,0x00,0x25,0x02,0x24, + 0x45,0x5F,0x7F,0x1E,0xDE,0x88,0x04,0x5F,0x02,0x97,0xBD,0x42,0x02,0xD8,0x70,0x1E, + 0x84,0x42,0x68,0xD9,0x00,0x2A,0x66,0xDD,0x0B,0x46,0x48,0x33,0x00,0x20,0x02,0x27, + 0x18,0x5E,0xDF,0x5F,0x40,0x00,0x7F,0x00,0x02,0x2A,0x05,0xD1,0x04,0x22,0x9A,0x5E, + 0x10,0x18,0x06,0x22,0x9A,0x5E,0xD7,0x19,0x00,0x9A,0x6B,0x00,0x9A,0x1A,0x53,0x1C, + 0x00,0x2B,0x01,0xDD,0x52,0x1C,0x00,0xE0,0xD2,0x43,0x94,0x46,0x62,0x00,0x92,0x1B, + 0x53,0x1C,0x00,0x2B,0x01,0xDD,0x52,0x1C,0x00,0xE0,0xD2,0x43,0x03,0x92,0x09,0x7C, + 0x09,0x09,0x49,0x1C,0x48,0x43,0x4F,0x43,0x01,0x90,0x00,0x28,0x0C,0xD0,0x00,0x99, + 0x60,0x46,0x40,0x1A,0x41,0x03,0x01,0x20,0x40,0x03,0x08,0x18,0x01,0x99,0x00,0x29, + 0x00,0xDC,0x49,0x42,0xFF,0xF7,0x6C,0xFD,0x04,0x90,0x00,0x2F,0x42,0xD0,0x03,0x98, + 0x80,0x1B,0x41,0x03,0x01,0x20,0x40,0x03,0x08,0x18,0x39,0x1E,0x00,0xDC,0x79,0x42, + 0xFF,0xF7,0x5E,0xFD,0x04,0x99,0x81,0x42,0x00,0xDC,0x01,0x46,0x01,0x20,0x40,0x03, + 0x81,0x42,0x00,0xDD,0x00,0x21,0x01,0x98,0x01,0x22,0x48,0x43,0x12,0x03,0x4F,0x43, + 0x80,0x18,0xB9,0x18,0x89,0x13,0x62,0x1A,0x80,0x13,0x94,0x46,0x02,0x9F,0x2B,0x1A, + 0x01,0x22,0xBB,0x42,0x03,0xD8,0x77,0x1E,0xBC,0x45,0x00,0xD8,0x92,0x1E,0x50,0x43, + 0x45,0x19,0x4A,0x43,0x14,0x19,0x00,0x20,0x01,0x46,0x00,0x2D,0x05,0xDD,0x02,0x9A, + 0x29,0x46,0x95,0x42,0x01,0xDB,0x00,0x99,0x49,0x1E,0x0E,0x9A,0x00,0x2C,0x11,0x80, + 0x04,0xDD,0x71,0x1E,0x20,0x46,0x8C,0x42,0x00,0xDB,0x70,0x1E,0x0E,0x99,0x48,0x80, + 0x09,0xB0,0xF0,0xBD,0x00,0x20,0xC5,0xE7,0xFE,0xB5,0x41,0x48,0x3F,0x4E,0x00,0x68, + 0x01,0x46,0x20,0x30,0x04,0x7C,0x45,0x7C,0x20,0x46,0x68,0x43,0x00,0x90,0x3D,0x48, + 0x80,0x08,0x80,0x00,0x01,0x90,0x94,0x20,0x47,0x5C,0x20,0x46,0x39,0x46,0xFF,0xF7, + 0xF9,0xFC,0x00,0x29,0x01,0xD1,0x00,0x20,0x00,0xE0,0x78,0x1A,0x00,0x19,0x00,0x05, + 0x02,0x0C,0x35,0x49,0x01,0xA8,0x04,0xF0,0x19,0xFC,0x34,0x48,0x33,0x49,0x84,0x61, + 0xC5,0x61,0x00,0x98,0x40,0x00,0x02,0x90,0x08,0x62,0x48,0x62,0x88,0x62,0x2C,0x48, + 0x00,0x68,0x80,0x30,0x07,0x7D,0x20,0x46,0x39,0x46,0xFF,0xF7,0xDB,0xFC,0x00,0x29, + 0x01,0xD1,0x00,0x20,0x00,0xE0,0x78,0x1A,0x00,0x19,0x28,0x49,0x68,0x43,0xC8,0x62, + 0x60,0x00,0x08,0x63,0x48,0x63,0x88,0x63,0xCC,0x63,0x24,0x4A,0x69,0x00,0x11,0x64, + 0x51,0x64,0x91,0x64,0xD5,0x64,0x21,0x4B,0x02,0x9A,0x1A,0x65,0x1A,0x46,0x50,0x65, + 0x10,0x46,0x11,0x25,0x00,0x24,0x07,0x46,0x81,0x65,0xA0,0x00,0xC1,0x19,0x88,0x69, + 0x18,0x31,0x82,0xB2,0x01,0xA8,0x04,0xF0,0xE1,0xFB,0x64,0x1C,0xE4,0xB2,0xAC,0x42, + 0xF3,0xD3,0x17,0x49,0x01,0x98,0xFF,0xF7,0x13,0xFD,0x16,0x49,0x02,0x46,0xB0,0x42, + 0x09,0xD2,0xB0,0x1A,0x80,0xB2,0x08,0x77,0x02,0x0A,0x4A,0x77,0x01,0x21,0x89,0x02, + 0x88,0x42,0x06,0xD8,0x02,0xE0,0x00,0x20,0x08,0x77,0x48,0x77,0x01,0x20,0x03,0xF0, + 0x71,0xFA,0x08,0x48,0x01,0x99,0xC0,0x1E,0x09,0x1A,0xFF,0xF7,0xE4,0xFC,0x01,0x99, + 0x09,0x48,0x08,0x60,0x03,0x20,0x02,0xF0,0x23,0xFA,0xFE,0xBD,0xF8,0x5F,0x00,0x20, + 0x10,0x06,0x00,0x20,0x9B,0x21,0x00,0x20,0xA4,0x03,0x00,0x20,0xAC,0x03,0x00,0x20, + 0xA4,0x04,0x00,0x20,0x32,0x01,0x00,0x20,0x5A,0xA5,0xAC,0xCA,0x70,0xB5,0x05,0x46, + 0x0C,0x46,0x00,0x2B,0x05,0xD0,0x01,0x46,0x52,0x00,0x20,0x46,0xFF,0xF7,0x9C,0xFC, + 0x70,0xBD,0x00,0x20,0x08,0xE0,0x43,0x00,0xE1,0x5E,0x4E,0x00,0x89,0x19,0xEE,0x5E, + 0x89,0x19,0x89,0x10,0xE1,0x52,0x40,0x1C,0x90,0x42,0xF4,0xDB,0x70,0xBD,0x70,0xB5, + 0x48,0x79,0x01,0x26,0x0D,0x46,0x00,0x28,0x03,0xD1,0x28,0x7A,0x00,0x28,0x00,0xD0, + 0x00,0x26,0x00,0x24,0x18,0x20,0x60,0x43,0x40,0x19,0x18,0x30,0x41,0x68,0x00,0x29, + 0x05,0xD0,0x10,0x22,0x82,0x5E,0x00,0x68,0x33,0x46,0xFF,0xF7,0xCF,0xFF,0x64,0x1C, + 0x05,0x2C,0xEF,0xDB,0x70,0xBD,0xF0,0xB5,0x86,0x46,0x8C,0x46,0x00,0x25,0x18,0x20, + 0x68,0x43,0x70,0x44,0x28,0x22,0x82,0x5E,0xC4,0x69,0x83,0x69,0x52,0x1E,0x16,0xD4, + 0x20,0x30,0x81,0x7A,0x00,0x29,0x03,0xD0,0x56,0x00,0xA7,0x5B,0x99,0x5B,0x0A,0xE0, + 0x61,0x46,0x00,0x29,0x04,0xD0,0x56,0x00,0x9F,0x5B,0xA1,0x5B,0x79,0x18,0x03,0xE0, + 0x56,0x00,0x9F,0x5B,0xA1,0x5B,0x79,0x1A,0x99,0x53,0x52,0x1E,0xE9,0xD5,0x6D,0x1C, + 0x05,0x2D,0xDC,0xDB,0xF0,0xBD,0xF3,0xB5,0x83,0xB0,0x04,0x98,0x04,0x9C,0xC0,0x78, + 0x74,0x34,0x00,0x07,0x00,0x0F,0x01,0x28,0x14,0xD0,0x21,0x46,0x04,0x9A,0x03,0x98, + 0x05,0xF0,0x32,0xFD,0x60,0x79,0x00,0x25,0x03,0x28,0x1F,0xD2,0x04,0x99,0x22,0x7A, + 0x09,0x7B,0x8A,0x42,0x1A,0xD2,0x04,0x99,0xE2,0x79,0x49,0x7B,0x8A,0x42,0x05,0xD2, + 0x40,0x1C,0x04,0xE0,0x00,0x20,0x60,0x71,0x05,0xB0,0xF0,0xBD,0x00,0x20,0x60,0x71, + 0x21,0x46,0x03,0x98,0xFF,0xF7,0x93,0xFF,0x20,0x7A,0x40,0x1C,0x20,0x72,0x00,0x20, + 0x20,0x71,0xE0,0x6A,0x01,0x25,0x00,0x78,0xA0,0x71,0x61,0xE0,0x04,0x9E,0x40,0x36, + 0xB0,0x7C,0x00,0x28,0x08,0xD0,0x01,0x21,0x20,0x46,0x03,0xF0,0x11,0xFF,0x00,0x20, + 0x20,0x71,0x04,0x98,0x40,0x7C,0x52,0xE0,0x00,0x21,0x20,0x46,0x03,0xF0,0x08,0xFF, + 0x32,0x7E,0x21,0x46,0x03,0x98,0x03,0xF0,0x63,0xFE,0x00,0x90,0x20,0x79,0x40,0x1C, + 0xC0,0xB2,0x20,0x71,0xA1,0x79,0x88,0x42,0x42,0xD3,0x00,0x98,0x00,0x28,0x07,0xD0, + 0x28,0x21,0x61,0x5E,0x60,0x6A,0x40,0x18,0x00,0x21,0x61,0x5E,0xFF,0xF7,0x13,0xFC, + 0x00,0x25,0x18,0x20,0x68,0x43,0x02,0x19,0x18,0x32,0x51,0x68,0x00,0x29,0x26,0xD0, + 0x90,0x68,0x01,0x90,0xD0,0x68,0x86,0x46,0x10,0x20,0x10,0x5E,0x1D,0xE0,0x43,0x00, + 0x01,0x9F,0xCA,0x5E,0xFE,0x5E,0xB4,0x46,0xB2,0x42,0x16,0xD0,0x76,0x46,0x36,0x56, + 0x32,0x2E,0x12,0xDC,0x31,0x27,0xFF,0x43,0xBE,0x42,0x0E,0xDB,0x00,0x9F,0x00,0x2F, + 0x05,0xD0,0x62,0x46,0xCA,0x52,0x00,0x22,0x73,0x46,0x1A,0x54,0x05,0xE0,0x62,0x45, + 0x01,0xDA,0x52,0x1C,0x00,0xE0,0x52,0x1E,0xCA,0x52,0x40,0x1E,0xDF,0xD5,0x6D,0x1C, + 0x05,0x2D,0xCE,0xDB,0x00,0x20,0x20,0x71,0xE0,0x6A,0x01,0x25,0x00,0x78,0xA0,0x71, + 0x21,0x46,0x04,0x9A,0x03,0x98,0x05,0xF0,0xC5,0xFC,0x00,0x21,0x20,0x46,0xFF,0xF7, + 0x3A,0xFF,0x28,0x46,0x80,0xE7,0x00,0x00,0x70,0xB5,0x04,0x46,0x74,0x34,0xFF,0x21, + 0x61,0x71,0x01,0x78,0x18,0x4A,0x49,0x1C,0x4D,0x08,0x41,0x78,0x49,0x1C,0x49,0x08, + 0x4D,0x43,0xFF,0x21,0x25,0x80,0x45,0x31,0x09,0x58,0x0A,0x60,0x01,0x46,0x01,0x22, + 0x20,0x46,0x00,0xF0,0x23,0xF8,0x60,0x6A,0x00,0x28,0x01,0xD0,0x00,0x20,0x70,0xBD, + 0x04,0xF0,0x74,0xFD,0x03,0x46,0x00,0x21,0x18,0x22,0x4A,0x43,0x12,0x19,0x18,0x32, + 0x10,0x26,0x96,0x5F,0x00,0x2E,0x06,0xDD,0x10,0x26,0xD0,0x60,0x96,0x5F,0x30,0x18, + 0x00,0x29,0x00,0xD1,0x40,0x19,0x49,0x1C,0x05,0x29,0xED,0xDB,0xC4,0x1A,0x20,0x46, + 0x04,0xF0,0x7A,0xFD,0x20,0x46,0x70,0xBD,0x47,0x08,0x00,0x00,0xF7,0xB5,0x05,0x46, + 0x82,0xB0,0x0F,0x78,0x48,0x78,0x00,0x90,0xE8,0x69,0x00,0x24,0x0E,0x46,0x00,0x28, + 0x33,0xD0,0x04,0xF0,0x4B,0xFD,0x02,0x46,0x28,0x6A,0x00,0x28,0x12,0xD1,0x04,0x98, + 0x00,0x28,0x16,0xD0,0x00,0x20,0x18,0x21,0x41,0x43,0x49,0x19,0xCB,0x69,0x00,0x2B, + 0x05,0xD0,0x63,0x00,0x9B,0x18,0x0B,0x62,0x28,0x23,0xCB,0x5E,0x1C,0x19,0x40,0x1C, + 0x05,0x28,0xF0,0xDB,0xF0,0x78,0x00,0x09,0x0F,0xD0,0xB0,0x68,0xC0,0x07,0x03,0xD0, + 0x0B,0xE0,0x01,0x20,0x68,0x72,0xF5,0xE7,0x60,0x00,0x80,0x18,0x28,0x61,0xE0,0x19, + 0x41,0x00,0x89,0x18,0x69,0x61,0x00,0x99,0x44,0x18,0x64,0x00,0x21,0x46,0x10,0x46, + 0xFF,0xF7,0x59,0xFB,0x20,0x46,0x04,0xF0,0x37,0xFD,0x20,0x46,0x05,0xB0,0xF0,0xBD, + 0xF8,0xB5,0x04,0x46,0x05,0x46,0x07,0x46,0x48,0x34,0x88,0x68,0x34,0x37,0x0E,0x46, + 0x40,0x07,0x1A,0xD5,0x00,0x21,0x04,0x20,0x79,0x5E,0x38,0x5E,0x00,0x22,0x09,0x1A, + 0xA2,0x5E,0x00,0x01,0x89,0x18,0x06,0x22,0x51,0x43,0x08,0x18,0x00,0x11,0x38,0x80, + 0x02,0x21,0xB8,0x5E,0x79,0x5E,0x02,0x22,0x09,0x1A,0xA2,0x5E,0x00,0x01,0x89,0x18, + 0x06,0x22,0x51,0x43,0x08,0x18,0x00,0x11,0x78,0x80,0x02,0x23,0x00,0x22,0x26,0x21, + 0x24,0x20,0xFB,0x5E,0xBA,0x5E,0x69,0x5E,0x28,0x5E,0x04,0xF0,0xCC,0xFF,0xC1,0x00, + 0x00,0x91,0x06,0x23,0x04,0x22,0x26,0x21,0x24,0x20,0xFB,0x5E,0xBA,0x5E,0x69,0x5E, + 0x28,0x5E,0x04,0xF0,0xC0,0xFF,0x00,0x99,0xC0,0x00,0x09,0x18,0x13,0xD0,0x00,0x9A, + 0x40,0x43,0x52,0x43,0x12,0x18,0x56,0x20,0x80,0x5D,0x41,0x43,0x10,0x46,0xFF,0xF7, + 0xCF,0xFA,0x0A,0x22,0xA2,0x5E,0x00,0x23,0x11,0x18,0x00,0x29,0x0B,0xD0,0x6F,0x7C, + 0xFF,0x09,0x02,0xD0,0x07,0xE0,0x00,0x20,0xF3,0xE7,0x52,0x43,0x40,0x43,0x10,0x18, + 0xFF,0xF7,0xBE,0xFA,0x03,0x46,0x1B,0xB2,0x63,0x81,0x20,0x36,0x30,0x7A,0x71,0x7A, + 0x40,0x00,0x4F,0x00,0x00,0x22,0xC1,0x1B,0x18,0x1A,0x02,0xD4,0x01,0x22,0x52,0x02, + 0x06,0xE0,0xD8,0x1B,0x00,0x28,0x03,0xDD,0x40,0x02,0xFF,0xF7,0xA9,0xFA,0x02,0x46, + 0x10,0x46,0x50,0x43,0x03,0x12,0xB0,0x7A,0x00,0xF0,0xDD,0xF8,0x07,0x46,0xF0,0x7A, + 0x00,0xF0,0xD9,0xF8,0x03,0x26,0x36,0x02,0xB2,0x1A,0x39,0x1A,0x5A,0x43,0x4A,0x43, + 0x01,0x21,0x49,0x04,0x51,0x18,0x89,0x14,0x0E,0x18,0x08,0x20,0x20,0x5E,0x81,0x19, + 0x1B,0xD0,0xB0,0x42,0x12,0xDA,0x2B,0x7C,0x04,0x22,0x1B,0x07,0x1B,0x0F,0x05,0x2B, + 0x00,0xD3,0x02,0x22,0x72,0x43,0x50,0x43,0x40,0x18,0xFF,0xF7,0x81,0xFA,0x00,0xB2, + 0x20,0x81,0xB0,0x42,0x00,0xDA,0x06,0x46,0x26,0x81,0x06,0xE0,0x40,0x43,0x76,0x43, + 0x80,0x19,0x40,0x1A,0xFF,0xF7,0x74,0xFA,0x20,0x81,0x08,0x20,0x20,0x5E,0x80,0x21, + 0x08,0x1A,0xF8,0xBD,0xF0,0xB5,0x04,0x46,0x06,0x46,0x0F,0x46,0x15,0x46,0x34,0x30, + 0x0E,0xC8,0x85,0xB0,0x48,0x34,0x68,0x46,0x05,0xF0,0xBC,0xFF,0x30,0x6C,0x08,0x21, + 0x01,0x90,0x61,0x5E,0x20,0x22,0x49,0x43,0x89,0x11,0x10,0x46,0x20,0x29,0x00,0xDC, + 0x08,0x46,0x00,0x2D,0x6B,0x46,0x06,0xD0,0x06,0x21,0x59,0x5E,0x12,0x1A,0x51,0x43, + 0x02,0x22,0x9A,0x5E,0x05,0xE0,0x04,0x21,0x59,0x5E,0x12,0x1A,0x51,0x43,0x00,0x22, + 0x9A,0x5E,0x6D,0x00,0x42,0x43,0x88,0x18,0x61,0x5F,0x2A,0x19,0x04,0x23,0x02,0x92, + 0x01,0x91,0xD3,0x5E,0x40,0x11,0x5A,0x10,0x10,0x18,0x0B,0x18,0x38,0x46,0x78,0x43, + 0x00,0x11,0x02,0x46,0x7A,0x43,0x9C,0x46,0xD2,0x11,0xF9,0x00,0xD3,0x00,0xD3,0x1A, + 0xC7,0x00,0xDB,0x19,0x4F,0x00,0xCF,0x19,0xDF,0x1B,0x01,0x23,0xDB,0x02,0xFF,0x18, + 0x63,0x46,0x5F,0x43,0xBC,0x46,0x53,0x00,0x5B,0x42,0x87,0x00,0xDB,0x19,0x0A,0x27, + 0x4F,0x43,0xDB,0x1B,0x01,0x27,0x7F,0x03,0x34,0x36,0xDB,0x19,0x77,0x5F,0xAE,0x19, + 0x7B,0x43,0x06,0x27,0x9C,0x44,0x78,0x43,0x93,0x00,0x1B,0x1A,0x4F,0x43,0xDF,0x19, + 0x01,0x23,0xDB,0x02,0xFF,0x18,0x04,0x23,0xF3,0x5E,0x03,0x93,0x5F,0x43,0x63,0x46, + 0xFB,0x18,0x97,0x00,0xD2,0x19,0x10,0x1A,0xCA,0x00,0x51,0x1A,0x40,0x18,0x08,0x21, + 0x71,0x5E,0x48,0x43,0xC0,0x18,0x03,0x21,0x09,0x03,0x4A,0x10,0x80,0x18,0xFF,0xF7, + 0xF7,0xF9,0x03,0x9B,0x01,0x99,0xC3,0x1A,0x02,0x9A,0x59,0x1A,0x91,0x80,0x63,0x53, + 0x05,0xB0,0xF0,0xBD,0xF8,0xB5,0x04,0x46,0x34,0x34,0x05,0x46,0x0E,0x46,0x48,0x35, + 0x17,0x46,0x02,0x21,0x8A,0x00,0x12,0x19,0x13,0x46,0x20,0x3B,0x49,0x1E,0xDB,0x69, + 0x49,0xB2,0x13,0x60,0x00,0x29,0xF5,0xDC,0x01,0x68,0x21,0x60,0x00,0x7C,0x00,0x07, + 0x00,0x0F,0x02,0x28,0x0E,0xD1,0x21,0x5E,0x06,0x23,0x04,0x22,0x00,0x20,0xE3,0x5E, + 0xA2,0x5E,0x20,0x5E,0x04,0xF0,0xAF,0xFE,0xC0,0x00,0x39,0x46,0xFF,0xF7,0xB2,0xF9, + 0x68,0x81,0x2E,0x81,0xF8,0xBD,0x32,0x28,0x04,0xDA,0x83,0x21,0xC9,0x01,0x48,0x43, + 0x00,0x14,0x70,0x47,0x64,0x21,0x08,0x1A,0xBF,0x21,0x40,0x43,0x09,0x02,0x48,0x43, + 0x00,0x15,0x80,0x21,0x08,0x1A,0x70,0x47,0x70,0xB5,0x53,0x00,0xC2,0x5E,0x1D,0x18, + 0x0C,0x68,0x8E,0x68,0x4B,0x68,0x04,0x20,0x21,0x46,0x28,0x5E,0x71,0x43,0x00,0x2B, + 0x10,0xD0,0x08,0x26,0xAE,0x5F,0x80,0x00,0x80,0x1A,0x80,0x1B,0x15,0x1A,0xAD,0x19, + 0x65,0x43,0x54,0x00,0x00,0x1B,0x58,0x43,0x28,0x18,0x48,0x43,0x00,0x0B,0x80,0x18, + 0x00,0xB2,0x70,0xBD,0x12,0x1A,0x51,0x43,0x09,0x0B,0x08,0x18,0xF8,0xE7,0x00,0x00, + 0xFF,0xB5,0x00,0x20,0x8B,0xB0,0x00,0x90,0x07,0x90,0x05,0x90,0x01,0x90,0x04,0x46, + 0x05,0x46,0x1A,0x79,0x98,0x79,0x04,0x90,0x58,0x79,0x03,0x90,0xD8,0x79,0x02,0x90, + 0x0D,0x98,0x1E,0x46,0x40,0x78,0x06,0x90,0x00,0x20,0x08,0x90,0x0C,0x98,0x00,0x28, + 0x10,0xD1,0x04,0x98,0x52,0x1E,0x40,0x1C,0x04,0x90,0x03,0x98,0x40,0x1E,0x03,0x90, + 0x02,0x98,0x03,0x99,0x40,0x1C,0x02,0x90,0x40,0x1A,0x40,0x1C,0x06,0x90,0x50,0x43, + 0x40,0x18,0x08,0x90,0x00,0x20,0x86,0x46,0x5B,0xE0,0x03,0x99,0x55,0xE0,0x06,0x98, + 0x50,0x43,0x43,0x18,0x08,0x98,0x18,0x1A,0x03,0xB2,0x0B,0x98,0x5F,0x00,0xC0,0x5F, + 0x00,0x28,0x49,0xDD,0x0C,0x9F,0x00,0x2F,0x0E,0xD0,0xFB,0x5C,0x37,0x7B,0xBF,0x08, + 0xBB,0x42,0x01,0xD0,0x0F,0x2B,0x3F,0xD3,0x15,0x2B,0x00,0xD1,0x40,0x10,0x40,0x23, + 0x40,0x28,0x00,0xDC,0x03,0x46,0x9E,0x44,0x07,0x9B,0x83,0x42,0x03,0xDA,0x03,0xB2, + 0x07,0x93,0x32,0x72,0x71,0x72,0x01,0x23,0x5B,0x02,0x98,0x42,0x00,0xDA,0x03,0x46, + 0x5B,0x43,0x00,0x98,0x9C,0x46,0xC0,0x18,0x00,0x90,0x18,0x46,0x5B,0x08,0x48,0x43, + 0xC0,0x18,0x09,0x93,0x05,0x9B,0xC0,0x01,0x18,0x41,0x04,0xE0,0x05,0x9B,0x64,0x10, + 0x5B,0x1C,0x40,0x10,0x05,0x93,0x01,0x23,0x27,0x18,0x1B,0x06,0x9F,0x42,0xF5,0xDA, + 0x24,0x18,0x60,0x46,0x09,0x9B,0x50,0x43,0xC0,0x18,0x01,0x9B,0xC0,0x01,0x18,0x41, + 0x04,0xE0,0x01,0x9B,0x6D,0x10,0x5B,0x1C,0x40,0x10,0x01,0x93,0x01,0x23,0x2F,0x18, + 0x1B,0x06,0x9F,0x42,0xF5,0xDA,0x2D,0x18,0x49,0x1C,0x02,0x98,0x81,0x42,0xA6,0xDD, + 0x52,0x1C,0x04,0x98,0x82,0x42,0xA0,0xDD,0x0C,0x98,0x00,0x28,0x0B,0xD0,0x71,0x46, + 0x15,0x4A,0xFF,0x20,0x89,0x1D,0x91,0x42,0x04,0xDA,0x70,0x46,0x0C,0x21,0x80,0x1D, + 0xFF,0xF7,0xF6,0xF8,0xF0,0x72,0x00,0x98,0x00,0x28,0x19,0xDD,0x01,0x46,0x05,0x98, + 0x01,0x41,0x20,0x46,0xFF,0xF7,0xEC,0xF8,0x04,0x46,0x00,0x99,0x01,0x98,0x01,0x41, + 0x28,0x46,0xFF,0xF7,0xE5,0xF8,0x05,0x46,0x01,0x21,0x20,0x46,0x0D,0x9A,0x00,0xF0, + 0x25,0xFC,0x30,0x80,0x00,0x21,0x28,0x46,0x0D,0x9A,0x00,0xF0,0x1F,0xFC,0x70,0x80, + 0x00,0x20,0x0F,0xB0,0xF0,0xBD,0x00,0x00,0xF4,0x0B,0x00,0x00,0xFF,0xB5,0x10,0x88, + 0x89,0xB0,0x15,0x46,0x00,0x28,0x7E,0xD0,0x0A,0x99,0x0A,0x9A,0x49,0x78,0x12,0x78, + 0x10,0x20,0x51,0x43,0x09,0x09,0x10,0x29,0x00,0xD3,0x08,0x46,0x04,0x90,0x04,0xF0, + 0xBD,0xFA,0x00,0x90,0x0A,0x98,0x80,0x78,0x80,0x1C,0x07,0x90,0x00,0x20,0x06,0x90, + 0x28,0x46,0x08,0x30,0x05,0x90,0x00,0x20,0xB8,0xE0,0xC4,0x00,0x05,0x98,0x26,0x18, + 0x0A,0x98,0xB1,0x79,0x40,0x7F,0x81,0x42,0x6F,0xD9,0x06,0x9B,0x07,0x98,0x83,0x42, + 0x13,0xDB,0xFF,0x21,0x00,0x20,0x08,0xE0,0x0C,0x9A,0x07,0x01,0xBA,0x18,0x52,0x7B, + 0x8A,0x42,0x01,0xDA,0x11,0x46,0x03,0x46,0x40,0x1C,0x07,0x9A,0x90,0x42,0xF3,0xDB, + 0x60,0x19,0x80,0x7B,0x88,0x42,0x58,0xDB,0x01,0xE0,0x58,0x1C,0x06,0x90,0x0C,0x98, + 0x19,0x01,0x0C,0x18,0x20,0x7B,0x31,0x79,0x80,0x07,0x89,0x08,0x80,0x0F,0x89,0x00, + 0x08,0x43,0x20,0x73,0x31,0x79,0x40,0x08,0xC9,0x07,0x40,0x00,0xC9,0x0F,0x08,0x43, + 0x20,0x73,0xFD,0x21,0x08,0x40,0x31,0x79,0x89,0x07,0xC9,0x0F,0x49,0x00,0x08,0x43, + 0x20,0x73,0xB0,0x79,0x60,0x73,0x70,0x79,0xA0,0x72,0x00,0x20,0xE0,0x72,0x30,0x68, + 0x60,0x60,0xF0,0x78,0x71,0x78,0x32,0x78,0x40,0x1A,0xB1,0x78,0x40,0x1C,0x89,0x1A, + 0x32,0x79,0x49,0x1C,0xD2,0x07,0x75,0xD1,0x02,0x46,0x04,0x9B,0x4A,0x43,0x9A,0x42, + 0x70,0xDA,0x0A,0x9A,0x92,0x68,0x92,0x06,0x6C,0xD5,0x80,0x1C,0x89,0x1C,0x02,0x90, + 0x01,0x91,0x48,0x43,0x41,0x00,0x00,0x98,0xFF,0xF7,0x8D,0xF8,0x30,0x78,0x09,0x99, + 0x40,0x1E,0x14,0x22,0x00,0xE0,0x5B,0xE0,0x8A,0x56,0x71,0x78,0x50,0x43,0x40,0x18, + 0x40,0x1E,0x86,0x46,0x01,0x99,0x00,0x20,0x01,0x23,0x49,0x1E,0x08,0x91,0x2A,0xE0, + 0x02,0x9A,0x01,0x21,0x52,0x1E,0x94,0x46,0x21,0xE0,0x3D,0xE0,0x09,0x9A,0x14,0x26, + 0x96,0x57,0x72,0x46,0x5E,0x43,0x8A,0x18,0xB2,0x18,0x6E,0x68,0x27,0x7B,0xB6,0x5C, + 0xBF,0x08,0xBE,0x42,0x01,0xD0,0x0F,0x2E,0x10,0xD3,0x09,0x9E,0x52,0x00,0x36,0x68, + 0xB2,0x5E,0x00,0x2A,0x04,0xDD,0x40,0x26,0x40,0x2A,0x00,0xDC,0x16,0x46,0x30,0x18, + 0x02,0x9E,0x5E,0x43,0x76,0x18,0x77,0x00,0x00,0x9E,0xF2,0x53,0x49,0x1C,0x61,0x45, + 0xDC,0xDB,0x08,0x99,0x5B,0x1C,0x8B,0x42,0xD2,0xDB,0x15,0x4B,0xFF,0x21,0x82,0x1D, + 0x9A,0x42,0x04,0xDA,0x0C,0x21,0x80,0x1D,0xFF,0xF7,0x0A,0xF8,0x01,0x46,0xE1,0x72, + 0x00,0x9B,0x01,0x9A,0x18,0x46,0x02,0x99,0x03,0xF0,0xD6,0xF8,0x23,0x46,0x00,0x21, + 0x0A,0x9A,0x00,0x98,0xFF,0xF7,0x6C,0xFE,0x03,0x98,0x40,0x1C,0x00,0x21,0x03,0x90, + 0x69,0x5E,0x81,0x42,0x01,0xDD,0x40,0xE7,0x04,0xE0,0x04,0xF0,0x05,0xFA,0x06,0x98, + 0x0D,0xB0,0xF0,0xBD,0x09,0x98,0x69,0x68,0x00,0x68,0x23,0x46,0x0A,0x9A,0xE9,0xE7, + 0xF4,0x0B,0x00,0x00,0xFF,0xB5,0x86,0x46,0x00,0x20,0x85,0xB0,0x00,0x90,0x01,0x90, + 0x04,0x46,0x06,0x46,0x05,0x46,0x0F,0x78,0x88,0x78,0x8C,0x46,0x03,0x90,0x2F,0xE0, + 0x60,0x46,0x43,0x78,0xC0,0x78,0x02,0x90,0x26,0xE0,0x71,0x46,0x14,0x20,0x08,0x56, + 0x0A,0x68,0x78,0x43,0xC0,0x18,0x41,0x00,0x52,0x5E,0x00,0x2A,0x1A,0xDD,0x0E,0x99, + 0x08,0x5C,0x08,0x99,0x08,0x40,0x07,0x99,0x88,0x42,0x01,0xD0,0x15,0x28,0x11,0xD1, + 0x00,0x99,0x89,0x18,0x00,0x91,0x11,0x46,0x51,0x43,0x4D,0x19,0x11,0x46,0xB2,0x42, + 0x00,0xDC,0x31,0x46,0x0E,0x46,0x01,0x99,0x49,0x1C,0x01,0x91,0x10,0x99,0x8A,0x42, + 0x00,0xDB,0x64,0x1C,0x02,0x98,0x5B,0x1C,0x98,0x42,0xD6,0xDA,0x03,0x98,0x7F,0x1C, + 0xB8,0x42,0xCD,0xDA,0x10,0x99,0x00,0x20,0x8E,0x42,0x36,0xDB,0x0F,0x9F,0x0A,0x20, + 0x47,0x43,0x39,0x46,0x00,0x98,0xFE,0xF7,0x9B,0xFF,0x40,0x1C,0x40,0x21,0x40,0x28, + 0x00,0xDA,0x01,0x46,0x88,0x00,0x01,0x46,0xFF,0x22,0x41,0x43,0x81,0x32,0x10,0x1A, + 0x41,0x43,0xC8,0x12,0x01,0x21,0x89,0x02,0x46,0x18,0x01,0x99,0x08,0x20,0x09,0x19, + 0x08,0x29,0x00,0xDA,0x08,0x46,0x80,0x01,0x05,0xF0,0xDC,0xF9,0x68,0x43,0x00,0x99, + 0xFE,0xF7,0x7E,0xFF,0x0A,0x21,0x48,0x43,0x39,0x46,0xFE,0xF7,0x79,0xFF,0xAA,0x28, + 0x00,0xDB,0xAA,0x20,0x01,0x46,0xFF,0x22,0x41,0x43,0x01,0x32,0x10,0x1A,0x41,0x43, + 0x88,0x13,0x46,0x43,0x2B,0x20,0x46,0x43,0x70,0x14,0x09,0xB0,0xF0,0xBD,0x00,0x00, + 0xF7,0xB5,0x96,0xB0,0x17,0x98,0xC0,0x30,0x09,0x90,0xC0,0x68,0x00,0x28,0x7E,0xD0, + 0x16,0x98,0x15,0x26,0x14,0x24,0x86,0x57,0x04,0x57,0x07,0x68,0x09,0x98,0x21,0xC8, + 0x0E,0x90,0x04,0xF0,0x53,0xF9,0x03,0x46,0x0F,0x90,0x32,0x46,0x21,0x46,0x38,0x46, + 0x03,0xF0,0x22,0xF8,0x0F,0x98,0x06,0x90,0x00,0x20,0x31,0x46,0x61,0x43,0x01,0x91, + 0x12,0xE0,0x41,0x00,0x0F,0x9A,0x7B,0x5E,0x51,0x5E,0x49,0x10,0x5A,0x1A,0x14,0x32, + 0x00,0x21,0x02,0x2A,0x04,0xDB,0xFF,0x21,0xFF,0x2A,0x00,0xDA,0x11,0x46,0x09,0xB2, + 0x06,0x9A,0x11,0x54,0x01,0x99,0x40,0x1C,0x81,0x42,0xEA,0xDC,0x30,0x46,0x60,0x43, + 0x04,0xF0,0x4A,0xF9,0x04,0xF0,0x2A,0xF9,0x04,0x46,0xF0,0x20,0x04,0xF0,0x44,0xF9, + 0xF0,0x21,0x20,0x46,0xFE,0xF7,0x5F,0xFF,0x09,0x98,0x00,0x21,0xC0,0x68,0x00,0x90, + 0x41,0x5E,0x00,0x22,0x8C,0x46,0x10,0x46,0x16,0xE0,0x00,0x99,0xC3,0x00,0x5B,0x18, + 0x19,0x7B,0xCE,0x07,0xF6,0x0F,0x01,0x01,0x76,0x1C,0x09,0x19,0x8E,0x72,0xDF,0x68, + 0x9E,0x68,0x4F,0x60,0x0E,0x60,0x0E,0x79,0x76,0x08,0x76,0x00,0x0E,0x71,0xD9,0x7B, + 0x91,0x42,0x00,0xDD,0x0A,0x46,0x40,0x1C,0x61,0x46,0x60,0x45,0xE5,0xDB,0x09,0x98, + 0x40,0x69,0x40,0x30,0xC2,0x73,0x0E,0x00,0x03,0xD1,0x07,0x21,0x28,0x46,0xFE,0xF7, + 0x32,0xFF,0x01,0x98,0x5A,0x21,0x40,0x10,0x5A,0x28,0x00,0xDD,0x01,0x46,0x09,0x98, + 0x11,0x96,0x40,0x69,0x02,0x7F,0x00,0x2A,0x78,0xD0,0x40,0x30,0xC0,0x7B,0x88,0x42, + 0x74,0xDC,0x76,0xB2,0x68,0x46,0x06,0x74,0x00,0x27,0x38,0x46,0x00,0xE0,0xFF,0xE1, + 0x05,0x96,0x0E,0xE0,0x02,0x01,0x11,0x19,0x8B,0x78,0xA2,0x5C,0x9A,0x1A,0xCB,0x78, + 0x49,0x78,0x59,0x1A,0x51,0x18,0x89,0x1C,0xB9,0x42,0x00,0xDC,0x39,0x46,0x0F,0x46, + 0x40,0x1C,0xB0,0x42,0xEE,0xDB,0x00,0x2F,0x58,0xD0,0x04,0xF0,0xC7,0xF8,0x10,0x90, + 0x38,0x01,0xC0,0x1B,0x18,0x30,0x04,0xF0,0xDF,0xF8,0x2F,0xE0,0x68,0x46,0x10,0x27, + 0xC7,0x57,0x0F,0x2F,0x2C,0xDA,0x30,0x46,0x00,0x01,0x10,0x38,0x00,0x19,0x84,0x46, + 0x80,0x7A,0x76,0x1E,0x01,0x28,0x21,0xD0,0x38,0x01,0x00,0x19,0x00,0x21,0x01,0x60, + 0x41,0x60,0x81,0x60,0xC1,0x60,0x01,0x79,0xBA,0x00,0x89,0x07,0x89,0x0F,0x11,0x43, + 0x01,0x71,0x00,0x23,0x17,0x9A,0x03,0x93,0x10,0x99,0x6B,0x46,0x07,0xC3,0x63,0x46, + 0x0E,0x9A,0x06,0x99,0x16,0x98,0x02,0xF0,0x7B,0xF8,0x00,0x28,0x06,0xD0,0x02,0xDD, + 0x7F,0x1C,0x68,0x46,0x07,0x74,0x68,0x46,0x10,0x26,0x86,0x57,0x00,0x2E,0xCD,0xD1, + 0x10,0x22,0x68,0x46,0x82,0x56,0x00,0x21,0x08,0x46,0x06,0xE0,0x03,0x01,0x1B,0x19, + 0xDB,0x89,0x00,0x2B,0x00,0xD0,0x49,0x1C,0x40,0x1C,0x90,0x42,0xF6,0xDB,0x00,0x20, + 0x28,0x56,0x90,0x42,0x32,0xDD,0x05,0x22,0xAA,0x56,0x05,0x98,0x82,0x42,0x2D,0xD1, + 0x04,0x20,0x28,0x56,0x88,0x42,0x29,0xDA,0x00,0x27,0x22,0xE0,0x19,0xE1,0x0F,0x2E, + 0x24,0xDA,0x38,0x01,0x00,0x19,0x84,0x46,0xC0,0x89,0x00,0x28,0x18,0xD0,0x30,0x01, + 0x00,0x19,0x01,0x79,0xB2,0x00,0x89,0x07,0x89,0x0F,0x11,0x43,0x01,0x71,0x50,0x23, + 0x17,0x9A,0x03,0x93,0x10,0x99,0x6B,0x46,0x07,0xC3,0x63,0x46,0x0E,0x9A,0x06,0x99, + 0x16,0x98,0x02,0xF0,0x35,0xF8,0x00,0x28,0x02,0xD0,0x76,0x1C,0x68,0x46,0x06,0x74, + 0x7F,0x1C,0x68,0x46,0x10,0x26,0x86,0x57,0xB7,0x42,0xD8,0xDB,0x09,0x98,0x40,0x69, + 0x12,0x90,0x80,0x68,0xC0,0x05,0x79,0xD5,0x00,0x20,0x69,0x46,0x10,0x26,0x28,0x56, + 0x8E,0x57,0xB0,0x42,0x03,0xDB,0x02,0x20,0x28,0x56,0xB0,0x42,0x6E,0xDA,0xFF,0x22, + 0x0F,0x21,0x05,0xA8,0xFE,0xF7,0x68,0xFE,0x00,0x21,0x14,0x96,0x57,0xE0,0x08,0x01, + 0x00,0x19,0x02,0x79,0xD2,0x07,0x51,0xD0,0x12,0x9A,0x84,0x46,0x92,0x78,0x00,0x20, + 0x13,0x92,0x49,0xE0,0x09,0x9A,0x13,0x69,0x54,0x22,0x42,0x43,0x16,0x46,0x1F,0x46, + 0x10,0x36,0x9B,0x5D,0x1B,0x07,0x3D,0xD0,0x36,0x1F,0xBB,0x5D,0x9B,0x07,0x39,0xD4, + 0x12,0x1D,0xBA,0x18,0x13,0x78,0x66,0x46,0x03,0x93,0x36,0x78,0x76,0x1C,0xB3,0x42, + 0x30,0xD8,0x53,0x78,0x66,0x46,0x01,0x93,0x76,0x78,0x76,0x1C,0xB3,0x42,0x29,0xD8, + 0x93,0x78,0x66,0x46,0x02,0x93,0xB6,0x78,0x76,0x1E,0xB3,0x42,0x22,0xDB,0xD2,0x78, + 0x63,0x46,0x00,0x92,0xDB,0x78,0x5B,0x1E,0x9A,0x42,0x1B,0xDB,0x05,0xAB,0x5A,0x56, + 0x56,0x1C,0x16,0xD0,0x54,0x23,0x5A,0x43,0x03,0x9E,0x02,0x9B,0x12,0x1D,0xBA,0x18, + 0x9B,0x1B,0x01,0x9F,0x00,0x9E,0xF6,0x1B,0x73,0x43,0x96,0x78,0x17,0x78,0xF6,0x1B, + 0xD7,0x78,0x52,0x78,0xBA,0x1A,0x56,0x43,0xB3,0x42,0x03,0xDD,0x05,0xAA,0x50,0x54, + 0x00,0xE0,0x58,0x54,0x13,0x9A,0x40,0x1C,0x82,0x42,0xB3,0xDC,0x49,0x1C,0x14,0x98, + 0x81,0x42,0xA4,0xDB,0x00,0x20,0x0A,0x90,0x0B,0x90,0x0C,0x90,0x0D,0x90,0x40,0x1E, + 0x03,0x90,0x14,0x98,0x00,0x26,0x40,0x1E,0x15,0x90,0x6A,0xE0,0x6B,0xE0,0x0A,0xA8, + 0x80,0x5D,0x01,0x28,0x63,0xD0,0x03,0x98,0x40,0x1C,0x03,0x90,0x05,0xA8,0x80,0x57, + 0x40,0x1C,0x5C,0xD0,0x77,0x1C,0x4A,0xE0,0x05,0xA8,0x81,0x57,0xC0,0x57,0x81,0x42, + 0x44,0xD1,0x30,0x01,0x00,0x19,0x12,0x90,0x41,0x79,0x38,0x01,0x03,0x19,0x5A,0x79, + 0x91,0x42,0x3B,0xD1,0x00,0x90,0x12,0x98,0x01,0x93,0x13,0x90,0x00,0x79,0x14,0x21, + 0x82,0x08,0x16,0x98,0x41,0x56,0x0E,0x98,0x02,0xF0,0xD3,0xFA,0x00,0x98,0x01,0x9B, + 0x21,0x5C,0x5A,0x78,0x12,0x98,0x04,0xF0,0x19,0xFE,0x01,0x9B,0x12,0x98,0xDA,0x78, + 0x99,0x78,0x04,0xF0,0x13,0xFE,0x13,0x98,0x01,0x9B,0xC0,0x79,0xD9,0x79,0x41,0x18, + 0x13,0x98,0xC1,0x71,0x09,0x98,0x0E,0x99,0x40,0x69,0x03,0x7D,0x82,0x7D,0x68,0x46, + 0x0E,0xC0,0x13,0x98,0xFF,0x23,0x00,0x79,0x12,0x99,0x82,0x08,0x16,0x98,0xFF,0xF7, + 0x99,0xFD,0x01,0x46,0x13,0x98,0x81,0x71,0x01,0x20,0x0A,0xA9,0xC8,0x55,0x69,0x46, + 0x08,0x7C,0x40,0x1E,0x08,0x74,0xFF,0x20,0x05,0xA9,0xC8,0x55,0x7F,0x1C,0x14,0x98, + 0x87,0x42,0xB1,0xDB,0x03,0x98,0x86,0x42,0x09,0xD0,0x31,0x01,0x09,0x19,0x0A,0x46, + 0x8C,0xCA,0x00,0x01,0x00,0x19,0xC9,0x68,0x8C,0xC0,0x0C,0x38,0xC1,0x60,0x15,0x98, + 0x76,0x1C,0x86,0x42,0x93,0xDB,0x10,0x98,0x03,0xF0,0x96,0xFF,0x68,0x46,0x10,0x26, + 0x86,0x57,0x00,0x21,0x08,0x46,0x07,0xE0,0x02,0x01,0x12,0x19,0xD2,0x89,0x00,0x2A, + 0x00,0xD0,0x49,0x1C,0x40,0x1C,0x40,0xB2,0xB0,0x42,0xF5,0xDB,0x05,0x22,0xAA,0x56, + 0x11,0x98,0x82,0x42,0x09,0xD0,0x2E,0x70,0x01,0x20,0x68,0x70,0x00,0x20,0xA8,0x70, + 0xE8,0x70,0x29,0x71,0x11,0x98,0x68,0x71,0x20,0xE0,0x00,0x20,0x28,0x56,0xB0,0x42, + 0x2C,0x48,0x28,0x56,0x16,0xD0,0x03,0x28,0x08,0xDA,0x2E,0x70,0x02,0x20,0x28,0x56, + 0xB0,0x42,0x01,0xD1,0xE8,0x78,0x10,0xE0,0x00,0x20,0x0E,0xE0,0x02,0x21,0x69,0x56, + 0xB1,0x42,0x02,0xD1,0xE9,0x78,0x49,0x1C,0x01,0xE0,0xAE,0x70,0x00,0x21,0xE9,0x70, + 0x40,0x10,0x02,0xE0,0x7F,0x28,0x01,0xDA,0x40,0x1C,0x68,0x70,0x09,0x98,0xC2,0x68, + 0x00,0x20,0x10,0x80,0x24,0xE0,0x01,0x01,0x09,0x19,0x8B,0x7A,0x00,0x2B,0x1E,0xD0, + 0x00,0x23,0xD3,0x5E,0x0F,0x2B,0x1A,0xDA,0xDB,0x00,0x9B,0x18,0x4F,0x68,0x0D,0x68, + 0xDF,0x60,0x9D,0x60,0x00,0x23,0xD3,0x5E,0x0F,0x79,0xDB,0x00,0x9B,0x18,0x1D,0x7B, + 0xBF,0x08,0xAD,0x07,0xAD,0x0F,0xBF,0x00,0x3D,0x43,0x1D,0x73,0x00,0x23,0xD3,0x5E, + 0x49,0x79,0xDB,0x00,0x9B,0x18,0x59,0x73,0x11,0x88,0x49,0x1C,0x11,0x80,0x40,0x1C, + 0xB0,0x42,0xD8,0xDB,0x09,0x98,0x18,0x9B,0x41,0x69,0x16,0x98,0xFF,0xF7,0x16,0xFC, + 0x05,0x46,0x20,0x46,0x03,0xF0,0x20,0xFF,0x0F,0x98,0x03,0xF0,0x1D,0xFF,0x28,0x46, + 0x19,0xB0,0xF0,0xBD,0x01,0x00,0x00,0x00,0xF8,0xB5,0x04,0x46,0x04,0xF0,0x7C,0xF9, + 0x66,0x78,0x25,0x78,0xFF,0x34,0x41,0x34,0x64,0x68,0x03,0xF0,0xCF,0xFE,0x27,0x46, + 0xC0,0x37,0x38,0x60,0x28,0x46,0x70,0x43,0x03,0xF0,0xE6,0xFE,0x03,0xF0,0xC6,0xFE, + 0x78,0x60,0x07,0x20,0x03,0xF0,0xE0,0xFE,0x07,0x21,0x78,0x68,0xFE,0xF7,0xFB,0xFC, + 0x01,0x48,0x60,0x60,0x00,0x20,0xF8,0xBD,0xE1,0x11,0x00,0x00,0xF8,0xB5,0x05,0x46, + 0x50,0x7E,0x00,0x29,0x01,0xD0,0x00,0x09,0x01,0xE0,0x00,0x07,0x00,0x0F,0x00,0x90, + 0x00,0x29,0x01,0xD0,0x94,0x7E,0x00,0xE0,0xD4,0x7E,0x00,0x29,0x01,0xD0,0x97,0x88, + 0x00,0xE0,0xD7,0x88,0x69,0x00,0xC8,0x1B,0x00,0x28,0x00,0xDC,0x78,0x1A,0x38,0x1A, + 0x80,0x26,0x40,0x10,0x30,0x1A,0x00,0x28,0x05,0xDD,0x40,0x00,0x60,0x43,0x31,0x46, + 0xFE,0xF7,0x96,0xFC,0x04,0x19,0x68,0x02,0x39,0x02,0x40,0x1A,0xFF,0x30,0x39,0x46, + 0x01,0x30,0x81,0x39,0xFE,0xF7,0x8C,0xFC,0xFF,0x21,0xC9,0x43,0x88,0x42,0x03,0xDD, + 0x49,0x42,0xFF,0x28,0x00,0xDC,0x01,0x46,0x08,0x46,0x48,0x43,0x02,0x12,0x00,0x20, + 0x02,0xE0,0x52,0x43,0x12,0x12,0x40,0x1C,0x00,0x9B,0x98,0x42,0xF9,0xDB,0x00,0x29, + 0x00,0xDA,0x52,0x42,0x70,0x10,0x50,0x43,0x60,0x43,0x00,0x02,0x64,0x21,0xFE,0xF7, + 0x6F,0xFC,0x29,0x04,0x08,0x18,0x00,0x14,0xF8,0xBD,0xF0,0xB5,0x83,0x78,0x20,0x31, + 0x00,0x25,0x00,0x2A,0x28,0xD1,0x8E,0x7B,0x0A,0x22,0xC4,0x88,0x56,0x43,0xAA,0x1E, + 0xB4,0x42,0x21,0xD3,0x4E,0x7B,0x0A,0x27,0x7E,0x43,0xB4,0x42,0x1C,0xD8,0x01,0x2B, + 0x06,0xD0,0x01,0x23,0x83,0x70,0x83,0x8A,0x03,0x81,0xC3,0x8A,0x43,0x81,0x15,0xE0, + 0x82,0x8A,0x03,0x89,0x44,0x89,0xD2,0x1A,0xC3,0x8A,0x09,0x7C,0x1B,0x1B,0x52,0x43, + 0x5B,0x43,0xC9,0x01,0xD2,0x18,0x49,0x43,0x8A,0x42,0x01,0xDA,0x01,0x22,0x01,0xE0, + 0x00,0x22,0xD2,0x43,0x85,0x70,0x0C,0xE0,0x01,0x2B,0x0A,0xD1,0x09,0x7B,0x83,0x88, + 0x0A,0x24,0x61,0x43,0x8B,0x42,0x04,0xD9,0x00,0x2A,0x02,0xDA,0x85,0x70,0x00,0x22, + 0x01,0xE0,0x51,0x1C,0x00,0xDB,0x85,0x70,0x50,0xB2,0xF0,0xBD,0xF7,0xB5,0x05,0x46, + 0xC0,0x35,0x84,0xB0,0x29,0x69,0x68,0x69,0x02,0x91,0x81,0x88,0x00,0x24,0x49,0x1E, + 0x00,0x91,0xC1,0x88,0x20,0x30,0x49,0x1E,0x01,0x91,0x03,0x90,0xC1,0x7B,0x64,0x20, + 0x40,0x1A,0x00,0x99,0x07,0x46,0x48,0x43,0xC8,0x21,0xFE,0xF7,0xFB,0xFB,0x06,0x46, + 0x01,0x99,0x38,0x46,0x48,0x43,0xC8,0x21,0xFE,0xF7,0xF4,0xFB,0x03,0x46,0x00,0x21, + 0x22,0xE0,0x54,0x20,0x02,0x9A,0x48,0x43,0x82,0x18,0x10,0x7C,0x07,0x07,0x03,0x98, + 0x3F,0x0F,0xC0,0x78,0x87,0x42,0x16,0xD9,0x20,0x27,0x05,0x98,0xD7,0x5F,0x07,0x60, + 0x22,0x20,0x10,0x5E,0x06,0x9A,0x10,0x60,0x05,0x9A,0x12,0x68,0xB2,0x42,0x0A,0xD3, + 0x98,0x42,0x08,0xD3,0x00,0x9F,0xBF,0x1B,0xBA,0x42,0x04,0xD8,0x01,0x9A,0xD2,0x1A, + 0x90,0x42,0x00,0xD8,0x64,0x1C,0x49,0x1C,0x68,0x69,0x80,0x78,0x88,0x42,0xD8,0xDC, + 0x20,0x46,0x07,0xB0,0xF0,0xBD,0x00,0x00,0x70,0xB5,0x0D,0x4C,0x0D,0x4D,0x20,0x68, + 0x20,0x30,0x01,0x7C,0x40,0x7C,0x41,0x43,0x49,0x00,0x28,0x6D,0xFE,0xF7,0x0B,0xFC, + 0x20,0x68,0x20,0x30,0x00,0x7C,0x41,0x00,0x68,0x6D,0xFE,0xF7,0x04,0xFC,0x20,0x68, + 0x20,0x30,0x40,0x7C,0x41,0x00,0xA8,0x6D,0xFE,0xF7,0xFD,0xFB,0x70,0xBD,0x00,0x00, + 0x10,0x06,0x00,0x20,0xAC,0x03,0x00,0x20,0xC3,0x07,0x00,0x21,0x09,0x4A,0x00,0x2B, + 0x00,0xD0,0x11,0x70,0x83,0x06,0x00,0xD5,0x51,0x71,0x83,0x07,0x00,0xD5,0x51,0x70, + 0x03,0x07,0x00,0xD5,0xD1,0x70,0x43,0x07,0x00,0xD5,0x91,0x70,0xC0,0x06,0x00,0xD5, + 0x11,0x71,0x70,0x47,0x48,0x20,0x00,0x20,0x10,0xB5,0x0E,0x4C,0xA0,0x7A,0xC1,0x06, + 0x16,0xD5,0x11,0x28,0x05,0xD1,0x5C,0x22,0x0B,0x49,0x0C,0x48,0xFE,0xF7,0xAC,0xFB, + 0x0A,0xE0,0x12,0x28,0x08,0xD1,0x0A,0x48,0x9C,0x22,0x01,0x68,0x06,0x48,0xFF,0x31, + 0xA1,0x31,0xFE,0xF7,0xA1,0xFB,0xEE,0xE7,0x01,0x20,0xA0,0x71,0x00,0x20,0xA0,0x72, + 0x10,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0x32,0x05,0x00,0x20,0xD6,0x04,0x00,0x20, + 0x10,0x06,0x00,0x20,0xFF,0xB5,0x86,0xB0,0x00,0x20,0x04,0x90,0x08,0x68,0x02,0x90, + 0x14,0x20,0x01,0x26,0x08,0x56,0x01,0x90,0x15,0x20,0x08,0x56,0x1D,0x46,0xB4,0x46, + 0x05,0x90,0x04,0x98,0x40,0x00,0x29,0x5C,0x40,0x19,0x00,0x91,0x40,0x78,0x03,0x90, + 0x04,0x98,0x40,0x1C,0x80,0x06,0x80,0x0E,0x04,0x90,0x01,0x98,0x41,0x43,0x03,0x98, + 0x08,0x18,0x41,0x00,0x02,0x98,0x41,0x5E,0x10,0x98,0x81,0x42,0x2D,0xDB,0x03,0x24, + 0x03,0x9A,0x00,0x99,0xE0,0x07,0x05,0xD0,0x12,0x19,0x01,0x98,0x92,0x1E,0x82,0x42, + 0x21,0xD2,0x04,0xE0,0x09,0x19,0x05,0x98,0x49,0x1E,0x81,0x42,0x1B,0xD2,0x01,0x98, + 0x06,0x9B,0x48,0x43,0x80,0x18,0x1B,0x5C,0x0F,0x2B,0x14,0xD3,0x02,0x9B,0x47,0x00, + 0xDF,0x5F,0x11,0x9B,0x9F,0x42,0x0E,0xDB,0x06,0x9F,0x08,0x9B,0x3B,0x54,0x60,0x46, + 0x40,0x00,0x29,0x54,0x40,0x19,0x42,0x70,0x0F,0x98,0x04,0xF0,0xAF,0xFB,0x76,0x1C, + 0xB0,0x06,0x80,0x0E,0x84,0x46,0x64,0x1E,0xD2,0xD5,0x04,0x98,0x60,0x45,0xB8,0xD1, + 0x30,0x46,0x0A,0xB0,0xF0,0xBD,0xFF,0xB5,0x8D,0xB0,0xC0,0x31,0x02,0x91,0x48,0x69, + 0x07,0x90,0x0E,0x68,0x00,0x2E,0x06,0xD0,0x40,0x30,0x01,0x7C,0x00,0x29,0x02,0xD0, + 0x00,0x7A,0x00,0x28,0x02,0xD0,0x00,0x20,0x11,0xB0,0xF0,0xBD,0x0D,0x98,0x14,0x21, + 0x41,0x56,0x04,0x91,0x01,0x46,0x15,0x20,0x08,0x56,0x05,0x90,0x08,0x68,0x08,0x90, + 0x04,0x99,0x05,0x98,0x1F,0x22,0x41,0x43,0x30,0x46,0xFE,0xF7,0x35,0xFB,0x02,0x98, + 0x80,0x21,0xC0,0x68,0x09,0x90,0xFE,0xF7,0x36,0xFB,0x09,0x98,0x46,0x60,0x00,0x20, + 0x00,0x90,0x01,0x90,0x02,0x98,0x41,0x69,0x01,0x98,0x80,0x00,0x5F,0x30,0x09,0x18, + 0x88,0x78,0x00,0x28,0x3E,0xD0,0x00,0x98,0x00,0x23,0xC0,0xB2,0x0A,0x78,0x84,0x46, + 0x18,0xE0,0x48,0x78,0x12,0xE0,0x0D,0x9C,0x27,0x46,0x25,0x68,0x14,0x24,0x3C,0x57, + 0x54,0x43,0x27,0x18,0x7F,0x00,0xEF,0x5F,0x02,0x9D,0x6D,0x69,0x6D,0x7D,0xAF,0x42, + 0x03,0xDB,0x37,0x18,0x65,0x46,0xE5,0x55,0x5B,0x1C,0x40,0x1C,0xCC,0x78,0x84,0x42, + 0xE9,0xDA,0x52,0x1C,0x88,0x78,0x90,0x42,0xE3,0xDA,0xFF,0x24,0x22,0x46,0xFF,0x2B, + 0x00,0xDA,0x1A,0x46,0x00,0x98,0xC3,0x00,0x09,0x98,0x18,0x18,0xC2,0x73,0x02,0x7B, + 0x00,0x9B,0x92,0x07,0x92,0x0F,0x9B,0x00,0x1A,0x43,0x02,0x23,0x1A,0x43,0x02,0x73, + 0x84,0x73,0x62,0x46,0x42,0x73,0x08,0x30,0x04,0x22,0xFE,0xF7,0xC5,0xFA,0x00,0x98, + 0x40,0x1C,0x00,0x90,0x01,0x98,0x40,0x1C,0x01,0x90,0x04,0x28,0xB2,0xDB,0x03,0xF0, + 0xA5,0xFC,0x00,0x9C,0x06,0x90,0x64,0x1E,0x6F,0xE0,0x04,0x9D,0x6B,0xE0,0x0E,0x2C, + 0x6B,0xDA,0x04,0x99,0x05,0x98,0x48,0x43,0x40,0x19,0x08,0x99,0x42,0x00,0x8A,0x5E, + 0x07,0x99,0x49,0x7D,0x8A,0x42,0x5E,0xDB,0x31,0x5C,0x0F,0x29,0x5B,0xD3,0x06,0x9A, + 0x05,0x99,0x11,0x70,0x06,0x99,0x6A,0x46,0x4D,0x70,0x06,0x99,0x64,0x1C,0x09,0x88, + 0x91,0x81,0x06,0x99,0x09,0x88,0xD1,0x81,0xE1,0xB2,0x0A,0x91,0x0B,0x91,0x31,0x54, + 0x07,0x98,0x03,0xA9,0x42,0x7D,0x10,0x9B,0x68,0x46,0x0E,0xC0,0x62,0xB2,0x30,0x46, + 0x06,0x9B,0x0D,0x99,0xFF,0xF7,0xF6,0xFE,0x07,0x46,0x07,0x98,0x03,0xA9,0x03,0x7D, + 0x82,0x7D,0x02,0x93,0x01,0x92,0x00,0x96,0xFF,0x23,0x0B,0x9A,0x0D,0x98,0xFF,0xF7, + 0x81,0xFA,0x01,0x46,0x07,0x98,0x42,0x7F,0x8A,0x42,0x1A,0xDB,0x68,0x46,0x00,0x7B, + 0x11,0xE0,0x69,0x46,0x4A,0x7B,0x04,0x9B,0x01,0x46,0x59,0x43,0x06,0xE0,0xB7,0x18, + 0xCB,0x5D,0xA3,0x42,0x01,0xD1,0x1F,0x23,0xCB,0x55,0x52,0x1C,0x6B,0x46,0xDB,0x7B, + 0x93,0x42,0xF4,0xDA,0x40,0x1C,0x69,0x46,0x89,0x7B,0x81,0x42,0xE9,0xDA,0x64,0x1E, + 0x11,0xE0,0x09,0x98,0xE2,0x00,0x10,0x18,0xC7,0x73,0x02,0x7B,0x92,0x07,0x92,0x0F, + 0xA3,0x00,0x1A,0x43,0x02,0x73,0x81,0x73,0x03,0x99,0x81,0x60,0x01,0x21,0x0A,0x43, + 0x02,0x73,0x0A,0x99,0x41,0x73,0x6D,0x1E,0x91,0xD5,0x05,0x98,0x40,0x1E,0x05,0x90, + 0x8B,0xD5,0x09,0x98,0x64,0x1C,0x04,0x80,0x03,0xF0,0x3E,0xFC,0x13,0xE7,0x00,0x00, + 0x10,0x48,0x11,0x49,0x10,0xB5,0x40,0x1A,0x1B,0xD0,0x00,0xF0,0xC9,0xFA,0x09,0x24, + 0x01,0x22,0x0B,0x21,0x24,0x03,0x12,0x03,0x09,0x03,0x20,0x46,0x01,0xF0,0x0A,0xF8, + 0x55,0x21,0x0A,0x4A,0x00,0x20,0x08,0xCC,0x40,0x1C,0x59,0x18,0x80,0xB2,0x90,0x42, + 0xF9,0xD3,0x20,0x68,0x88,0x42,0x04,0xD0,0x01,0x21,0x04,0x20,0x00,0xF0,0x88,0xFF, + 0xFE,0xE7,0x10,0xBD,0x10,0x90,0x00,0x00,0x00,0x90,0x00,0x00,0xFF,0x03,0x00,0x00, + 0x10,0xB5,0x04,0x48,0x80,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x88,0x70, + 0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0x02,0x48,0x41,0x88,0x11,0x22,0x11,0x43, + 0x41,0x80,0x70,0x47,0x00,0x10,0x00,0x40,0x10,0xB5,0x04,0x48,0x40,0x69,0x80,0x47, + 0x02,0x49,0x01,0x20,0x08,0x39,0x48,0x71,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20, + 0xF8,0xB5,0x0D,0x46,0x00,0x26,0x02,0x09,0x38,0x49,0x0F,0x2A,0x28,0xD0,0x58,0x28, + 0x6A,0xD8,0x37,0x4A,0x10,0x5C,0xFF,0x28,0x66,0xD0,0x02,0x07,0x06,0x09,0x12,0x0F, + 0xF0,0x00,0x47,0x18,0x01,0x20,0x90,0x40,0xC4,0xB2,0x38,0x46,0x00,0xF0,0x26,0xFF, + 0x01,0x78,0xA1,0x43,0x01,0x70,0x8C,0x46,0x41,0x78,0xA1,0x43,0x41,0x70,0x82,0x78, + 0xA2,0x43,0x82,0x70,0xC3,0x78,0xA3,0x43,0xC3,0x70,0x04,0x2D,0x0D,0xD0,0x0C,0x2D, + 0x0E,0xD0,0x08,0x2D,0x10,0xD0,0x02,0x2D,0x12,0xD0,0x01,0x2D,0x13,0xD0,0x14,0xE0, + 0x00,0x07,0xFF,0x24,0x40,0x0E,0x47,0x18,0xDF,0xE7,0x21,0x43,0x41,0x70,0x0C,0xE0, + 0x62,0x46,0x22,0x43,0x02,0x70,0xF8,0xE7,0x61,0x46,0x21,0x43,0x01,0x70,0x04,0xE0, + 0x22,0x43,0x82,0x70,0x01,0xE0,0x23,0x43,0xC3,0x70,0x1A,0x49,0x8A,0x5D,0x00,0x2A, + 0x22,0xD0,0x00,0x22,0x17,0x49,0x89,0x5D,0xD1,0x40,0xC9,0x07,0x18,0xD0,0x01,0x21, + 0x91,0x40,0x14,0x4D,0xCB,0xB2,0x00,0x21,0xF4,0x00,0x08,0x35,0x64,0x19,0xA4,0x46, + 0x64,0x46,0xA5,0x5C,0x08,0x24,0xCC,0x40,0x25,0x42,0x02,0xD0,0x44,0x5C,0x1C,0x43, + 0x01,0xE0,0x44,0x5C,0x9C,0x43,0x44,0x54,0x49,0x1C,0xC9,0xB2,0x04,0x29,0xEF,0xD3, + 0x52,0x1C,0xD2,0xB2,0x08,0x2A,0xDD,0xD3,0x01,0x78,0x39,0x70,0x41,0x78,0x79,0x70, + 0x81,0x78,0xB9,0x70,0xC0,0x78,0xF8,0x70,0xF8,0xBD,0x00,0x00,0x40,0x03,0x00,0x40, + 0xBA,0x6D,0x00,0x00,0xFC,0x20,0x00,0x20,0x58,0x28,0x01,0xD9,0xFF,0x20,0x70,0x47, + 0x0B,0x49,0x08,0x5C,0xFF,0x28,0xFA,0xD0,0x01,0x09,0x00,0x07,0xC9,0x00,0x00,0x0F, + 0x08,0x18,0x1E,0x28,0x05,0xD2,0x09,0x28,0x01,0xD2,0x0C,0x30,0x06,0xE0,0x09,0x38, + 0x04,0xE0,0x35,0x28,0x01,0xD2,0x0B,0x38,0x00,0xE0,0x20,0x38,0xC0,0xB2,0x70,0x47, + 0xBA,0x6D,0x00,0x00,0x70,0xB5,0x40,0x07,0x0D,0x4C,0x40,0x0F,0x24,0x5C,0x48,0x07, + 0x0B,0x49,0x40,0x0F,0x08,0x31,0x0D,0x5C,0x04,0x9E,0x00,0x2B,0x0E,0xD0,0x08,0x46, + 0x0A,0x21,0x4C,0x43,0x06,0x49,0x10,0x38,0x80,0x5C,0x09,0x1F,0xC9,0x5C,0x70,0x43, + 0x60,0x43,0x69,0x43,0xFE,0xF7,0x16,0xF9,0x80,0xB2,0x70,0xBD,0x00,0x20,0x70,0xBD, + 0x52,0x6E,0x00,0x00,0xF0,0xB5,0x0D,0x46,0x41,0x06,0xCC,0x0F,0x59,0x08,0x01,0x27, + 0x85,0xB0,0xFF,0x03,0xCF,0x19,0x03,0x91,0x0A,0x99,0x9C,0x46,0x49,0x00,0x02,0x91, + 0x81,0x06,0x89,0x0E,0x8E,0x46,0x89,0x1C,0x01,0x91,0x71,0x46,0x4B,0x1C,0x49,0x1E, + 0x8E,0x46,0x86,0x06,0x69,0x1E,0xB6,0x0E,0x00,0x91,0x97,0x42,0x29,0xD2,0x60,0x46, + 0x17,0x1A,0x01,0x20,0xC0,0x03,0x39,0x1A,0x00,0x29,0x02,0xDC,0x61,0x46,0x89,0x1A, + 0x09,0x18,0x88,0xB2,0x00,0x2C,0x29,0xD0,0x00,0x2E,0x07,0xD0,0x70,0x46,0x03,0xE0, + 0x0A,0x99,0xFE,0xF7,0xDF,0xF8,0x80,0x19,0xC3,0xB2,0x01,0xE0,0x00,0x24,0x27,0xE0, + 0x3F,0x2B,0x26,0xD9,0x3F,0x23,0x24,0xE0,0xA0,0x01,0x18,0x43,0x80,0x21,0x08,0x43, + 0x05,0xB0,0xF0,0xBD,0x00,0x99,0xA0,0x01,0x08,0x43,0x80,0x21,0x08,0x43,0xC0,0xB2, + 0xF6,0xE7,0x01,0x27,0x03,0x99,0xFF,0x03,0x79,0x1A,0x91,0x42,0xF0,0xD9,0xB8,0x1A, + 0x00,0x28,0x00,0xDC,0xD0,0x1B,0x80,0xB2,0x00,0x2C,0x06,0xD0,0x02,0x99,0x81,0x42, + 0xDE,0xD2,0x01,0x99,0xA9,0x42,0xDB,0xD2,0xD2,0xE7,0x00,0x2E,0xCE,0xD1,0x01,0x24, + 0x01,0x23,0xAB,0x42,0xDE,0xD2,0xD7,0xE7,0xFF,0xB5,0x07,0x46,0x83,0xB0,0x44,0x49, + 0x04,0x20,0x04,0xF0,0x99,0xF8,0x43,0x4C,0x01,0x25,0x25,0x80,0x42,0x48,0x61,0x21, + 0x01,0x72,0x60,0x21,0x41,0x72,0x08,0x20,0x00,0xF0,0xAE,0xF8,0x65,0x80,0x3F,0x48, + 0x0F,0x21,0x81,0x70,0x38,0x21,0x01,0x70,0x07,0x21,0xC1,0x70,0xFF,0x20,0xF1,0x30, + 0xE0,0x80,0x11,0x20,0x00,0x02,0x20,0x81,0x10,0x20,0xA0,0x80,0x00,0x24,0x61,0xE0, + 0x04,0x98,0x36,0x4A,0x00,0x5D,0x20,0x32,0x41,0x00,0x89,0x18,0x33,0x4A,0x00,0x91, + 0xC1,0x08,0x08,0x32,0x8A,0x18,0x31,0x49,0x01,0x92,0x60,0x39,0x46,0x18,0x40,0x07, + 0x40,0x0F,0x2E,0x4A,0x07,0x21,0xD1,0x70,0x80,0x21,0x31,0x70,0x01,0x21,0x01,0x9A, + 0x81,0x40,0x11,0x70,0x38,0x5D,0x00,0x21,0x00,0x9A,0x04,0xF0,0xFB,0xF9,0x05,0x46, + 0x38,0x5D,0x80,0x21,0x00,0x9A,0x04,0xF0,0xF5,0xF9,0x25,0x49,0x42,0x1B,0x52,0x18, + 0x49,0x00,0x8A,0x42,0x1A,0xD9,0x21,0x48,0x77,0x21,0xC1,0x70,0xF0,0x20,0x30,0x70, + 0x38,0x5D,0x80,0x21,0x00,0x9A,0x04,0xF0,0xE5,0xF9,0x01,0x21,0xC9,0x03,0x41,0x1A, + 0x8A,0x00,0x89,0x18,0x40,0x1A,0x80,0xB2,0x19,0x49,0x42,0x1B,0x52,0x18,0x49,0x00, + 0x8A,0x42,0x03,0xD8,0x16,0x48,0x40,0x42,0x28,0x18,0x80,0xB2,0x00,0x21,0x31,0x70, + 0x01,0x9A,0x11,0x70,0x41,0x1B,0x00,0x29,0x00,0xDC,0x29,0x1A,0x89,0xB2,0xB4,0x29, + 0x00,0xD2,0x01,0x21,0x06,0x98,0x00,0x28,0x06,0xD0,0x0E,0x48,0x49,0x1C,0xFE,0xF7, + 0x31,0xF8,0x06,0x99,0x62,0x00,0x88,0x52,0x00,0x21,0x01,0x20,0x00,0xF0,0xC0,0xFD, + 0x64,0x1C,0xE4,0xB2,0x05,0x98,0x84,0x42,0x9A,0xD3,0x07,0xB0,0xF0,0xBD,0x00,0x00, + 0xC9,0x1C,0x00,0x00,0x00,0x10,0x00,0x40,0x00,0x03,0x00,0x40,0x60,0x12,0x00,0x40, + 0xAC,0x0D,0x00,0x00,0x50,0x34,0x03,0x00,0xFF,0xB5,0x07,0x46,0x10,0x4C,0x81,0xB0, + 0x11,0x20,0x1D,0x46,0x16,0x46,0x60,0x80,0x04,0x20,0xFF,0xF7,0x65,0xFC,0x0D,0x49, + 0xB8,0x02,0x40,0x18,0x02,0x99,0x09,0x01,0x08,0x43,0x00,0x2E,0x01,0xD1,0x08,0x21, + 0x08,0x43,0x20,0x80,0x00,0x2D,0x06,0xD0,0x01,0x2D,0x06,0xD0,0x00,0x22,0x20,0x21, + 0x04,0x20,0x04,0xF0,0x43,0xFE,0x05,0xB0,0xF0,0xBD,0x00,0x22,0x21,0x21,0xF7,0xE7, + 0x00,0x10,0x00,0x40,0x43,0x03,0x00,0x00,0x70,0xB5,0x00,0x24,0x06,0x46,0xF0,0x25, + 0x20,0x46,0x28,0x43,0x31,0x46,0xFF,0xF7,0x1B,0xFE,0x64,0x1C,0xE4,0xB2,0x08,0x2C, + 0xF6,0xD3,0x70,0xBD,0xF0,0xB5,0x45,0x4E,0x89,0xB0,0x30,0x89,0x44,0x4F,0xC0,0xB2, + 0x08,0x90,0x30,0x68,0x07,0x90,0x3D,0x79,0x0C,0x46,0x00,0x20,0xB0,0x74,0x01,0x46, + 0xC8,0x20,0x01,0xF0,0x43,0xF9,0x00,0x20,0x38,0x71,0x02,0x46,0x01,0x46,0x3C,0x48, + 0x10,0x30,0x00,0xF0,0xA9,0xFD,0x06,0x90,0x39,0x48,0xFF,0x22,0x00,0x21,0x15,0x30, + 0x00,0xF0,0xA2,0xFD,0x05,0x90,0x36,0x48,0xFF,0x22,0x00,0x21,0x14,0x30,0x00,0xF0, + 0x9B,0xFD,0x04,0x90,0x32,0x48,0x00,0x22,0x11,0x46,0x13,0x30,0x00,0xF0,0x94,0xFD, + 0x03,0x90,0x2F,0x48,0x00,0x22,0x11,0x46,0x12,0x30,0x00,0xF0,0x8D,0xFD,0x02,0x90, + 0x2B,0x48,0x00,0x22,0x11,0x46,0x11,0x30,0x00,0xF0,0x86,0xFD,0x01,0x90,0x00,0xF0, + 0xC9,0xF8,0x00,0x2C,0x04,0xD0,0x00,0xF0,0x95,0xF9,0x01,0x20,0x00,0xF0,0x62,0xF9, + 0x0A,0x20,0xFF,0xF7,0xF1,0xFB,0xA0,0x27,0x01,0x22,0x22,0x21,0x0A,0x20,0x04,0xF0, + 0xDD,0xFD,0xB1,0x7C,0x00,0x29,0x30,0xD0,0x00,0x2C,0x02,0xD0,0x00,0x20,0x00,0xF0, + 0x51,0xF9,0x1B,0x48,0x05,0x71,0x1A,0x48,0x01,0x21,0x10,0x30,0x06,0x9A,0x00,0xF0, + 0x63,0xFD,0x17,0x48,0x01,0x21,0x15,0x30,0x05,0x9A,0x00,0xF0,0x5D,0xFD,0x14,0x48, + 0x01,0x21,0x14,0x30,0x04,0x9A,0x00,0xF0,0x57,0xFD,0x11,0x48,0x01,0x21,0x13,0x30, + 0x03,0x9A,0x00,0xF0,0x51,0xFD,0x0E,0x48,0x01,0x21,0x12,0x30,0x02,0x9A,0x00,0xF0, + 0x4B,0xFD,0x0B,0x48,0x01,0x21,0x11,0x30,0x01,0x9A,0x00,0xF0,0x45,0xFD,0x07,0x99, + 0x08,0x98,0x01,0xF0,0xD3,0xF8,0x09,0xB0,0xF0,0xBD,0x80,0x07,0x02,0xD5,0x01,0x20, + 0x00,0xF0,0x20,0xF9,0x03,0x48,0x87,0x80,0xBE,0xE7,0x00,0x00,0x68,0x20,0x00,0x20, + 0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0x0E,0xB5,0xB9,0x20,0x6B,0x46,0x18,0x72, + 0x01,0x22,0x01,0xA9,0x02,0xA8,0x13,0x46,0x00,0x92,0x00,0xF0,0x43,0xF8,0x0E,0xBD, + 0x70,0xB5,0x13,0x4D,0x00,0x20,0x68,0x82,0x07,0x21,0xE9,0x82,0x11,0x4C,0x20,0x80, + 0x33,0x20,0x60,0x80,0x10,0x49,0x01,0x20,0x03,0xF0,0x26,0xFF,0xBF,0x22,0x03,0x21, + 0x0E,0x48,0x00,0xF0,0x11,0xFD,0x0D,0x48,0xBF,0x22,0x03,0x21,0x80,0x1C,0x00,0xF0, + 0x0B,0xFD,0x0A,0x48,0xBF,0x22,0x03,0x21,0x40,0x1C,0x00,0xF0,0x05,0xFD,0xE0,0x8B, + 0x04,0x21,0x08,0x43,0xE0,0x83,0x24,0x20,0x68,0x82,0x03,0x20,0xE8,0x82,0x70,0xBD, + 0x00,0x20,0x00,0x40,0x20,0x11,0x00,0x40,0x4D,0x42,0x00,0x00,0x10,0x03,0x00,0x40, + 0x3E,0xB5,0x00,0x24,0xAB,0x25,0x6B,0x46,0x1D,0x72,0x01,0x22,0x01,0xA9,0x02,0xA8, + 0x13,0x46,0x00,0x92,0x00,0xF0,0x06,0xF8,0x64,0x1C,0xE4,0xB2,0x0A,0x2C,0xF2,0xD3, + 0x3E,0xBD,0x00,0x00,0x30,0xB5,0x0F,0x4D,0x03,0x9C,0xA8,0x62,0xE9,0x62,0x0D,0x48, + 0x40,0x21,0x20,0x30,0x01,0x80,0x82,0x80,0xC3,0x80,0x0B,0x48,0x24,0x21,0x41,0x82, + 0x03,0x21,0xC1,0x82,0x00,0x2C,0x01,0xD0,0x08,0x49,0x00,0xE0,0x08,0x49,0x41,0x82, + 0xC1,0x8A,0xC9,0x07,0xFC,0xD0,0x00,0x20,0x40,0x1C,0xC0,0xB2,0x13,0x28,0xFB,0xD3, + 0x30,0xBD,0x00,0x00,0x00,0x11,0x00,0x40,0x00,0x20,0x00,0x40,0x24,0x30,0x00,0x00, + 0x24,0x10,0x00,0x00,0x00,0xB5,0x00,0x22,0x01,0x21,0x11,0x48,0x00,0xF0,0xB4,0xFC, + 0x0F,0x48,0xFF,0x22,0x01,0x21,0x40,0x1D,0x00,0xF0,0xAE,0xFC,0x0C,0x48,0xFF,0x22, + 0x01,0x21,0x00,0x1D,0x00,0xF0,0xA8,0xFC,0x09,0x48,0x00,0x22,0x01,0x21,0xC0,0x1C, + 0x00,0xF0,0xA2,0xFC,0x06,0x48,0x00,0x22,0x01,0x21,0x80,0x1C,0x00,0xF0,0x9C,0xFC, + 0x03,0x48,0x00,0x22,0x01,0x21,0x40,0x1C,0x00,0xF0,0x96,0xFC,0x00,0xBD,0x00,0x00, + 0x10,0x03,0x00,0x40,0x10,0xB5,0x09,0x4C,0x44,0x21,0x60,0x68,0xFD,0xF7,0xFB,0xFE, + 0xA0,0x69,0xFF,0x22,0x41,0x79,0x60,0x68,0x11,0x30,0xFD,0xF7,0xED,0xFE,0x02,0xF0, + 0xB5,0xF8,0x60,0x61,0x61,0x68,0x00,0x78,0x08,0x74,0x10,0xBD,0x78,0x21,0x00,0x20, + 0xFF,0xB5,0x0D,0x46,0x81,0xB0,0x16,0x46,0x1F,0x46,0x29,0x49,0x02,0x20,0x03,0xF0, + 0x83,0xFE,0x01,0x24,0xA4,0x07,0xA0,0x89,0x00,0x07,0x00,0x0F,0xA0,0x81,0x00,0x2D, + 0x02,0xD1,0xA0,0x89,0xE0,0x21,0x05,0xE0,0xA0,0x89,0x02,0x2D,0x01,0xD1,0x10,0x21, + 0x00,0xE0,0x30,0x21,0x08,0x43,0xA0,0x81,0x1E,0x4D,0xC1,0x20,0x68,0x70,0x30,0x01, + 0x1D,0x49,0x38,0x43,0x88,0x83,0x00,0x22,0x30,0x46,0x0A,0x99,0x00,0xF0,0x94,0xF8, + 0x00,0x22,0x38,0x46,0x0A,0x99,0x00,0xF0,0x8F,0xF8,0x01,0x21,0x08,0x46,0xB0,0x40, + 0xB9,0x40,0x08,0x43,0x06,0x46,0xC2,0xB2,0x02,0x21,0x14,0x48,0x00,0xF0,0x44,0xFC, + 0x12,0x48,0xF2,0xB2,0x02,0x21,0x40,0x1E,0x00,0xF0,0x3E,0xFC,0x60,0x89,0x40,0x21, + 0x08,0x43,0x60,0x81,0x00,0x21,0x69,0x71,0x0B,0x98,0x28,0x70,0x01,0x98,0x00,0x28, + 0x03,0xD1,0x28,0x78,0x80,0x22,0x10,0x43,0x28,0x70,0x09,0x48,0x01,0x84,0x01,0x85, + 0x20,0x30,0xC1,0x71,0x0A,0x99,0x01,0x74,0x0C,0x99,0x41,0x74,0x05,0xB0,0xF0,0xBD, + 0x55,0x47,0x00,0x00,0x00,0x20,0x00,0x40,0x20,0x11,0x00,0x40,0x12,0x03,0x00,0x40, + 0xC8,0x20,0x00,0x20,0x03,0x49,0x00,0x28,0x01,0xD0,0x01,0x20,0x00,0xE0,0x10,0x20, + 0xC8,0x71,0x70,0x47,0x00,0x20,0x00,0x40,0xF0,0xB5,0x11,0x4C,0x06,0x9F,0x08,0x9E, + 0x09,0x9D,0x0F,0xC4,0x10,0x3C,0x20,0x46,0xC6,0x61,0x07,0x99,0x47,0x61,0x81,0x61, + 0x05,0x99,0x01,0x61,0x65,0x84,0x0A,0x98,0x00,0x22,0x28,0x18,0xA0,0x84,0x0C,0x99, + 0xE1,0x62,0x07,0x48,0x0B,0x9C,0x01,0x23,0x20,0x30,0x00,0x2C,0x03,0xD0,0x82,0x72, + 0xC3,0x72,0x0A,0x70,0xF0,0xBD,0x83,0x72,0xC2,0x72,0x0B,0x70,0xF0,0xBD,0x00,0x00, + 0xC8,0x20,0x00,0x20,0x70,0xB5,0x11,0x48,0x81,0x8B,0x80,0x8B,0x09,0x05,0x0D,0x0E, + 0x06,0x07,0x0F,0x4C,0x36,0x0F,0x21,0x7C,0x00,0x22,0x28,0x46,0x00,0xF0,0x1C,0xF8, + 0x21,0x7C,0x00,0x22,0x30,0x46,0x00,0xF0,0x17,0xF8,0x01,0x20,0x04,0x46,0xAC,0x40, + 0xB0,0x40,0x04,0x43,0xE2,0xB2,0x02,0x21,0x06,0x48,0x00,0xF0,0xCD,0xFB,0x05,0x48, + 0xE2,0xB2,0x02,0x21,0x40,0x1E,0x00,0xF0,0xC7,0xFB,0x70,0xBD,0x20,0x11,0x00,0x40, + 0xE8,0x20,0x00,0x20,0x12,0x03,0x00,0x40,0xF7,0xB5,0x07,0x46,0x01,0x20,0xB8,0x40, + 0x81,0xB0,0xC0,0xB2,0x00,0x90,0x02,0x98,0x01,0x21,0x05,0x07,0x06,0x09,0x2D,0x0F, + 0xEA,0x07,0xB9,0x40,0xC9,0xB2,0x24,0x48,0xCC,0x43,0x00,0x2A,0x02,0xD0,0x02,0x21, + 0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0xA6,0xFB,0x1F,0x48,0xA9,0x07, + 0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0x9C,0xFB, + 0x68,0x07,0x04,0xD5,0x18,0x48,0x02,0x21,0x40,0x1C,0x00,0x9A,0x03,0xE0,0x17,0x48, + 0xE2,0xB2,0x03,0x21,0x00,0x1D,0x00,0xF0,0x8F,0xFB,0x15,0x48,0xF1,0x07,0x02,0xD0, + 0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0x85,0xFB,0x11,0x48, + 0xB1,0x07,0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0, + 0x7B,0xFB,0x0D,0x48,0x71,0x07,0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2, + 0x03,0x21,0x00,0xF0,0x71,0xFB,0x03,0x98,0x00,0x28,0x03,0xD0,0x07,0x48,0x07,0x73, + 0x02,0x99,0x41,0x73,0xFF,0xBD,0x00,0x00,0x10,0x03,0x00,0x40,0x12,0x03,0x00,0x40, + 0x13,0x03,0x00,0x40,0x14,0x03,0x00,0x40,0x15,0x03,0x00,0x40,0x68,0x20,0x00,0x20, + 0xFF,0xB5,0x3A,0x4D,0x94,0x46,0x6F,0x68,0x4A,0x1E,0xF8,0x78,0x81,0xB0,0x90,0x42, + 0x01,0xDD,0x01,0x20,0x01,0xE0,0x08,0x1A,0xC0,0xB2,0x35,0x4C,0x01,0x22,0x22,0x80, + 0xAC,0x68,0x34,0x4E,0x62,0x78,0x92,0x01,0x18,0x32,0x32,0x70,0x00,0x2B,0x08,0xD0, + 0x31,0x4A,0x13,0x88,0x31,0x4A,0x93,0x42,0x03,0xD1,0x33,0x78,0x01,0x22,0x13,0x43, + 0x33,0x70,0xA2,0x78,0x00,0x2A,0x06,0xD0,0x33,0x78,0xF7,0x22,0x13,0x40,0x33,0x70, + 0x00,0x23,0x73,0x70,0x01,0xE0,0x10,0x22,0x72,0x70,0x0B,0x02,0x79,0x78,0x0B,0x43, + 0x23,0x49,0xCB,0x80,0x3A,0x78,0x12,0x03,0x02,0x43,0x0A,0x81,0xE0,0x78,0x22,0x79, + 0x00,0x01,0x10,0x43,0xF0,0x70,0x60,0x79,0x00,0x01,0x40,0x1C,0xB0,0x70,0x01,0x98, + 0x88,0x80,0x20,0x7A,0x43,0x21,0x00,0x01,0x08,0x43,0x1D,0x49,0x08,0x72,0xA0,0x79, + 0xE2,0x79,0x00,0x01,0x10,0x43,0x48,0x72,0x60,0x46,0xFF,0xF7,0x3D,0xFD,0xE8,0x68, + 0x01,0x78,0x40,0x68,0x00,0xF0,0x9E,0xFB,0xE8,0x68,0x01,0x78,0xC0,0x68,0x00,0xF0, + 0x75,0xFB,0x01,0x98,0x00,0x90,0x68,0x68,0x43,0x79,0x02,0x79,0xA8,0x68,0x01,0x79, + 0xC0,0x78,0xFF,0xF7,0xE7,0xFB,0xA8,0x83,0x00,0x28,0x02,0xD1,0xFF,0x20,0x2D,0x30, + 0xA8,0x83,0x80,0xB2,0x41,0x08,0x68,0x84,0x41,0x18,0x29,0x84,0x7D,0x21,0xC9,0x00, + 0x40,0x18,0x80,0xB2,0xA8,0x83,0x05,0xB0,0xF0,0xBD,0x00,0x00,0x44,0x21,0x00,0x20, + 0x00,0x10,0x00,0x40,0x60,0x12,0x00,0x40,0xB8,0x6D,0x00,0x00,0xAC,0xCA,0x00,0x00, + 0x00,0x03,0x00,0x40,0x70,0xB5,0x11,0x4C,0x05,0x46,0xE0,0x68,0x41,0x78,0x02,0x78, + 0x01,0x20,0xE0,0x77,0x00,0x20,0x20,0x70,0x60,0x70,0xA0,0x70,0xE0,0x70,0x00,0x29, + 0x00,0xD1,0x01,0x21,0x51,0x43,0x49,0x00,0x60,0x69,0xFD,0xF7,0x34,0xFD,0x04,0x20, + 0x01,0x07,0x48,0x80,0x01,0x21,0x00,0x22,0x08,0x46,0x00,0xF0,0x09,0xFE,0x00,0x2D, + 0x02,0xD0,0x20,0x78,0x00,0x28,0xFC,0xD0,0x70,0xBD,0x00,0x00,0x44,0x21,0x00,0x20, + 0xF0,0xB5,0x05,0xAC,0xE0,0xCC,0x04,0x4C,0xA5,0x61,0x63,0x61,0x62,0x60,0xA1,0x60, + 0xE0,0x60,0xA7,0x77,0x26,0x61,0xF0,0xBD,0x44,0x21,0x00,0x20,0xF0,0xB5,0x6D,0x48, + 0x9D,0xB0,0x41,0x88,0x11,0x22,0x11,0x43,0x41,0x80,0x6B,0x48,0xC1,0x7F,0x00,0x29, + 0x7E,0xD0,0x01,0x46,0x04,0x46,0xE0,0x68,0x28,0x31,0x4E,0x78,0x42,0x78,0x17,0x92, + 0x05,0x78,0x60,0x78,0x62,0x69,0x68,0x43,0x40,0x00,0x10,0x18,0x1C,0x90,0x89,0x68, + 0xA0,0x78,0x32,0x46,0x70,0x43,0x09,0x18,0x19,0xA8,0xFD,0xF7,0xCD,0xFC,0xE0,0x68, + 0x2A,0x46,0x40,0x68,0x01,0xA9,0x00,0xF0,0x2B,0xFB,0x20,0x34,0x60,0x79,0x21,0x79, + 0x88,0x42,0x35,0xD2,0x00,0x20,0x1B,0x90,0x57,0x48,0xC1,0x78,0xC2,0x68,0x80,0x69, + 0x12,0x78,0x51,0x43,0x08,0x18,0x00,0x27,0x18,0x90,0x16,0xE0,0x52,0x48,0x01,0xAA, + 0x41,0x8C,0x00,0x91,0x03,0x8C,0x79,0x00,0x40,0x68,0x52,0x5A,0x41,0x78,0x18,0x98, + 0xC0,0x5D,0xFF,0xF7,0x6F,0xFB,0x18,0x99,0xC9,0x5D,0x81,0x42,0x03,0xD0,0x18,0x99, + 0xC8,0x55,0x01,0x20,0x1B,0x90,0x7F,0x1C,0xFF,0xB2,0xAF,0x42,0xE6,0xD3,0x60,0x79, + 0x40,0x1C,0xC0,0xB2,0x60,0x71,0x1B,0x99,0x00,0x29,0x04,0xD0,0x21,0x79,0x88,0x42, + 0x01,0xD2,0x00,0x22,0x5C,0xE0,0x00,0x21,0x01,0x22,0x08,0x46,0x00,0xF0,0x90,0xFD, + 0x00,0x20,0x60,0x71,0x3C,0x48,0x29,0x46,0x28,0x30,0x03,0x78,0x28,0x38,0x82,0x8B, + 0x01,0xA8,0x00,0xF0,0x49,0xFD,0x01,0xAB,0x9C,0x46,0x33,0x02,0x2B,0x43,0x9E,0x46, + 0x11,0x23,0x36,0x48,0x00,0x93,0x1C,0x99,0x83,0x88,0x19,0xAA,0x10,0x27,0x3B,0x43, + 0x83,0x80,0xC2,0x80,0x63,0x46,0x03,0x81,0x41,0x81,0x81,0x81,0x73,0x46,0x43,0x80, + 0x00,0x9B,0x03,0x80,0x81,0x88,0xC9,0x06,0xFC,0xD5,0x2B,0x4F,0xF8,0x78,0x00,0xE0, + 0x2B,0xE0,0x40,0x1C,0xF8,0x70,0xB8,0x78,0x40,0x1C,0xB8,0x70,0xB8,0x78,0xB0,0x42, + 0x04,0xD3,0x00,0x20,0xB8,0x70,0x78,0x78,0x80,0x19,0x78,0x70,0x79,0x78,0x17,0x98, + 0x81,0x42,0x20,0xD2,0x78,0x78,0x81,0x19,0x17,0x98,0x81,0x42,0x0D,0xD9,0x80,0x1B, + 0x78,0x70,0x78,0x78,0x79,0x69,0x68,0x43,0x40,0x00,0x7A,0x78,0x08,0x18,0x17,0x99, + 0x89,0x1A,0x69,0x43,0x49,0x00,0xFD,0xF7,0x66,0xFC,0xF8,0x78,0x01,0x28,0x06,0xD0, + 0x01,0x22,0x11,0x46,0x00,0x20,0x00,0xF0,0x3B,0xFD,0x1D,0xB0,0xF0,0xBD,0x01,0x22, + 0x01,0x21,0x08,0x46,0xF7,0xE7,0x20,0x79,0x00,0x28,0x18,0xD1,0x04,0x20,0x04,0x07, + 0x60,0x80,0x08,0x20,0xFF,0xF7,0x10,0xFC,0xF8,0x68,0x01,0x78,0x40,0x68,0x00,0xF0, + 0x5B,0xFA,0x0C,0x20,0x60,0x80,0x0A,0x49,0x40,0x20,0x08,0x72,0x09,0x48,0x00,0x21, + 0x01,0x71,0xC2,0x78,0x52,0x06,0x52,0x0E,0xC2,0x70,0x81,0x70,0x61,0x80,0x01,0x20, + 0x38,0x70,0xDA,0xE7,0x00,0x10,0x00,0x40,0x44,0x21,0x00,0x20,0x00,0x11,0x00,0x40, + 0x00,0x03,0x00,0x40,0x60,0x12,0x00,0x40,0xF1,0xB5,0x1B,0x49,0x04,0x20,0x03,0xF0, + 0xCB,0xFB,0x1A,0x48,0x81,0x7F,0x00,0x29,0x2A,0xD0,0x04,0x46,0x00,0x21,0x20,0x34, + 0x61,0x71,0x81,0x68,0x89,0x7A,0x21,0x71,0x01,0x46,0xC5,0x68,0x28,0x31,0x4E,0x78, + 0x6F,0x78,0x31,0x46,0x38,0x46,0xFD,0xF7,0xC5,0xFB,0x00,0x29,0x06,0xD0,0x70,0x1A, + 0xC0,0x19,0x0E,0x4E,0x00,0x06,0x00,0x0E,0x02,0xD0,0x02,0xE0,0x00,0x20,0xF7,0xE7, + 0x01,0x20,0x29,0x78,0x80,0x22,0x41,0x43,0xB0,0x69,0xFD,0xF7,0xFD,0xFB,0x00,0xF0, + 0x55,0xF8,0x01,0x20,0xFF,0xF7,0xB6,0xFE,0x00,0x20,0x60,0x71,0x20,0x71,0xB0,0x77, + 0x00,0x98,0xFF,0xF7,0xAF,0xFE,0xF8,0xBD,0xFD,0x26,0x00,0x00,0x44,0x21,0x00,0x20, + 0x0D,0x49,0x42,0x08,0x48,0x70,0x0A,0x70,0x04,0x2A,0x01,0xD1,0x03,0x22,0x0A,0x70, + 0x04,0x28,0x06,0xD0,0x08,0x28,0x09,0xD0,0x08,0x48,0x48,0x60,0x40,0x1C,0x88,0x60, + 0x70,0x47,0x06,0x48,0x82,0x30,0x48,0x60,0x10,0x30,0xF8,0xE7,0x03,0x48,0x80,0x1C, + 0x48,0x60,0x40,0x30,0xF3,0xE7,0x00,0x00,0x6C,0x21,0x00,0x20,0x62,0x6E,0x00,0x00, + 0xF8,0xB5,0x10,0x4F,0x04,0x46,0x38,0x46,0x00,0xF0,0xF0,0xF8,0x0E,0x4A,0xD1,0x68, + 0x49,0x78,0x00,0x29,0x15,0xD0,0x00,0x21,0x13,0x69,0xE6,0x00,0x72,0x18,0x54,0x00, + 0x1D,0x5D,0x8A,0x00,0x85,0x54,0x64,0x1C,0x1D,0x5D,0x14,0x18,0x65,0x70,0x85,0x5C, + 0xCA,0x00,0xD2,0x19,0x15,0x70,0x64,0x78,0x54,0x70,0x49,0x1C,0xC9,0xB2,0x08,0x29, + 0xEC,0xD3,0xF8,0xBD,0x40,0x03,0x00,0x40,0x44,0x21,0x00,0x20,0xF0,0xB5,0x3C,0x48, + 0x85,0xB0,0x44,0x78,0x28,0x38,0xC0,0x68,0x00,0x26,0x40,0x78,0x01,0x96,0x00,0x90, + 0x69,0xE0,0x31,0x19,0x81,0x42,0x01,0xD9,0x00,0x1B,0xC6,0xB2,0x00,0x27,0x5E,0xE0, + 0x33,0x48,0x41,0x68,0x20,0x46,0x78,0x43,0x08,0x18,0x00,0x25,0x02,0x90,0x19,0xE0, + 0x02,0x98,0x40,0x57,0x01,0x28,0x02,0xD0,0x40,0x1C,0x08,0xD0,0x10,0xE0,0x2C,0x48, + 0x28,0x38,0xC0,0x68,0x01,0x69,0x70,0x19,0x08,0x5C,0x04,0x21,0x06,0xE0,0x28,0x48, + 0x28,0x38,0xC0,0x68,0x01,0x69,0x70,0x19,0x08,0x5C,0x0C,0x21,0xFF,0xF7,0x60,0xF9, + 0x6D,0x1C,0xED,0xB2,0xA5,0x42,0xE3,0xD3,0x01,0x98,0x00,0x25,0xC0,0x00,0x04,0x90, + 0xE8,0x00,0x20,0x49,0x03,0x90,0x40,0x18,0x00,0x22,0x11,0x46,0x00,0xF0,0xFC,0xF8, + 0x1B,0x49,0x28,0x39,0x0A,0x69,0x04,0x99,0x49,0x19,0x49,0x00,0x02,0x91,0x50,0x54, + 0x18,0x49,0x03,0x98,0x49,0x1C,0x40,0x18,0x00,0x22,0x11,0x46,0x00,0xF0,0xEC,0xF8, + 0x13,0x49,0x6D,0x1C,0x28,0x39,0x0A,0x69,0x02,0x99,0xED,0xB2,0x49,0x1C,0x50,0x54, + 0x08,0x2D,0xDD,0xD3,0x00,0x25,0x0A,0xE0,0x0D,0x48,0x28,0x38,0xC0,0x68,0x01,0x69, + 0x70,0x19,0x08,0x5C,0x08,0x21,0xFF,0xF7,0x2B,0xF9,0x6D,0x1C,0xED,0xB2,0xA5,0x42, + 0xF2,0xD3,0x01,0x98,0x40,0x1C,0xC0,0xB2,0x7F,0x1C,0xFF,0xB2,0x01,0x90,0xA7,0x42, + 0x9E,0xD3,0x30,0x19,0xC6,0xB2,0x00,0x98,0x86,0x42,0x92,0xD3,0x05,0xB0,0xF0,0xBD, + 0x6C,0x21,0x00,0x20,0x40,0x03,0x00,0x40,0x02,0x48,0x01,0x78,0x00,0x29,0xFC,0xD0, + 0x70,0x47,0x00,0x00,0x44,0x21,0x00,0x20,0x03,0x46,0xF0,0xB5,0x00,0x20,0x84,0x46, + 0x17,0x48,0x06,0x22,0x44,0x7E,0x01,0x46,0x13,0x31,0x63,0x54,0x00,0x24,0x00,0x25, + 0x29,0x46,0x14,0x4F,0x0E,0xE0,0x63,0x18,0xDB,0xB2,0x93,0x42,0x01,0xD3,0x9B,0x1A, + 0xDB,0xB2,0x46,0x18,0xF6,0x7C,0xFB,0x5C,0x9E,0x42,0x05,0xD1,0x6D,0x1C,0x49,0x1C, + 0xED,0xB2,0xC9,0xB2,0x91,0x42,0xEE,0xD3,0x95,0x42,0x02,0xD1,0x01,0x21,0x8C,0x46, + 0x03,0xE0,0x64,0x1C,0xE4,0xB2,0x94,0x42,0xE1,0xD3,0x41,0x7E,0x52,0x1E,0x91,0x42, + 0x01,0xDA,0x49,0x1C,0x00,0xE0,0x00,0x21,0x41,0x76,0x60,0x46,0xF0,0xBD,0x00,0x00, + 0x68,0x20,0x00,0x20,0x44,0x6E,0x00,0x00,0x01,0x49,0x00,0x20,0x48,0x76,0x70,0x47, + 0x68,0x20,0x00,0x20,0x00,0x22,0x06,0xE0,0x00,0x21,0x49,0x1C,0x89,0xB2,0x42,0x29, + 0xFB,0xD3,0x52,0x1C,0x92,0xB2,0x82,0x42,0xF6,0xD3,0x70,0x47,0x0E,0x4A,0x00,0x21, + 0xC9,0x43,0x82,0x18,0x09,0x2A,0x01,0xD8,0x51,0xB2,0x0C,0xE0,0x0A,0x4A,0x30,0x3A, + 0x80,0x18,0x3B,0x28,0x07,0xD8,0xC0,0xB2,0xC1,0x08,0x40,0x07,0x89,0x00,0x40,0x0F, + 0x08,0x18,0x10,0x30,0x41,0xB2,0x48,0x1C,0x01,0xD0,0x40,0x29,0x01,0xD3,0x00,0x20, + 0x70,0x47,0x02,0x48,0x40,0x18,0x70,0x47,0xF0,0xFC,0xFF,0xBF,0x84,0x20,0x00,0x20, + 0xF0,0xB5,0x00,0x27,0x1C,0x4A,0x1D,0x4D,0xCC,0xB2,0x1D,0x4E,0x03,0x46,0xFD,0xF7, + 0x23,0xFB,0x0C,0x07,0x09,0x0B,0x19,0x1B,0x1D,0x1F,0x21,0x25,0x2B,0x2D,0x2F,0x31, + 0x51,0x81,0x27,0xE0,0x57,0x74,0x25,0xE0,0xE9,0x68,0xEA,0x68,0xE8,0x68,0x0B,0x46, + 0x91,0x42,0x00,0xD8,0x13,0x46,0x83,0x42,0x03,0xD9,0x08,0x46,0x91,0x42,0x00,0xD8, + 0x10,0x46,0xF0,0xBD,0x51,0x60,0x15,0xE0,0x94,0x73,0x13,0xE0,0xD4,0x73,0x11,0xE0, + 0xD0,0x7B,0xF0,0xBD,0x01,0x20,0x80,0x07,0x40,0x88,0xF0,0xBD,0x08,0x03,0x01,0x21, + 0xC9,0x03,0x08,0x43,0xF0,0x83,0x05,0xE0,0xF7,0x83,0x03,0xE0,0x50,0x7C,0xF0,0xBD, + 0xA0,0x20,0xA8,0x80,0x00,0x20,0xF0,0xBD,0x68,0x20,0x00,0x20,0x00,0x02,0x00,0x40, + 0x20,0x11,0x00,0x40,0x01,0x46,0x08,0x78,0x0A,0x78,0x0B,0x78,0x90,0x42,0xFA,0xD1, + 0x98,0x42,0xF8,0xD1,0x70,0x47,0x00,0x00,0x30,0xB5,0x03,0x46,0x0C,0x46,0x15,0x46, + 0xFF,0xF7,0x8C,0xFF,0x00,0x28,0x06,0xD0,0x0D,0x49,0x40,0x1A,0x40,0xB2,0x42,0x1C, + 0x01,0xD0,0x40,0x28,0x01,0xD3,0x00,0x20,0x30,0xBD,0x01,0x2C,0x01,0xD1,0x0D,0x54, + 0x09,0xE0,0x02,0x2C,0x02,0xD1,0x0A,0x5C,0x2A,0x43,0x03,0xE0,0x03,0x2C,0x04,0xD1, + 0x0A,0x5C,0x2A,0x40,0x0A,0x54,0x0A,0x5C,0x1A,0x70,0x08,0x5C,0x30,0xBD,0x00,0x00, + 0x84,0x20,0x00,0x20,0xF0,0xB5,0x21,0x4B,0x06,0x46,0x9D,0x44,0x20,0x4B,0x3B,0x20, + 0x6B,0x44,0x18,0x71,0x00,0x20,0x18,0x72,0x0D,0x46,0x14,0x46,0x58,0x72,0xFF,0xF7, + 0xD7,0xFA,0x2A,0xE0,0x01,0x27,0xBF,0x02,0xBC,0x42,0x00,0xD8,0x27,0x46,0x18,0x4B, + 0x28,0x0C,0x6B,0x44,0x58,0x71,0x28,0x0A,0x98,0x71,0xDD,0x71,0x00,0x22,0x15,0x48, + 0x00,0x92,0x7B,0x08,0x06,0x22,0x01,0xA9,0x68,0x44,0xFF,0xF7,0xD3,0xFA,0x12,0x49, + 0x48,0x07,0xC1,0x80,0x00,0x20,0x01,0xA9,0x82,0x00,0x8A,0x58,0x40,0x1C,0x04,0xC6, + 0x80,0xB2,0xFF,0x28,0xF8,0xD9,0x00,0x20,0x01,0x21,0x89,0x07,0xC8,0x80,0xED,0x19, + 0x08,0x15,0x84,0x42,0x03,0xD9,0x20,0x1A,0x84,0xB2,0x00,0x2C,0xD2,0xD1,0xFF,0xF7, + 0x6B,0xFA,0x04,0x4B,0x08,0x33,0x9D,0x44,0xF0,0xBD,0x00,0x00,0xF4,0xEF,0xFF,0xFF, + 0x00,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0xCA,0xCA,0x00,0x00,0x70,0xB5,0x0D,0x46, + 0x06,0x46,0x00,0x24,0x05,0xE0,0x30,0x5D,0x01,0x21,0xFE,0xF7,0xD9,0xFF,0x64,0x1C, + 0xE4,0xB2,0xAC,0x42,0xF7,0xD3,0x70,0xBD,0xF0,0xB5,0x00,0x22,0x08,0x4E,0x0B,0xE0, + 0x83,0x5C,0xDC,0x08,0xA4,0x19,0x25,0x7A,0x5F,0x07,0x7F,0x0F,0x01,0x23,0xBB,0x40, + 0x9D,0x43,0x25,0x72,0x52,0x1C,0xD2,0xB2,0x8A,0x42,0xF1,0xD3,0xF0,0xBD,0x00,0x00, + 0x60,0x12,0x00,0x40,0xF0,0xB5,0x00,0x22,0x08,0x4E,0x0B,0xE0,0x83,0x5C,0xDC,0x08, + 0xA4,0x19,0x25,0x7A,0x5F,0x07,0x7F,0x0F,0x01,0x23,0xBB,0x40,0x1D,0x43,0x25,0x72, + 0x52,0x1C,0xD2,0xB2,0x8A,0x42,0xF1,0xD3,0xF0,0xBD,0x00,0x00,0x60,0x12,0x00,0x40, + 0x06,0x4B,0xD8,0x80,0x59,0x81,0x98,0x88,0x10,0x21,0x08,0x43,0x98,0x80,0x5A,0x80, + 0x21,0x20,0x18,0x80,0x98,0x88,0xC0,0x06,0xFC,0xD5,0x70,0x47,0x00,0x11,0x00,0x40, + 0x30,0xB5,0x07,0x4B,0x9C,0x88,0x10,0x25,0x2C,0x43,0x9C,0x80,0xD8,0x80,0x19,0x81, + 0x5A,0x80,0x31,0x20,0x18,0x80,0x98,0x88,0xC0,0x06,0xFC,0xD5,0x30,0xBD,0x00,0x00, + 0x00,0x11,0x00,0x40,0x70,0xB5,0x03,0x4C,0x05,0x9E,0x04,0x9D,0xA5,0x61,0x40,0xC4, + 0x0F,0xC4,0x70,0xBD,0x78,0x21,0x00,0x20,0xF7,0xB5,0xDB,0x4D,0x04,0x46,0xA8,0x69, + 0x8A,0xB0,0x00,0x79,0x01,0x90,0x0E,0x46,0xD8,0x49,0x04,0x20,0x2F,0x68,0x03,0xF0, + 0x2B,0xF9,0xA9,0x69,0x08,0x78,0x89,0x78,0x00,0x29,0x00,0xD1,0x30,0x46,0x00,0x23, + 0x1A,0x46,0x0F,0x21,0xFF,0xF7,0xB4,0xFB,0xCF,0x4D,0xC2,0x22,0x28,0x69,0x01,0x78, + 0x38,0x46,0xFD,0xF7,0x71,0xF9,0x28,0x69,0x39,0x46,0x02,0x78,0x40,0x68,0xFF,0xF7, + 0xBF,0xFF,0x68,0x68,0x00,0x78,0x00,0x28,0x04,0xD0,0x28,0x46,0x80,0x69,0x80,0x78, + 0x00,0x28,0x1F,0xD1,0xC4,0x4D,0xA9,0x69,0x88,0x78,0x00,0x28,0x01,0xD0,0x68,0x69, + 0x04,0x78,0x28,0x69,0xC9,0x78,0x03,0x78,0x42,0x68,0x20,0x46,0x00,0xF0,0x82,0xF9, + 0x01,0x46,0x68,0x68,0x0A,0x0A,0x01,0x75,0x42,0x75,0x02,0x46,0x20,0x32,0x11,0x73, + 0x0B,0x0A,0x53,0x73,0xAA,0x69,0x21,0x23,0x9B,0x5C,0x8B,0x42,0x1A,0xD8,0x91,0x78, + 0x00,0x29,0x17,0xD0,0x00,0x20,0x05,0x90,0xB3,0x4F,0x06,0x46,0x00,0x90,0xB8,0x69, + 0xB3,0x4D,0x41,0x79,0x00,0x29,0x04,0xD0,0x78,0x68,0xC0,0x79,0xFD,0xF7,0xEA,0xF8, + 0x00,0x91,0x01,0x99,0x00,0x98,0x48,0x43,0x06,0x90,0x79,0x69,0x08,0x18,0x00,0x24, + 0x08,0x90,0x79,0xE0,0x00,0x21,0xC1,0x73,0x81,0x70,0xC1,0x71,0x04,0x74,0x3B,0xE1, + 0xA5,0x4F,0x08,0x98,0x39,0x69,0x00,0x5D,0x0B,0x78,0x4A,0x68,0xB9,0x69,0xC9,0x78, + 0x00,0xF0,0x48,0xF9,0x62,0x00,0x02,0xA9,0x88,0x52,0x06,0x9B,0x79,0x68,0x1B,0x19, + 0x5B,0x00,0x07,0x93,0x2C,0x33,0xCF,0x18,0xBC,0x46,0x7B,0x78,0x3F,0x78,0x1B,0x02, + 0x3B,0x43,0x67,0x46,0x38,0x70,0x00,0x0A,0x78,0x70,0x02,0xA8,0x80,0x5A,0xC7,0x1A, + 0x00,0x2F,0x00,0xDC,0x1F,0x1A,0xC0,0x19,0x83,0xB2,0x02,0xA8,0x83,0x52,0x07,0x98, + 0x14,0x30,0x08,0x18,0x84,0x46,0x47,0x78,0x00,0x78,0x3F,0x02,0x07,0x43,0xD8,0x1B, + 0x19,0x28,0x07,0xDD,0x58,0x00,0x18,0x18,0x38,0x18,0x80,0x03,0x03,0x0C,0x02,0xA8, + 0x83,0x52,0x06,0xE0,0x78,0x00,0x38,0x18,0xC0,0x18,0x80,0x03,0x02,0xAF,0x00,0x0C, + 0xB8,0x52,0x02,0xAF,0xBB,0x5A,0x60,0x46,0x03,0x70,0x1B,0x0A,0x43,0x70,0xB8,0x5A, + 0xA8,0x42,0x01,0xD2,0x05,0x46,0x05,0x94,0xB0,0x42,0x00,0xD9,0x06,0x46,0x7E,0x48, + 0x80,0x69,0x20,0x30,0x40,0x78,0xA8,0x42,0x1C,0xD9,0x08,0x78,0x00,0x28,0x19,0xD1, + 0x48,0x78,0xA0,0x42,0x16,0xD1,0x8A,0x78,0x00,0x98,0x82,0x42,0x12,0xD1,0x76,0x4A, + 0x50,0x68,0xC0,0x79,0x40,0x1E,0xC8,0x71,0x4C,0x70,0x00,0x98,0x88,0x70,0x68,0x46, + 0x03,0x89,0x90,0x69,0x20,0x30,0x40,0x78,0x0A,0x38,0x83,0x42,0x01,0xDA,0x00,0x20, + 0x48,0x70,0x90,0xE0,0x64,0x1C,0xE4,0xB2,0x01,0x98,0x84,0x42,0x88,0xD3,0x6A,0x49, + 0x00,0x98,0x4C,0x68,0x05,0x9A,0x11,0x30,0x22,0x54,0xA0,0x78,0x06,0x90,0x07,0x90, + 0x60,0x78,0x08,0x90,0x09,0x90,0x00,0x9F,0x89,0x69,0x05,0x91,0x64,0x4D,0x00,0x20, + 0x4B,0x79,0x14,0xE0,0x01,0x46,0x11,0x31,0x61,0x5C,0xFF,0x29,0x0D,0xD0,0x01,0x9A, + 0x42,0x43,0x51,0x18,0x49,0x00,0x14,0x31,0x0A,0x19,0x51,0x78,0x12,0x78,0x09,0x02, + 0x11,0x43,0xA9,0x42,0x01,0xD2,0x0D,0x46,0x07,0x46,0x40,0x1C,0xC0,0xB2,0x83,0x42, + 0xE8,0xD8,0x57,0x48,0x85,0x42,0x04,0xD0,0x38,0x46,0x11,0x30,0x07,0x97,0x20,0x5C, + 0x09,0x90,0x20,0x46,0x08,0x30,0x00,0x90,0xFD,0xF7,0x89,0xF8,0x00,0x28,0x12,0xD1, + 0x05,0x99,0x20,0x31,0xCA,0x78,0x0C,0x99,0x8A,0x42,0x0C,0xD8,0x38,0x46,0xA7,0x73, + 0x11,0x30,0x21,0x5C,0xE1,0x73,0xA7,0x70,0x20,0x5C,0x60,0x70,0x01,0x20,0x00,0x99, + 0xFD,0xF7,0x7E,0xF8,0x3F,0xE0,0x09,0x9A,0x08,0x99,0x91,0x42,0x03,0xD1,0x07,0x9A, + 0x06,0x99,0x91,0x42,0x27,0xD0,0x01,0x9A,0x06,0x99,0x01,0x9B,0x51,0x43,0x08,0x9A, + 0x89,0x18,0x49,0x00,0x14,0x31,0x09,0x19,0x4A,0x78,0x09,0x78,0x12,0x02,0x0A,0x43, + 0x07,0x99,0x59,0x43,0x09,0x9B,0xC9,0x18,0x49,0x00,0x14,0x31,0x61,0x18,0x4B,0x78, + 0x0F,0x78,0x19,0x02,0x39,0x43,0x1E,0x31,0x8A,0x42,0x12,0xD9,0x05,0x99,0x0C,0x9A, + 0x20,0x31,0xCB,0x78,0x93,0x42,0x0C,0xD8,0x89,0x78,0x88,0x42,0x06,0xD3,0x09,0x98, + 0x60,0x70,0x07,0x98,0xA0,0x70,0x01,0x20,0x00,0x99,0x06,0xE0,0x40,0x1C,0x00,0x99, + 0x03,0xE0,0x01,0x28,0x03,0xD9,0x40,0x1E,0x00,0x99,0xFD,0xF7,0x41,0xF8,0x09,0x98, + 0xE0,0x73,0x07,0x98,0xA0,0x73,0x24,0x4C,0xA1,0x69,0x20,0x31,0x48,0x78,0x40,0x00, + 0xB0,0x42,0x0B,0xD2,0x60,0x68,0x1E,0x22,0x02,0x70,0x49,0x78,0x0A,0x23,0x59,0x43, + 0xB1,0x42,0x1A,0xD2,0x02,0x73,0x11,0x0A,0x41,0x73,0x16,0xE0,0x60,0x68,0x42,0x7B, + 0x03,0x7B,0x12,0x02,0x1A,0x43,0x03,0xD0,0x52,0x1E,0x02,0x73,0x12,0x0A,0x42,0x73, + 0x49,0x78,0xB1,0x42,0x09,0xD9,0x01,0x78,0x00,0x29,0x06,0xD0,0x49,0x1E,0x09,0x06, + 0x09,0x0E,0x01,0x70,0x01,0xD1,0xFF,0xF7,0xFD,0xF8,0x60,0x68,0x2A,0x0A,0xC5,0x70, + 0x02,0x71,0x46,0x71,0x32,0x0A,0x82,0x71,0x82,0x78,0x01,0x99,0x63,0x69,0x4A,0x43, + 0x99,0x18,0x42,0x78,0x89,0x5C,0x01,0x74,0x08,0x20,0xFE,0xF7,0xAD,0xFF,0x06,0x4C, + 0x20,0x69,0x01,0x78,0x40,0x68,0xFF,0xF7,0xF7,0xFD,0x60,0x68,0xC1,0x79,0x49,0x1C, + 0xC1,0x71,0x00,0x7C,0x0D,0xB0,0xF0,0xBD,0x78,0x21,0x00,0x20,0xC9,0x1C,0x00,0x00, + 0xFF,0x7F,0x00,0x00,0xFF,0xB5,0x39,0x4A,0x1E,0x46,0x11,0x68,0x83,0xB0,0x9B,0x00, + 0xCD,0x18,0x01,0x91,0x73,0x00,0xD2,0x68,0xCC,0x18,0xD1,0x78,0x43,0x1E,0x99,0x42, + 0x01,0xDD,0x01,0x23,0x01,0xE0,0x41,0x1A,0xCB,0xB2,0x31,0x49,0xCF,0x88,0xFF,0xB2, + 0xCF,0x80,0xCF,0x88,0x00,0x02,0x07,0x43,0xCF,0x80,0x08,0x89,0x00,0x0A,0x00,0x02, + 0x08,0x81,0x08,0x89,0x18,0x43,0x08,0x81,0x28,0x49,0x88,0x69,0x00,0x78,0x00,0x90, + 0x88,0x68,0x53,0x79,0x01,0x79,0x12,0x79,0xC0,0x78,0xFE,0xF7,0x2B,0xFE,0x00,0x90, + 0x00,0x20,0x03,0x46,0x23,0x4A,0x04,0xE0,0x41,0x00,0x6A,0x52,0x40,0x1C,0x63,0x52, + 0xC0,0xB2,0xB0,0x42,0xF8,0xD3,0x00,0x27,0x25,0xE0,0x1C,0x48,0x01,0x23,0xC0,0x68, + 0x1A,0x46,0x41,0x79,0x00,0x79,0xFE,0xF7,0x2F,0xFF,0x32,0x46,0x01,0x99,0x05,0x98, + 0xFF,0xF7,0xCE,0xFD,0x00,0x23,0x31,0x46,0x00,0x9A,0x01,0x98,0x00,0xF0,0x2C,0xF8, + 0x00,0x21,0x0C,0xE0,0x4A,0x00,0x01,0x98,0xAB,0x5E,0x80,0x5A,0x83,0x42,0x00,0xDD, + 0xA8,0x52,0xA3,0x5E,0x83,0x42,0x00,0xDA,0xA0,0x52,0x49,0x1C,0xC9,0xB2,0xB1,0x42, + 0xF0,0xD3,0x7F,0x1C,0xFF,0xB2,0x04,0x98,0x87,0x42,0xD6,0xD3,0x00,0x21,0x08,0x46, + 0x07,0xE0,0x42,0x00,0xA3,0x5A,0xAA,0x5A,0x9A,0x1A,0x51,0x18,0x40,0x1C,0x89,0xB2, + 0xC0,0xB2,0xB0,0x42,0xF5,0xD3,0x88,0x08,0x07,0xB0,0xF0,0xBD,0x78,0x21,0x00,0x20, + 0x00,0x10,0x00,0x40,0xFF,0x7F,0x00,0x00,0xF0,0xB5,0x00,0x24,0x01,0x25,0xED,0x03, + 0xAE,0x1A,0x27,0x46,0x0C,0xE0,0x62,0x00,0x85,0x5A,0xB5,0x42,0x02,0xDD,0xAD,0x1B, + 0x85,0x52,0x00,0xE0,0x87,0x52,0x85,0x5A,0xDD,0x40,0x64,0x1C,0x85,0x52,0xA4,0xB2, + 0x8C,0x42,0xF0,0xD3,0xF0,0xBD,0x00,0x00,0x01,0x22,0x82,0x40,0x00,0xB5,0x06,0x48, + 0xD2,0xB2,0x00,0x29,0x01,0xD0,0x02,0x21,0x02,0xE0,0xD1,0x43,0xCA,0xB2,0x03,0x21, + 0xFF,0xF7,0xCA,0xFC,0x00,0xBD,0x00,0x00,0x10,0x03,0x00,0x40,0x02,0x00,0x00,0xB5, + 0x06,0x48,0x41,0x7B,0x00,0x7B,0x03,0xD0,0xC9,0x07,0xC9,0x17,0x49,0x1C,0x01,0xE0, + 0xC9,0x07,0xC9,0x0F,0xFF,0xF7,0xE0,0xFF,0x00,0xBD,0x00,0x00,0x68,0x20,0x00,0x20, + 0xF8,0xB5,0x21,0x4E,0x0D,0x46,0xF1,0x78,0x14,0x46,0xF3,0x68,0xB7,0x69,0x1A,0x78, + 0x51,0x43,0xC9,0x19,0x00,0x28,0x05,0xD0,0x58,0x68,0xFF,0xF7,0x61,0xFD,0xF0,0x78, + 0xFF,0xF7,0x3E,0xFB,0x00,0x2D,0x0A,0xD0,0x0C,0x20,0x01,0x21,0x89,0x07,0x48,0x80, + 0x70,0x68,0x00,0x23,0x41,0x79,0x00,0x79,0x01,0x22,0xFE,0xF7,0x9D,0xFE,0x00,0x2C, + 0x1E,0xD0,0x11,0x48,0xF4,0x68,0x28,0x30,0x45,0x78,0x60,0x78,0x29,0x46,0x07,0x46, + 0xFC,0xF7,0xA8,0xFE,0x00,0x29,0x14,0xD0,0x68,0x1A,0x40,0x1E,0xF1,0x78,0xC0,0x19, + 0x88,0x42,0x0D,0xDD,0xF0,0x78,0x22,0x78,0x40,0x1C,0xB1,0x69,0x50,0x43,0x41,0x18, + 0x60,0x68,0xFF,0xF7,0x35,0xFD,0xF0,0x78,0x40,0x1C,0xC0,0xB2,0xFF,0xF7,0x10,0xFB, + 0xF8,0xBD,0x00,0x20,0xE9,0xE7,0x00,0x00,0x44,0x21,0x00,0x20,0xF8,0xB5,0x05,0x46, + 0x0E,0x46,0x16,0x49,0x08,0x20,0x02,0xF0,0x77,0xFE,0x15,0x48,0x15,0x4C,0x05,0x81, + 0x20,0x88,0x20,0x27,0x38,0x40,0x88,0x30,0x20,0x80,0x64,0x2D,0x05,0xD2,0x00,0x20, + 0x60,0x81,0x28,0x01,0xE1,0x13,0x08,0x43,0x08,0xE0,0x14,0x21,0x28,0x46,0xFC,0xF7, + 0x71,0xFE,0x01,0x21,0xC9,0x03,0x08,0x43,0x60,0x81,0x0B,0x48,0x20,0x81,0x20,0x88, + 0x08,0x21,0x88,0x43,0x20,0x80,0xAA,0x20,0xA0,0x80,0x20,0x88,0x38,0x43,0x20,0x80, + 0x00,0x2E,0x01,0xD0,0x02,0x48,0x06,0x60,0xF8,0xBD,0x00,0x00,0x15,0x6B,0x00,0x00, + 0x68,0x20,0x00,0x20,0x00,0x02,0x00,0x40,0x40,0x81,0x00,0x00,0x70,0xB5,0x22,0x4A, + 0xCA,0x21,0x11,0x74,0x51,0x74,0x00,0x25,0x49,0x07,0xCD,0x80,0x1E,0x4A,0x20,0x3A, + 0x95,0x72,0x0B,0x89,0x04,0x24,0x23,0x43,0x0B,0x81,0x0B,0x89,0x08,0x24,0x23,0x43, + 0x0B,0x81,0x4B,0x89,0x80,0x24,0x23,0x43,0x4B,0x81,0x00,0x28,0x02,0xD0,0x30,0x20, + 0x10,0x71,0x00,0xE0,0x15,0x71,0x00,0xF0,0x0B,0xFC,0x13,0x4C,0x12,0x4E,0x0F,0x3C, + 0xF6,0x1F,0x00,0x21,0x20,0x46,0xFF,0xF7,0x05,0xFC,0x02,0x46,0x01,0x21,0x20,0x46, + 0xFF,0xF7,0x0A,0xFC,0x64,0x1C,0xB4,0x42,0xF3,0xD9,0x0B,0x4C,0x0A,0x4E,0x20,0x34, + 0x5B,0x36,0x00,0x22,0x01,0x21,0x20,0x46,0xFF,0xF7,0xFE,0xFB,0x64,0x1C,0xB4,0x42, + 0xF7,0xD9,0x06,0x48,0xFF,0x21,0x45,0x74,0x41,0x81,0x85,0x73,0x01,0x21,0xC1,0x73, + 0x01,0x81,0x05,0x60,0x45,0x76,0x70,0xBD,0x20,0x03,0x00,0x40,0x68,0x20,0x00,0x20, + 0xFF,0xB5,0x98,0x78,0x19,0x78,0x95,0xB0,0x40,0x1A,0x40,0x1C,0x1F,0x9F,0x10,0x90, + 0xD8,0x78,0x59,0x78,0x1E,0x9D,0x40,0x1A,0x40,0x1C,0x11,0x90,0x10,0x98,0x1C,0x46, + 0x02,0x28,0x05,0xDC,0x11,0x98,0x02,0x28,0x02,0xDC,0x00,0x20,0x19,0xB0,0xF0,0xBD, + 0x11,0x99,0x10,0x98,0x46,0x18,0x30,0x01,0x81,0x1B,0x18,0x31,0x38,0x46,0xFC,0xF7, + 0x3A,0xFE,0x0C,0x20,0x70,0x43,0xC1,0x19,0x12,0x91,0x10,0x98,0x08,0x71,0x12,0x99, + 0x11,0x98,0x88,0x72,0x12,0x99,0x70,0x1E,0x08,0x74,0x12,0x99,0x88,0x75,0x10,0x98, + 0x0C,0x97,0x80,0x00,0x11,0x99,0xC0,0x19,0x0D,0x90,0x89,0x00,0x40,0x18,0x0E,0x90, + 0xF0,0x00,0xC0,0x19,0x00,0x1F,0x0F,0x90,0x14,0x21,0x15,0x98,0x00,0x22,0x41,0x56, + 0x08,0x91,0x6E,0xE0,0x20,0x78,0x08,0x99,0x80,0x18,0x48,0x43,0x61,0x78,0x40,0x18, + 0x84,0x46,0x00,0x21,0x61,0xE0,0x17,0x98,0x63,0x46,0xC0,0x5C,0x23,0x79,0x9B,0x08, + 0x98,0x42,0x01,0xD0,0x15,0x28,0x54,0xD1,0x16,0x9B,0x66,0x46,0x9B,0x5D,0x00,0x20, + 0x14,0x3B,0x00,0x2B,0x00,0xDD,0x18,0x46,0x93,0x00,0x0C,0x9E,0x01,0x93,0xF3,0x58, + 0x01,0x26,0x36,0x04,0x07,0x46,0x37,0x43,0xDE,0x19,0xBE,0x46,0x0C,0x9F,0x01,0x9B, + 0xFE,0x50,0x8B,0x00,0x0D,0x9E,0x00,0x93,0xF6,0x58,0x0D,0x9F,0x76,0x44,0xFE,0x50, + 0x53,0x18,0x9B,0x00,0x0E,0x9E,0x09,0x93,0x07,0x93,0xF3,0x58,0x77,0x46,0xDE,0x19, + 0x0E,0x9F,0x07,0x9B,0xFE,0x50,0x11,0x9B,0x57,0x1A,0xFB,0x18,0x9B,0x00,0x02,0x93, + 0x0F,0x9E,0x1B,0x1F,0x0B,0x93,0xF3,0x58,0x77,0x46,0xDE,0x19,0x0F,0x9F,0x0B,0x9B, + 0xFE,0x50,0x01,0x9B,0x0C,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0C,0x9E, + 0xF0,0x54,0x00,0x9B,0x0D,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0D,0x9E, + 0xF0,0x54,0x09,0x9B,0x0E,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0E,0x9E, + 0xF0,0x54,0x02,0x9B,0x0F,0x9E,0x5B,0x1E,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0F,0x9E, + 0xF0,0x54,0x49,0x1C,0x60,0x46,0x40,0x1C,0x84,0x46,0x11,0x98,0x81,0x42,0x9A,0xDB, + 0x52,0x1C,0x10,0x98,0x82,0x42,0x8D,0xDB,0x00,0x27,0x78,0x1E,0x01,0x90,0x02,0x90, + 0xE7,0x81,0x20,0x98,0x19,0x21,0xC0,0x30,0x08,0x90,0x40,0x69,0x3E,0x46,0x00,0x7F, + 0x48,0x43,0x21,0x99,0x40,0x18,0x09,0x90,0x00,0x20,0x07,0xAB,0x07,0x90,0x00,0x93, + 0xB0,0x00,0x0C,0xA9,0x0A,0x90,0x08,0x58,0x72,0xB2,0x20,0x9B,0x12,0x99,0x00,0xF0, + 0xA1,0xF9,0x00,0x28,0x17,0xDD,0x08,0x99,0x49,0x69,0x89,0x68,0xC9,0x06,0x04,0xD5, + 0x00,0x2E,0x02,0xD1,0x07,0x99,0x14,0x39,0x07,0x91,0x07,0x99,0xB9,0x42,0x0A,0xDD, + 0x0A,0x9A,0x0C,0xAB,0x9B,0x58,0x82,0x00,0x92,0x1C,0x9A,0x5C,0x08,0x2A,0x02,0xD2, + 0x0F,0x46,0x01,0x96,0x02,0x90,0xE1,0x89,0x07,0x98,0x81,0x42,0x00,0xDB,0x08,0x46, + 0x76,0x1C,0xE0,0x81,0x04,0x2E,0xCF,0xDB,0x01,0x98,0x40,0x1C,0x08,0xD0,0xE0,0x89, + 0x00,0x28,0x05,0xD0,0xFF,0x22,0x09,0x99,0x24,0x32,0x51,0x1A,0x88,0x42,0x02,0xDA, + 0x01,0x20,0xA0,0x72,0x11,0xE7,0x15,0x98,0x15,0x21,0x41,0x56,0x12,0x91,0x14,0x21, + 0x41,0x56,0x01,0x98,0x07,0x91,0x00,0xB2,0x09,0x90,0x02,0x98,0x00,0xB2,0x0B,0x90, + 0xA1,0x78,0x20,0x78,0x09,0x1A,0x49,0x1C,0x13,0x91,0xE2,0x78,0x61,0x78,0x11,0x91, + 0x52,0x1A,0x52,0x1C,0x0A,0x92,0xAA,0x4A,0x00,0x21,0x22,0x80,0x61,0x80,0x2A,0x80, + 0x69,0x80,0x0F,0x46,0x02,0x91,0x01,0x90,0x56,0xE0,0x11,0x98,0x00,0x26,0x00,0x90, + 0x4B,0xE0,0x00,0x20,0x09,0x99,0xC0,0x43,0x00,0x29,0x06,0xD0,0x01,0x29,0x06,0xD0, + 0x02,0x29,0x06,0xD0,0x03,0x29,0x06,0xD0,0x09,0xE0,0x38,0x46,0x07,0xE0,0x30,0x46, + 0x05,0xE0,0xB8,0x19,0x03,0xE0,0x0A,0x98,0xB9,0x1B,0x08,0x18,0x40,0x1E,0x07,0x9A, + 0x01,0x99,0x00,0x9B,0x51,0x43,0x17,0x9A,0xD2,0x18,0x10,0x92,0x23,0x79,0x8A,0x5C, + 0x9B,0x08,0x9C,0x46,0x9A,0x42,0x01,0xD0,0x15,0x2A,0x22,0xD1,0x0B,0x9B,0x98,0x42, + 0x0E,0xD1,0x02,0x98,0x03,0xAA,0x40,0x00,0x01,0x9B,0x13,0x54,0x80,0x18,0x00,0x9B, + 0x43,0x70,0x02,0x98,0x40,0x1C,0x02,0x90,0x10,0x98,0x15,0x22,0x0A,0x54,0x10,0xE0, + 0x98,0x42,0x09,0xDD,0x62,0x45,0x03,0xD1,0x28,0x79,0x82,0x08,0x10,0x98,0x0A,0x54, + 0x28,0x46,0x00,0x9A,0x01,0x99,0x02,0xE0,0x20,0x46,0x00,0x9A,0x01,0x99,0x02,0xF0, + 0x2D,0xFD,0x00,0x98,0x76,0x1C,0x40,0x1C,0x00,0x90,0x0A,0x98,0x86,0x42,0xB0,0xDB, + 0x01,0x98,0x7F,0x1C,0x40,0x1C,0x01,0x90,0x13,0x98,0x87,0x42,0xA5,0xDB,0x00,0x20, + 0x6A,0xE0,0x01,0x99,0x00,0x23,0x49,0x00,0x03,0x20,0x03,0xAA,0x0A,0x91,0x89,0x18, + 0x09,0x91,0x0A,0x99,0x1F,0x46,0x51,0x5C,0x00,0x91,0x09,0x99,0x49,0x78,0x8C,0x46, + 0x00,0x9E,0x61,0x46,0xC2,0x07,0x05,0xD0,0x09,0x18,0x07,0x9A,0x89,0x1E,0x91,0x42, + 0x18,0xD2,0x04,0xE0,0x36,0x18,0x12,0x9A,0x76,0x1E,0x96,0x42,0x12,0xD2,0x07,0x9A, + 0x56,0x43,0x16,0x9A,0x71,0x18,0x56,0x5C,0x17,0x9A,0x14,0x3E,0x51,0x5C,0x22,0x79, + 0x92,0x08,0x91,0x42,0x01,0xD1,0x9B,0x19,0x04,0xE0,0x2A,0x79,0x92,0x08,0x91,0x42, + 0x00,0xD1,0xBF,0x19,0x40,0x1E,0xDB,0xD5,0x07,0x99,0x00,0x98,0x15,0x26,0x48,0x43, + 0x61,0x46,0x41,0x18,0x16,0x98,0x40,0x5C,0x14,0x38,0x98,0x42,0x03,0xDD,0xB8,0x42, + 0x01,0xDD,0x16,0x26,0x07,0xE0,0x9F,0x42,0x01,0xDA,0x20,0x79,0x02,0xE0,0xBB,0x42, + 0x01,0xDA,0x28,0x79,0x86,0x08,0x20,0x79,0x80,0x08,0xB0,0x42,0x04,0xD0,0x62,0x46, + 0x28,0x46,0x00,0x99,0x02,0xF0,0xCA,0xFC,0x28,0x79,0x80,0x08,0xB0,0x42,0x07,0xD0, + 0x09,0x99,0x03,0xA8,0x4A,0x78,0x0A,0x99,0x41,0x5C,0x20,0x46,0x02,0xF0,0xBE,0xFC, + 0x0A,0x99,0x03,0xA8,0x40,0x5C,0x07,0x99,0x48,0x43,0x09,0x99,0x49,0x78,0x41,0x18, + 0x17,0x98,0x46,0x54,0x01,0x98,0x40,0x1C,0x02,0x99,0x01,0x90,0x88,0x42,0x90,0xDB, + 0x08,0xB2,0x09,0x90,0x08,0x98,0x17,0x99,0x40,0x69,0x1F,0x27,0x03,0x7D,0x82,0x7D, + 0x68,0x46,0x0E,0xC0,0x20,0x79,0xFF,0x23,0x82,0x08,0x21,0x46,0x15,0x98,0xFD,0xF7, + 0x39,0xFC,0x07,0x90,0x08,0x98,0x40,0x69,0x41,0x7F,0x07,0x98,0x81,0x42,0x13,0xDB, + 0x20,0x79,0x14,0x21,0x87,0x08,0x15,0x98,0x2B,0x46,0x41,0x56,0x3A,0x46,0x17,0x98, + 0x00,0xF0,0x3F,0xF9,0x15,0x98,0x14,0x21,0x41,0x56,0x23,0x46,0x1F,0x22,0x17,0x98, + 0x00,0xF0,0x37,0xF9,0x28,0x68,0x20,0x60,0x08,0x98,0x17,0x99,0x40,0x69,0x03,0x7D, + 0x82,0x7D,0x68,0x46,0x0E,0xC0,0x28,0x79,0xFF,0x23,0x82,0x08,0x29,0x46,0x15,0x98, + 0xFD,0xF7,0x10,0xFC,0x00,0x90,0x08,0x98,0x40,0x69,0x41,0x7F,0x00,0x98,0x81,0x42, + 0x22,0xDB,0x28,0x79,0x14,0x21,0x87,0x08,0x15,0x98,0x2B,0x46,0x41,0x56,0x1F,0x22, + 0x17,0x98,0x00,0xF0,0x16,0xF9,0x00,0x26,0x13,0xE0,0x15,0x98,0x14,0x21,0x41,0x56, + 0x70,0x00,0x03,0xAA,0x13,0x5C,0x80,0x18,0x42,0x78,0x59,0x43,0x88,0x18,0x21,0x79, + 0x9C,0x46,0x8B,0x08,0x17,0x99,0x0B,0x54,0x61,0x46,0x20,0x46,0x02,0xF0,0x4E,0xFC, + 0x76,0x1C,0x09,0x98,0x86,0x42,0xE8,0xDB,0x1F,0x2F,0x02,0xD0,0x00,0x20,0xC0,0x43, + 0xBC,0xE5,0x07,0x98,0xA0,0x71,0x21,0x79,0x01,0x20,0x01,0x43,0x21,0x71,0x00,0x99, + 0xA9,0x71,0x29,0x79,0x01,0x43,0x29,0x71,0xE1,0x89,0xA9,0x81,0x00,0x21,0xE1,0x81, + 0xA9,0x89,0xA1,0x81,0x02,0x21,0xA9,0x72,0x61,0x79,0x69,0x71,0xA6,0xE5,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0xFF,0xB5,0x10,0x46,0x06,0x21,0x91,0xB0,0x48,0x43,0x12,0x99, + 0x0E,0x90,0x40,0x18,0x04,0x21,0x0C,0x90,0x41,0x56,0x01,0x20,0x14,0x46,0x02,0x2A, + 0x00,0xDB,0x00,0x20,0x00,0x26,0x08,0x18,0xF6,0x43,0x03,0x28,0x02,0xDC,0x30,0x46, + 0x15,0xB0,0xF0,0xBD,0x1D,0x46,0xC0,0x35,0x01,0x2C,0x04,0xDD,0x68,0x69,0x02,0x7D, + 0x11,0x98,0x00,0xF0,0xE5,0xF8,0x68,0x69,0x3D,0x21,0x00,0x7E,0x48,0x43,0x80,0x30, + 0x01,0x0A,0x02,0x2C,0x02,0xDB,0x2D,0x20,0x41,0x43,0x89,0x11,0x01,0x20,0x80,0x04, + 0x0A,0x91,0xFC,0xF7,0x7D,0xFB,0x00,0x27,0x00,0x26,0x0B,0x90,0xFF,0x43,0x11,0x98, + 0x03,0x97,0x09,0x96,0x00,0x88,0x06,0x96,0x0F,0x96,0x01,0x90,0x05,0x96,0x07,0x97, + 0x01,0x20,0x00,0x90,0x0C,0x99,0x08,0x97,0x04,0x20,0x08,0x56,0x34,0x46,0x04,0x90, + 0x6E,0xE0,0x88,0x00,0x11,0x99,0x00,0x9A,0x41,0x18,0x20,0x39,0x89,0x8B,0x4D,0x42, + 0x04,0x99,0x91,0x42,0x02,0xDD,0x11,0x99,0x08,0x5A,0x45,0x19,0x01,0x98,0x68,0x43, + 0x00,0x28,0x41,0xDA,0x01,0x99,0x10,0x46,0x48,0x43,0x09,0x99,0x69,0x43,0x40,0x1A, + 0x0A,0x99,0x48,0x43,0x01,0x99,0x49,0x1B,0xFC,0xF7,0x4A,0xFB,0x02,0x90,0x03,0x98, + 0x40,0x1C,0x37,0xD0,0x78,0x1C,0x38,0xD0,0x03,0x99,0x02,0x98,0x40,0x1A,0x0F,0x99, + 0x88,0x42,0x23,0xDD,0x0F,0x90,0x0B,0x98,0x03,0x99,0x07,0x91,0x78,0x43,0x02,0x99, + 0x80,0x14,0x08,0x91,0x81,0x00,0x11,0x98,0x42,0x5A,0x00,0x2A,0x27,0xD0,0xA6,0x42, + 0x02,0xDD,0x66,0x40,0x74,0x40,0x66,0x40,0x28,0x21,0x28,0x2A,0x03,0xD9,0xFA,0x21, + 0xFA,0x2A,0x00,0xD2,0x11,0x46,0x8C,0x42,0x00,0xDB,0x0C,0x46,0x30,0x19,0x80,0x00, + 0xF2,0x00,0x80,0x18,0xFC,0xF7,0x1C,0xFB,0x06,0x97,0x05,0x90,0x00,0x27,0xFF,0x43, + 0x02,0x98,0x00,0x26,0x34,0x46,0x03,0x90,0x03,0x98,0x40,0x1C,0x0C,0xD0,0x78,0x1C, + 0x08,0xD0,0x0B,0xE0,0x02,0x98,0x03,0x90,0xF6,0xE7,0x02,0x9F,0xF7,0xE7,0x7D,0x20, + 0xC0,0x00,0xE9,0xE7,0x76,0x1B,0x02,0xE0,0x78,0x1C,0x00,0xD0,0x64,0x19,0x00,0x2D, + 0x02,0xD0,0x00,0x98,0x01,0x95,0x09,0x90,0x00,0x98,0x40,0x1C,0x00,0x90,0x04,0x98, + 0x00,0x99,0x88,0x42,0x8D,0xDA,0x06,0x98,0x0B,0x99,0x40,0x00,0x40,0x1C,0x48,0x43, + 0x12,0x9B,0x0E,0x9A,0x07,0x99,0x99,0x52,0x0C,0x9A,0x08,0x99,0x51,0x80,0x0A,0x9A, + 0x0F,0x99,0x53,0x00,0xC0,0x14,0xD2,0x18,0x8A,0x42,0x00,0xDC,0x11,0x46,0x05,0x9B, + 0x01,0x22,0x4B,0x43,0x92,0x02,0x9C,0x10,0x94,0x42,0x00,0xDA,0x22,0x46,0x1A,0x9C, + 0x0F,0x2B,0x22,0x60,0x02,0xDB,0x0F,0x29,0x00,0xDB,0x39,0xE7,0x00,0x20,0xC0,0x43, + 0x36,0xE7,0xFF,0xB5,0xD1,0xB2,0x96,0x46,0x1C,0x78,0x8C,0x46,0x12,0xE0,0x01,0x9A, + 0x59,0x78,0x62,0x43,0x0A,0xE0,0x55,0x18,0x1F,0x79,0x46,0x5D,0xBF,0x08,0xBE,0x42, + 0x01,0xD0,0x15,0x2E,0x01,0xD1,0x66,0x46,0x46,0x55,0x49,0x1C,0xDD,0x78,0x8D,0x42, + 0xF1,0xDA,0x64,0x1C,0x99,0x78,0xA1,0x42,0xE9,0xDA,0x70,0x46,0x1F,0x28,0x06,0xD0, + 0x18,0x79,0x71,0x46,0x80,0x07,0x80,0x0F,0x89,0x00,0x08,0x43,0x18,0x71,0xFF,0xBD, + 0xFE,0xB5,0x04,0x46,0x00,0x20,0x0E,0x46,0x4B,0x1E,0x49,0x1E,0x84,0x46,0x01,0x91, + 0x0B,0xE0,0x81,0x00,0x0D,0x19,0xE9,0x78,0xED,0x79,0xA9,0x42,0x03,0xD3,0x91,0x42, + 0x01,0xD9,0x84,0x46,0x03,0xE0,0x01,0x99,0x40,0x1C,0x88,0x42,0xF1,0xDB,0x75,0x1E, + 0x0B,0xE0,0xA8,0x00,0x07,0x19,0xF9,0x78,0x20,0x3F,0xFF,0x7F,0xB9,0x42,0x03,0xD3, + 0x91,0x42,0x01,0xD9,0x2B,0x46,0x02,0xE0,0x6D,0x1E,0x00,0x2D,0xF1,0xDC,0xFF,0x20, + 0xF5,0x30,0x00,0x25,0x61,0x46,0x09,0xE0,0x8A,0x00,0x12,0x19,0xD2,0x78,0x82,0x42, + 0x00,0xDA,0x10,0x46,0xAA,0x42,0x00,0xDD,0x15,0x46,0x49,0x1C,0x99,0x42,0xF3,0xDD, + 0x14,0x21,0x14,0x28,0x03,0xDD,0x64,0x21,0x64,0x28,0x00,0xDA,0x01,0x46,0x28,0x1A, + 0x0A,0x22,0x50,0x43,0xFC,0xF7,0x64,0xFA,0x80,0x1C,0x00,0x90,0x0A,0x28,0x1E,0xDA, + 0x81,0x1C,0x01,0x20,0x00,0x27,0x25,0x88,0x00,0x04,0xFC,0xF7,0x59,0xFA,0x03,0x46, + 0x00,0x20,0x12,0xE0,0x01,0x9A,0x39,0x46,0x2F,0x46,0x90,0x42,0x01,0xD1,0x00,0x25, + 0x02,0xE0,0x82,0x00,0x12,0x19,0x95,0x88,0x00,0x9A,0x49,0x19,0x7A,0x43,0x51,0x18, + 0x59,0x43,0x09,0x0C,0x82,0x00,0xA1,0x52,0x40,0x1C,0xB0,0x42,0xEA,0xDB,0xFE,0xBD, + 0x62,0xB6,0x70,0x47,0x01,0x46,0x10,0xB5,0x0A,0x48,0x01,0x29,0x02,0xD1,0x0C,0x22, + 0x09,0xA1,0x08,0xE0,0x02,0x29,0x02,0xD1,0x0C,0x22,0x0B,0xA1,0x03,0xE0,0x03,0x29, + 0x03,0xD1,0x0C,0x22,0x0C,0xA1,0xFC,0xF7,0x3F,0xFA,0x00,0x21,0x04,0x20,0xFE,0xF7, + 0xA7,0xFF,0xFE,0xE7,0x50,0x01,0x00,0x20,0x6D,0x61,0x6C,0x6C,0x6F,0x63,0x20,0x65, + 0x72,0x72,0x0D,0x0A,0x00,0x00,0x00,0x00,0x4F,0x76,0x65,0x72,0x46,0x6C,0x6F,0x77, + 0x21,0x21,0x0D,0x0A,0x00,0x00,0x00,0x00,0x61,0x6C,0x67,0x4E,0x6F,0x4D,0x61,0x74, + 0x63,0x68,0x0D,0x0A,0x00,0x00,0x00,0x00,0xF0,0xB5,0x8F,0xB0,0xF0,0x20,0x6B,0x46, + 0x98,0x70,0x00,0x20,0x18,0x71,0xD9,0x79,0x58,0x71,0x09,0x09,0x09,0x01,0xC9,0xB2, + 0x09,0x07,0x09,0x0F,0xD9,0x71,0x98,0x71,0x1E,0x48,0x05,0x21,0xC0,0x7C,0x18,0x72, + 0x1D,0x48,0xC0,0x78,0xD8,0x70,0x01,0xA8,0x00,0xF0,0xE4,0xFB,0x6B,0x46,0x18,0x80, + 0x18,0x48,0x1A,0x49,0x40,0x38,0x02,0xF0,0x34,0xFD,0x18,0x48,0x00,0x24,0x60,0x30, + 0x0E,0x90,0x1F,0xE0,0x16,0x49,0x15,0x4F,0x0D,0x68,0x66,0x00,0x69,0x7F,0x2A,0x7F, + 0xB8,0x5B,0x09,0x02,0x11,0x43,0x48,0x43,0x0E,0x49,0x40,0x39,0x89,0x88,0xFC,0xF7, + 0xD7,0xF9,0xB8,0x53,0xE9,0x7F,0xF6,0x19,0xAA,0x7F,0xB0,0x8F,0x09,0x02,0x11,0x43, + 0x48,0x43,0x08,0x49,0x40,0x39,0xC9,0x88,0xFC,0xF7,0xCA,0xF9,0xB0,0x87,0x64,0x1C, + 0x0E,0x98,0xE4,0xB2,0x00,0x7E,0xA0,0x42,0xDC,0xD8,0x68,0x46,0x02,0xF0,0x64,0xF9, + 0x0F,0xB0,0xF0,0xBD,0x58,0x06,0x00,0x20,0xB8,0x04,0x00,0x20,0x78,0x1F,0x00,0x20, + 0x10,0x06,0x00,0x20,0xF7,0xB5,0xBC,0xB0,0x15,0x46,0x00,0x29,0x18,0xD0,0x00,0x24, + 0x18,0x20,0x41,0x43,0x0B,0x4E,0x0F,0x46,0x10,0xE0,0x3A,0x46,0x68,0x46,0x3C,0x99, + 0xFC,0xF7,0xBA,0xF9,0x2B,0x46,0x62,0x1C,0x69,0x46,0x70,0x68,0x02,0xF0,0x36,0xFE, + 0xC1,0xB2,0x68,0x46,0x00,0xF0,0x08,0xF8,0x64,0x1C,0xE4,0xB2,0xAC,0x42,0xEC,0xD3, + 0x3F,0xB0,0xF0,0xBD,0x58,0x07,0x00,0x20,0xF3,0xB5,0x95,0xB0,0x00,0x27,0x6B,0x46, + 0x9F,0x82,0xFF,0x20,0x98,0x75,0x61,0x48,0x14,0x90,0x01,0x79,0x3A,0x46,0xFF,0x29, + 0x26,0xD0,0x5F,0x48,0x00,0x6B,0x40,0x5C,0x00,0x09,0x20,0xD0,0x1A,0x76,0x5A,0x76, + 0x9A,0x76,0xDA,0x7E,0x09,0x07,0x12,0x09,0x12,0x01,0xD2,0xB2,0x12,0x07,0x12,0x0F, + 0xDA,0x76,0x1A,0x7F,0x09,0x0F,0x12,0x09,0x12,0x01,0x0A,0x43,0x1A,0x77,0x01,0x28, + 0x01,0xD0,0x02,0x28,0x05,0xD1,0x6B,0x46,0x18,0x7F,0x00,0x07,0x00,0x0F,0x10,0x30, + 0x03,0xE0,0x6B,0x46,0x18,0x7F,0x00,0x07,0x00,0x0F,0x6B,0x46,0x18,0x77,0x01,0x27, + 0x00,0x25,0x2E,0x46,0x7A,0xE0,0x30,0x46,0x18,0x21,0x48,0x43,0x15,0x99,0x6B,0x46, + 0x09,0x5C,0x02,0x91,0x15,0x9A,0x19,0x7C,0x84,0x18,0x09,0x07,0x60,0x78,0x09,0x0F, + 0x80,0x06,0x03,0xD0,0xA0,0x78,0x01,0x28,0x00,0xD0,0x02,0x20,0x00,0x01,0x01,0x43, + 0x6B,0x46,0xC8,0xB2,0x19,0x74,0x02,0x99,0x00,0x09,0x09,0x07,0x00,0x01,0x09,0x0F, + 0x08,0x43,0x18,0x74,0xA2,0x89,0xE0,0x89,0x00,0x90,0x14,0x98,0x00,0x78,0x00,0x28, + 0x02,0xD0,0x22,0x89,0x60,0x89,0x00,0x90,0x36,0x48,0x81,0x88,0x36,0x48,0x00,0x68, + 0x13,0x90,0x43,0x7F,0x00,0x7F,0x1B,0x02,0x03,0x43,0x53,0x43,0x18,0x46,0xFC,0xF7, + 0x27,0xF9,0x80,0xB2,0x01,0x90,0x2F,0x48,0xC1,0x88,0x13,0x98,0xC2,0x7F,0x83,0x7F, + 0x10,0x02,0x00,0x9A,0x18,0x43,0x50,0x43,0xFC,0xF7,0x1A,0xF9,0x82,0xB2,0x02,0x98, + 0x06,0x21,0x48,0x43,0x29,0x49,0xE3,0x78,0x40,0x18,0x41,0x79,0x99,0x42,0x01,0xD2, + 0x49,0x1C,0x02,0xE0,0x99,0x42,0x01,0xD9,0x49,0x1E,0x41,0x71,0x6B,0x46,0x01,0x99, + 0x19,0x73,0xD9,0x7B,0x01,0x9B,0x09,0x09,0x1B,0x05,0x09,0x01,0x1B,0x0F,0x19,0x43, + 0x6B,0x46,0xD9,0x73,0x5A,0x73,0xC9,0xB2,0x12,0x09,0xF0,0x23,0x09,0x07,0x1A,0x40, + 0x09,0x0F,0x11,0x43,0x6B,0x46,0xD9,0x73,0x40,0x79,0x98,0x73,0xB8,0x00,0x38,0x18, + 0x05,0xA9,0x40,0x18,0xA9,0x00,0x69,0x18,0x40,0x18,0x00,0x1D,0x05,0x22,0x03,0xA9, + 0xFC,0xF7,0xFA,0xF8,0x6D,0x1C,0x76,0x1C,0xED,0xB2,0x76,0xB2,0x16,0x98,0x86,0x42, + 0x81,0xDB,0x38,0x01,0x28,0x43,0x6B,0x46,0xD8,0x75,0x16,0x98,0xC0,0x19,0x81,0x00, + 0x41,0x18,0x06,0xA8,0x00,0xF0,0xC6,0xFA,0x6B,0x46,0x98,0x82,0xE8,0x19,0x02,0xD0, + 0x05,0xA8,0x02,0xF0,0x71,0xF8,0x17,0xB0,0xF0,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20, + 0x44,0x04,0x00,0x20,0x18,0x06,0x00,0x20,0x10,0x06,0x00,0x20,0xF2,0x1F,0x00,0x20, + 0xF3,0xB5,0x00,0x24,0x0F,0x46,0x83,0xB0,0x0E,0x46,0x20,0x37,0x34,0xE0,0x54,0x20, + 0x03,0x99,0x60,0x43,0x45,0x18,0x28,0x7C,0x01,0x07,0x2B,0xD0,0x39,0x79,0x00,0x09, + 0x88,0x42,0x27,0xD8,0x56,0x20,0x82,0x5D,0xF9,0x7A,0x28,0x46,0xFC,0xF7,0xBA,0xFE, + 0x28,0x7C,0x00,0x07,0x00,0x0F,0x02,0x28,0x02,0xD2,0x68,0x6B,0x00,0x90,0x14,0xE0, + 0x31,0x46,0x28,0x46,0xFC,0xF7,0x84,0xFD,0x01,0x46,0x01,0x90,0x33,0x46,0x00,0x22, + 0x28,0x46,0xFC,0xF7,0x27,0xFE,0x69,0x46,0x08,0x80,0x33,0x46,0x01,0x22,0x28,0x46, + 0x01,0x99,0xFC,0xF7,0x1F,0xFE,0x69,0x46,0x48,0x80,0x6A,0x46,0x31,0x46,0x28,0x46, + 0x02,0xF0,0x34,0xFE,0x64,0x1C,0xE4,0xB2,0xB0,0x78,0xA0,0x42,0xC7,0xD8,0x00,0x20, + 0x05,0xB0,0xF0,0xBD,0xFF,0x30,0x41,0x30,0x40,0x68,0x02,0x49,0xC1,0x60,0x00,0x20, + 0x70,0x47,0x00,0x00,0x31,0x3F,0x00,0x00,0xFF,0xB5,0x06,0x46,0x08,0x46,0x83,0xB0, + 0x0D,0x46,0x24,0x30,0x01,0x90,0x18,0x30,0x18,0x31,0x02,0x90,0x30,0x38,0x00,0x91, + 0x2F,0x46,0x01,0x21,0x54,0x37,0x81,0x55,0x00,0x24,0x17,0xE0,0x00,0x98,0x00,0x5D, + 0x00,0x28,0x12,0xD1,0x01,0x98,0x71,0x00,0x42,0x5E,0x02,0x98,0x61,0x00,0x40,0x5E, + 0x12,0x18,0x06,0x98,0x70,0x43,0x00,0x19,0x43,0x00,0x05,0x98,0xC0,0x5A,0x10,0x1A, + 0x0A,0xD0,0x7A,0x5E,0x82,0x42,0x00,0xDD,0x78,0x52,0x64,0x1C,0x06,0x98,0x84,0x42, + 0xE4,0xD3,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x00,0x99,0x01,0x20,0x08,0x55,0x28,0x57, + 0x41,0x1C,0x06,0xD0,0x29,0x46,0x06,0x9B,0x05,0x9A,0xFF,0xF7,0xC5,0xFF,0x00,0x28, + 0xEB,0xD0,0x2E,0x55,0x01,0x20,0xED,0xE7,0xF8,0xB5,0x79,0x48,0x2B,0x27,0x07,0x70, + 0x00,0x26,0x78,0x4C,0x46,0x70,0x20,0x68,0xFF,0x30,0x41,0x30,0x40,0x7C,0x01,0xF0, + 0xF7,0xFF,0x00,0x20,0xFF,0xF7,0x2A,0xF9,0x73,0x48,0x21,0x68,0x05,0x6D,0xFF,0x31, + 0x9C,0x22,0xA1,0x31,0x71,0x48,0xFC,0xF7,0x2F,0xF8,0x5C,0x22,0x6F,0x49,0x70,0x48, + 0xFC,0xF7,0x2A,0xF8,0x6E,0x48,0x6F,0x49,0x86,0x72,0x06,0x77,0x30,0x20,0x48,0x70, + 0x08,0x46,0x20,0x30,0x00,0x90,0xA8,0xE0,0x65,0x48,0x00,0x78,0x01,0x46,0x20,0x38, + 0x10,0x28,0x55,0xD8,0x62,0x4C,0x2B,0x29,0x01,0xD0,0xF0,0x21,0x61,0x70,0x03,0x46, + 0xFC,0xF7,0xAA,0xF8,0x0B,0x07,0x0B,0x12,0x17,0x3D,0x40,0x4E,0x45,0x60,0x6C,0x75, + 0x4E,0x00,0x5F,0x49,0x07,0x20,0x88,0x73,0x01,0xE0,0x5D,0x48,0x86,0x73,0xE0,0x78, + 0x29,0x46,0x00,0xF0,0xFB,0xF9,0x2D,0xE0,0x00,0x21,0x0A,0x20,0xFD,0xF7,0xF2,0xFF, + 0x4F,0xE0,0x53,0x48,0xC0,0x78,0x00,0x28,0x0C,0xD1,0x53,0x4C,0x2B,0x46,0x22,0x78, + 0xE1,0x69,0xE0,0x68,0xFD,0xF7,0x18,0xFF,0x20,0x78,0x62,0x78,0x40,0x00,0x43,0x19, + 0xA1,0x69,0x0B,0xE0,0x50,0x4C,0x2B,0x46,0x22,0x78,0xA1,0x69,0xE0,0x68,0xFD,0xF7, + 0x0B,0xFF,0x20,0x78,0x62,0x78,0x40,0x00,0x61,0x69,0x43,0x19,0x20,0x69,0xFD,0xF7, + 0x03,0xFF,0x43,0x49,0x01,0x20,0x88,0x70,0xFC,0x20,0x48,0x70,0x44,0xE0,0x02,0x20, + 0xA0,0x70,0x11,0xE0,0x01,0x20,0xA0,0x70,0xFC,0x20,0x60,0x70,0x3C,0xE0,0x02,0x20, + 0xA0,0x70,0x66,0x70,0x00,0x22,0x27,0x70,0x21,0x21,0x10,0x46,0x02,0xF0,0xE6,0xFD, + 0x37,0x48,0x81,0x78,0x02,0x29,0x2C,0xD1,0x35,0x4C,0x60,0x78,0xFC,0x28,0x40,0xD1, + 0x01,0x20,0xFF,0xF7,0xAB,0xF8,0x05,0x20,0xFE,0xF7,0xF4,0xFC,0x00,0x20,0xFF,0xF7, + 0xA5,0xF8,0x08,0xE0,0x2F,0x48,0x00,0x68,0xFF,0x30,0x61,0x30,0x00,0x7D,0x01,0x21, + 0x0A,0xE0,0x02,0x20,0xA0,0x70,0x27,0x70,0x66,0x70,0x2A,0xE0,0x29,0x48,0x00,0x21, + 0x00,0x68,0xFF,0x30,0x61,0x30,0x00,0x7D,0xFF,0xF7,0x7E,0xF8,0xF1,0xE7,0x78,0x20, + 0xFE,0xF7,0xD8,0xFC,0xFE,0xF7,0x96,0xF8,0x00,0x21,0x01,0x20,0xFE,0xF7,0x00,0xFD, + 0xFA,0xE7,0x40,0x78,0xFC,0x28,0x14,0xD1,0x00,0x98,0x86,0x70,0x01,0x20,0xFF,0xF7, + 0x7D,0xF8,0x1C,0x48,0x00,0x68,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A,0x08,0x02, + 0x10,0x43,0x02,0xF0,0x81,0xFD,0x00,0x20,0xFF,0xF7,0x70,0xF8,0x14,0x48,0x07,0x70, + 0x46,0x70,0x00,0x21,0x01,0x20,0xFE,0xF7,0xE3,0xFC,0x16,0x48,0x00,0x78,0x11,0x28, + 0x00,0xD1,0x51,0xE7,0x0F,0x48,0x9C,0x22,0x01,0x68,0x10,0x48,0x0C,0x46,0xFF,0x31, + 0xA1,0x31,0xFB,0xF7,0x69,0xFF,0x5C,0x22,0x0C,0x49,0x0D,0x48,0xFB,0xF7,0x64,0xFF, + 0x0C,0x48,0x31,0x0A,0x86,0x72,0xC1,0x72,0x00,0x9A,0x01,0x21,0x91,0x71,0x06,0x72, + 0x31,0x0A,0x41,0x72,0xFF,0x21,0x51,0x31,0x08,0x5D,0x01,0xF0,0x11,0xFF,0xF8,0xBD, + 0xC8,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0xAC,0x03,0x00,0x20,0x32,0x05,0x00,0x20, + 0xD6,0x04,0x00,0x20,0x98,0x04,0x00,0x20,0x44,0x04,0x00,0x20,0x01,0x49,0x01,0x20, + 0xC8,0x82,0x70,0x47,0x00,0x20,0x00,0x40,0xFF,0xB5,0x81,0xB0,0x00,0x24,0x33,0xE0, + 0x20,0x46,0x48,0x43,0x01,0x9A,0x40,0x00,0x83,0x18,0x04,0x9A,0x9C,0x46,0x85,0x18, + 0x02,0x20,0x00,0x22,0x18,0x5E,0x9A,0x5E,0x43,0x00,0x93,0x42,0x02,0xDA,0x53,0x00, + 0xD3,0x18,0x00,0xE0,0x53,0x00,0x1B,0x18,0x2B,0x80,0x01,0x23,0x4E,0x1E,0x00,0x96, + 0x0D,0xE0,0x46,0x00,0xB6,0x18,0x02,0x46,0x58,0x00,0x67,0x46,0x86,0x46,0xC7,0x19, + 0x02,0x20,0x38,0x5E,0x37,0x18,0x76,0x46,0xAF,0x53,0x00,0x9E,0x5B,0x1C,0xB3,0x42, + 0xEF,0xDB,0x56,0x00,0x86,0x42,0x02,0xDA,0x46,0x00,0x80,0x19,0x00,0xE0,0x40,0x00, + 0x80,0x18,0x5A,0x00,0xA8,0x52,0x64,0x1C,0x03,0x98,0x84,0x42,0xC8,0xDB,0x00,0x25, + 0x30,0xE0,0x04,0x98,0x6A,0x00,0x14,0x18,0x48,0x00,0x00,0x22,0x20,0x5E,0xA2,0x5E, + 0x43,0x00,0x93,0x42,0x02,0xDA,0x53,0x00,0xD3,0x18,0x00,0xE0,0x53,0x00,0x1B,0x18, + 0x1B,0x11,0x23,0x80,0x03,0x9E,0x0B,0x46,0x76,0x1E,0x4E,0x43,0xB4,0x46,0x0B,0xE0, + 0x46,0x00,0xB2,0x18,0x17,0xB2,0x02,0x46,0x5E,0x18,0x70,0x00,0x20,0x5E,0x3F,0x18, + 0x3F,0x11,0x5B,0x00,0xE7,0x52,0x33,0x46,0x9C,0x45,0xF1,0xDC,0x56,0x00,0x86,0x42, + 0x02,0xDA,0x46,0x00,0x80,0x19,0x00,0xE0,0x40,0x00,0x80,0x18,0x00,0x11,0x5A,0x00, + 0xA0,0x52,0x6D,0x1C,0x8D,0x42,0xCC,0xDB,0x05,0xB0,0xF0,0xBD,0xF0,0xB5,0x03,0x46, + 0xC0,0x30,0x84,0x68,0x40,0x69,0x85,0xB0,0x01,0x27,0x05,0x46,0xFF,0x43,0x40,0x35, + 0x03,0x90,0xEF,0x74,0x03,0x98,0x80,0x68,0x00,0x07,0x02,0xD4,0x38,0x46,0x05,0xB0, + 0xF0,0xBD,0xA8,0x7D,0x02,0x90,0x00,0x20,0x01,0x90,0x00,0x90,0x6A,0x46,0x01,0xA9, + 0x18,0x46,0xFD,0xF7,0x73,0xFA,0x06,0x46,0x01,0x28,0x03,0xDD,0xFF,0x20,0xE8,0x74, + 0xE0,0x70,0x01,0x26,0x31,0x46,0x20,0x46,0x02,0x9A,0x00,0xF0,0x63,0xF8,0x60,0x78, + 0x01,0x28,0x02,0xD0,0x02,0x28,0x11,0xD0,0x25,0xE0,0x01,0x2E,0x0C,0xD1,0x20,0x46, + 0x00,0x9A,0x01,0x99,0x02,0xF0,0x3F,0xFC,0xE2,0x88,0x02,0x99,0x14,0x48,0x51,0x18, + 0x81,0x42,0x00,0xDC,0x08,0x46,0xE0,0x80,0xEF,0x74,0x14,0xE0,0xE0,0x78,0xFF,0x28, + 0x18,0xD0,0x20,0x46,0x03,0x99,0x00,0xF0,0xCF,0xFB,0xE1,0x68,0x07,0x46,0x00,0x29, + 0x07,0xD0,0x00,0x2F,0x05,0xDA,0x20,0x78,0x04,0x28,0x02,0xD3,0x20,0x46,0x88,0x47, + 0x07,0x46,0x00,0x20,0x60,0x70,0x3A,0x46,0x20,0x46,0x03,0x99,0xFD,0xF7,0xF5,0xF9, + 0xE8,0x74,0xB4,0xE7,0x00,0x27,0xFF,0x43,0x00,0x20,0xE0,0x70,0xF1,0xE7,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0x70,0xB5,0x0D,0x46,0x81,0x68,0x16,0x46,0x09,0x07,0x01,0xD4, + 0x00,0x20,0x70,0xBD,0xFF,0x22,0x53,0x21,0x0A,0x54,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x08,0x48,0x20,0x61,0x01,0xF0,0x42,0xF8,0xC0,0x34,0xA0,0x60,0xC8,0x20,0x01,0xF0, + 0x5B,0xF8,0xA4,0x68,0xC8,0x21,0x20,0x46,0xFB,0xF7,0x75,0xFE,0x26,0x61,0xC8,0x20, + 0xE5,0x60,0x70,0xBD,0x3D,0x43,0x00,0x00,0x10,0xB5,0x00,0x22,0x11,0x46,0xFF,0xF7, + 0xD9,0xFF,0x10,0xBD,0x10,0xB5,0x00,0x29,0x06,0xD1,0x84,0x88,0x0C,0x4B,0xA2,0x18, + 0x9A,0x42,0x00,0xDA,0x13,0x46,0x83,0x80,0x42,0x78,0x00,0x2A,0x07,0xD0,0x01,0x2A, + 0x04,0xD1,0x81,0x88,0x05,0x29,0x01,0xD3,0x02,0x21,0x41,0x70,0x10,0xBD,0x01,0x29, + 0xFC,0xD1,0x41,0x70,0x00,0x21,0x01,0x70,0xC1,0x80,0x81,0x80,0x10,0xBD,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0x03,0x46,0x10,0xB5,0x55,0x20,0x00,0x22,0x03,0xE0,0x9C,0x5C, + 0x20,0x18,0x80,0xB2,0x52,0x1C,0x8A,0x42,0xF9,0xDB,0x10,0xBD,0x06,0x48,0x80,0x69, + 0x01,0x79,0x04,0x29,0x03,0xD0,0x03,0x29,0x03,0xD0,0x1B,0x30,0x70,0x47,0x80,0x1D, + 0x70,0x47,0x12,0x30,0x70,0x47,0x00,0x00,0x78,0x21,0x00,0x20,0xF0,0xB5,0x05,0x46, + 0x85,0xB0,0x0C,0x46,0x01,0x20,0xFE,0xF7,0x33,0xFA,0x1C,0x48,0x1C,0x4B,0x1D,0x4E, + 0x1D,0x4F,0x00,0x2D,0x0A,0xD1,0x41,0x6C,0xF0,0x6A,0x01,0x22,0x02,0x92,0x01,0x91, + 0x00,0x90,0x1A,0x46,0x08,0x3A,0x19,0x46,0x30,0x46,0x09,0xE0,0x81,0x6C,0xF8,0x69, + 0x01,0x22,0x02,0x92,0x00,0x90,0x12,0x4A,0x01,0x91,0x13,0x48,0x08,0x3A,0x19,0x46, + 0x23,0x46,0xFE,0xF7,0xE5,0xF8,0x0E,0x48,0x08,0x22,0x08,0x38,0x81,0x78,0x00,0x7A, + 0x00,0x23,0xFE,0xF7,0x35,0xF8,0x03,0x90,0x01,0x20,0xFE,0xF7,0xCD,0xF9,0x00,0x2D, + 0x04,0xD1,0x32,0x78,0x70,0x78,0xF3,0x6A,0x42,0x43,0x01,0xE0,0x3A,0x78,0xFB,0x69, + 0x20,0x46,0x03,0x99,0x01,0xF0,0x16,0xFE,0x05,0xB0,0xF0,0xBD,0x60,0x03,0x00,0x20, + 0xDE,0x04,0x00,0x20,0xAC,0x03,0x00,0x20,0x44,0x04,0x00,0x20,0x04,0x48,0x01,0x7A, + 0xC2,0x79,0x88,0x1A,0x91,0x42,0x00,0xD2,0x08,0x30,0xC0,0xB2,0x70,0x47,0x00,0x00, + 0xB8,0x04,0x00,0x20,0x10,0xB5,0x04,0x48,0x00,0x69,0x80,0x47,0x02,0x49,0x01,0x20, + 0x08,0x39,0x08,0x71,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0x03,0x49,0x02,0x48, + 0xC8,0x60,0xBF,0xF3,0x40,0x8F,0xFE,0xE7,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0, + 0xF7,0xB5,0x8C,0xB0,0xC8,0x69,0x08,0x90,0x08,0x6A,0x09,0x90,0x48,0x6A,0x06,0x90, + 0x0C,0x98,0x15,0x24,0x04,0x57,0x14,0x25,0x45,0x57,0x22,0x46,0x06,0x98,0x6A,0x43, + 0x13,0x18,0x00,0x20,0x03,0x90,0x02,0x46,0x04,0x90,0xC8,0x6A,0x01,0x26,0x86,0x57, + 0x07,0x96,0x02,0x26,0x86,0x57,0x0A,0x96,0x03,0x26,0x86,0x57,0xB0,0x10,0x6E,0x46, + 0x31,0xC6,0x00,0x20,0x6C,0xE0,0x0E,0x98,0x00,0x28,0x00,0xD0,0x01,0x20,0x86,0x46, + 0x60,0xE0,0x00,0x20,0x0B,0x90,0xC5,0x07,0x05,0x9C,0xED,0x0F,0x2C,0x19,0x02,0x25, + 0x05,0x40,0x75,0x44,0xAC,0x46,0x01,0x9D,0xAC,0x42,0x34,0xD2,0x02,0x9D,0xAC,0x45, + 0x31,0xD2,0x65,0x43,0x06,0x9E,0x65,0x44,0x76,0x57,0x32,0x36,0x65,0x2E,0x30,0xD2, + 0x08,0x9E,0x6D,0x00,0x77,0x5F,0x09,0x9E,0x75,0x5F,0x07,0x9E,0x7D,0x1B,0xB5,0x42, + 0x02,0xDC,0x0A,0x9E,0xB5,0x42,0x00,0xDA,0x52,0x1C,0x0E,0x9E,0x00,0x2E,0x1A,0xD1, + 0x40,0x26,0x77,0x5E,0x00,0x2F,0x16,0xDD,0x07,0x9E,0xB5,0x42,0x13,0xDD,0x0C,0x9D, + 0x64,0x00,0x6D,0x68,0x4E,0x6B,0x2D,0x5F,0x34,0x5F,0x2C,0x1B,0x0A,0x2C,0x0A,0xDD, + 0x0C,0x9C,0xCE,0x6C,0xA5,0x68,0x64,0x46,0x64,0x00,0x2D,0x5F,0x34,0x5F,0x2C,0x1B, + 0x0A,0x2C,0x00,0xDD,0x52,0x1E,0x40,0x1C,0x04,0x28,0xBC,0xDB,0x0B,0x98,0x00,0x28, + 0x02,0xD0,0x00,0x20,0x18,0x70,0x11,0xE0,0x00,0x20,0x18,0x56,0x7F,0x24,0x45,0x1C, + 0x7F,0x2D,0x00,0xDA,0x2C,0x46,0x60,0xB2,0x18,0x70,0x03,0x9C,0x64,0x1C,0x03,0x94, + 0x00,0x9C,0xA0,0x42,0x02,0xDB,0x04,0x98,0x40,0x1C,0x04,0x90,0x70,0x46,0x80,0x1C, + 0x86,0x46,0x5B,0x1C,0x04,0x46,0x02,0x98,0x84,0x42,0x9A,0xDB,0x05,0x98,0x80,0x1C, + 0x01,0x9C,0x05,0x90,0xA0,0x42,0x8E,0xDB,0x04,0x9B,0x03,0x99,0x00,0x20,0x99,0x42, + 0x04,0xD1,0x00,0x29,0x02,0xDD,0x02,0x2A,0x00,0xDD,0x01,0x20,0x0F,0xB0,0xF0,0xBD, + 0xF3,0xB5,0x81,0xB0,0x05,0x46,0x00,0x24,0x18,0x20,0x60,0x43,0x42,0x19,0x18,0x32, + 0x50,0x68,0x00,0x28,0x2A,0xD0,0x02,0x98,0x00,0x28,0x04,0xD0,0x10,0x21,0x51,0x5E, + 0x00,0x2C,0x1D,0xD0,0x1F,0xE0,0x00,0x21,0xD6,0x68,0x14,0xE0,0x13,0x68,0x48,0x00, + 0x97,0x68,0x1B,0x5E,0x38,0x5E,0x1B,0x1A,0x70,0x56,0xC7,0x00,0x38,0x1A,0xC0,0x10, + 0xC0,0x18,0x7F,0x23,0xDB,0x43,0x98,0x42,0x03,0xDD,0x7F,0x23,0x7F,0x28,0x00,0xDA, + 0x03,0x46,0x73,0x54,0x49,0x1C,0x10,0x20,0x10,0x5E,0x88,0x42,0xE6,0xDC,0x05,0xE0, + 0x00,0x20,0x28,0x5E,0x41,0x18,0xD0,0x68,0xFB,0xF7,0xED,0xFC,0x64,0x1C,0x05,0x2C, + 0xCA,0xDB,0xFE,0xBD,0xF8,0xB5,0x66,0x4D,0xE8,0x79,0x66,0x4E,0xC1,0x07,0x34,0x46, + 0x20,0x34,0xE0,0x7A,0x00,0x27,0x00,0x29,0x43,0xD0,0x29,0x46,0x4D,0x88,0xC9,0x79, + 0x09,0x06,0x1E,0xD5,0x5E,0x49,0x10,0x22,0xCA,0x71,0x31,0x1F,0x0F,0x80,0x00,0x28, + 0x1C,0xD0,0x70,0x69,0x80,0x47,0x28,0x0A,0x00,0x90,0xB1,0x69,0x88,0x47,0xE0,0x7A, + 0x00,0x28,0x09,0xD0,0x00,0x98,0xFE,0xF7,0x9F,0xF9,0x00,0x28,0x04,0xD0,0x01,0x20, + 0xA0,0x72,0xE7,0x72,0xF1,0x6A,0x08,0x70,0xB1,0x69,0xE8,0xB2,0x88,0x47,0x35,0x85, + 0x04,0xE0,0x50,0x49,0x09,0x1F,0x08,0x88,0x40,0x1C,0x08,0x80,0x4E,0x49,0xA0,0x20, + 0x88,0x80,0x4C,0x48,0xFF,0x22,0x00,0x1F,0x01,0x88,0xF5,0x32,0x91,0x42,0x0F,0xD9, + 0x47,0x49,0x10,0x22,0xCA,0x71,0x07,0x80,0xE0,0x7A,0x00,0x28,0x08,0xD0,0x70,0x69, + 0x80,0x47,0xB1,0x69,0x28,0x0A,0x88,0x47,0xB1,0x69,0xE8,0xB2,0x88,0x47,0x35,0x85, + 0xF8,0xBD,0xA9,0x79,0xCF,0x22,0x11,0x40,0x01,0x29,0x33,0xD0,0x05,0x29,0x1F,0xD0, + 0x09,0x29,0x72,0xD1,0xA7,0x71,0xE7,0x71,0x29,0x78,0x09,0x06,0x08,0xD4,0x00,0x28, + 0x06,0xD0,0x68,0x88,0x31,0x69,0xC0,0x05,0x00,0x0E,0x88,0x47,0x00,0x28,0x64,0xD0, + 0x68,0x88,0xC0,0x07,0x0C,0xD1,0x37,0x84,0xE0,0x7A,0x00,0x28,0x01,0xD0,0x70,0x69, + 0x80,0x47,0xA0,0x7A,0x00,0x28,0x01,0xD0,0x70,0x68,0x80,0x47,0x10,0x20,0x0D,0xE0, + 0xE0,0x7A,0x00,0x28,0x0C,0xD0,0x30,0x8D,0xC0,0xB2,0x55,0x28,0x02,0xD1,0xE0,0x79, + 0x40,0x1C,0xE0,0x71,0xF0,0x69,0x80,0x47,0x68,0x80,0x14,0x20,0xA8,0x71,0xF8,0xBD, + 0xF0,0x68,0xF8,0xE7,0x22,0x49,0x49,0x88,0xA2,0x79,0xCD,0xB2,0x21,0x49,0x02,0x2A, + 0x89,0x68,0x30,0xD2,0x33,0x8C,0x1B,0x02,0x2B,0x43,0x33,0x84,0x00,0x28,0x1E,0xD0, + 0x00,0x2A,0x15,0xD1,0x28,0x46,0xFE,0xF7,0x27,0xF9,0x00,0x28,0x04,0xD0,0x01,0x20, + 0xA0,0x72,0xE7,0x72,0xF1,0x6A,0x08,0x70,0x60,0x7C,0xA8,0x42,0x02,0xD1,0xE7,0x71, + 0x37,0x85,0x05,0xE0,0x30,0x8D,0x00,0x02,0x30,0x85,0x30,0x8D,0x28,0x43,0x30,0x85, + 0xA0,0x79,0x01,0x28,0x01,0xD1,0xFE,0xF7,0x47,0xF9,0xB1,0x69,0x05,0xE0,0x01,0x2A, + 0x05,0xD1,0x30,0x8C,0x00,0x0A,0x88,0x47,0xB1,0x68,0x28,0x46,0x88,0x47,0xA0,0x79, + 0x40,0x1C,0xA0,0x71,0x04,0xE0,0x00,0x28,0x00,0xD0,0xB1,0x69,0x28,0x46,0x88,0x47, + 0x03,0x49,0x10,0x20,0x88,0x71,0xF8,0xBD,0xFF,0xE7,0xAF,0x71,0xFB,0xE7,0x00,0x00, + 0x00,0x20,0x00,0x40,0xC8,0x20,0x00,0x20,0x00,0x02,0x00,0x40,0x10,0xB5,0x04,0x48, + 0x40,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x48,0x70,0x10,0xBD,0x00,0x00, + 0x50,0x20,0x00,0x20,0xF0,0xB5,0x18,0x48,0x89,0xB0,0x04,0x68,0x6B,0x46,0xFF,0x34, + 0x41,0x34,0x60,0x7F,0xE2,0x7F,0x61,0x7E,0x07,0xC3,0xA3,0x7E,0xE2,0x7E,0x21,0x7F, + 0x20,0x7E,0xFD,0xF7,0x0D,0xFD,0x11,0x48,0x11,0x4A,0x01,0x68,0x8E,0x46,0x41,0x68, + 0x8C,0x46,0x81,0x68,0x08,0x91,0xC3,0x68,0x10,0x30,0xF0,0xC8,0x30,0x20,0x05,0x90, + 0x00,0x21,0x09,0x48,0x07,0x92,0x06,0x91,0x00,0x68,0x41,0x7E,0x00,0x7E,0x0A,0x02, + 0x02,0x43,0x68,0x46,0xF0,0xC0,0x04,0x92,0x61,0x46,0x70,0x46,0x08,0x9A,0xFD,0xF7, + 0x5B,0xFD,0x09,0xB0,0xF0,0xBD,0x00,0x00,0x10,0x06,0x00,0x20,0x98,0x6D,0x00,0x00, + 0xC3,0x04,0x00,0x20,0x0A,0x49,0x0B,0x48,0x0A,0x6D,0x02,0x60,0x4A,0x6D,0x42,0x60, + 0x8A,0x6D,0x82,0x60,0x08,0x4A,0xC2,0x60,0x00,0x22,0x02,0x74,0x42,0x74,0x07,0x48, + 0x00,0x68,0x20,0x30,0x02,0x7C,0x4A,0x75,0x40,0x7C,0x08,0x75,0x70,0x47,0x00,0x00, + 0xAC,0x03,0x00,0x20,0x34,0x20,0x00,0x20,0x7A,0x01,0x00,0x20,0x10,0x06,0x00,0x20, + 0x70,0xB5,0x00,0x24,0x18,0x4D,0x19,0x4E,0x08,0xE0,0x00,0x19,0x20,0x30,0x00,0x7D, + 0xFD,0xF7,0x0A,0xFA,0xA9,0x69,0x08,0x55,0x64,0x1C,0xE4,0xB2,0x30,0x68,0x30,0x21, + 0x09,0x5C,0xA1,0x42,0xF1,0xD8,0x00,0x24,0x08,0xE0,0x00,0x19,0x60,0x30,0x00,0x7A, + 0xFD,0xF7,0xFA,0xF9,0xE9,0x69,0x08,0x55,0x64,0x1C,0xE4,0xB2,0x30,0x68,0x31,0x21, + 0x09,0x5C,0xA1,0x42,0xF1,0xD8,0x01,0x46,0x20,0x31,0x4A,0x7C,0x2A,0x70,0x09,0x7C, + 0x69,0x70,0xE9,0x69,0x69,0x60,0xA9,0x69,0xA9,0x60,0x01,0x46,0x68,0x31,0x34,0x30, + 0xE9,0x60,0x28,0x61,0x70,0xBD,0x00,0x00,0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20, + 0x70,0xB5,0x15,0x4C,0x10,0x20,0x20,0x70,0x20,0x20,0x60,0x70,0x00,0x21,0x07,0x20, + 0xFE,0xF7,0xB6,0xF8,0xA0,0x70,0xFF,0x22,0x10,0x48,0x62,0x77,0x01,0x68,0x0D,0x46, + 0xFF,0x31,0x41,0x31,0x08,0x7C,0x20,0x77,0x0D,0x48,0x81,0x78,0x20,0x46,0x20,0x30, + 0x41,0x71,0x01,0x21,0x81,0x71,0x81,0x70,0x02,0x71,0x00,0x21,0x81,0x73,0xC1,0x20, + 0x08,0x49,0x80,0x04,0xFB,0xF7,0x6C,0xFB,0x29,0x46,0x40,0x22,0xA8,0x31,0x06,0x48, + 0xFB,0xF7,0x2A,0xFB,0x70,0xBD,0x00,0x00,0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0xD6,0x04,0x00,0x20,0x4A,0x01,0x00,0x20,0xCE,0x05,0x00,0x20,0x7C,0xB5,0x29,0x4D, + 0x20,0x20,0x68,0x70,0x29,0x4C,0x28,0x48,0x20,0x60,0x9C,0x22,0x28,0x49,0x29,0x48, + 0xFB,0xF7,0x12,0xFB,0x5C,0x22,0x27,0x49,0x27,0x48,0xFB,0xF7,0x0D,0xFB,0x22,0x48, + 0x10,0x30,0xFB,0xF7,0x3C,0xFB,0xC0,0x07,0xC0,0x0F,0xFE,0xF7,0x87,0xFC,0x20,0x68, + 0x01,0x22,0xFF,0x30,0x61,0x30,0x41,0x7D,0x00,0x7D,0xFD,0xF7,0xF5,0xFC,0xFF,0xF7, + 0x19,0xFF,0xFB,0xF7,0xC1,0xFD,0xFF,0xF7,0xA3,0xFF,0xFF,0xF7,0x69,0xFF,0x01,0xF0, + 0x19,0xF9,0x01,0xF0,0x4F,0xF8,0x20,0x68,0xFF,0x30,0x51,0x30,0x41,0x79,0x00,0x79, + 0x09,0x02,0x01,0x43,0x00,0x20,0xFE,0xF7,0x53,0xF8,0x14,0x48,0x12,0x49,0x02,0x6A, + 0x34,0x31,0x01,0x92,0x00,0x91,0x10,0x4A,0x2C,0x39,0x11,0x48,0x0F,0x4B,0xFE,0xF7, + 0x61,0xF9,0x20,0x68,0xFF,0x30,0x81,0x30,0xC0,0x7E,0x00,0x28,0x28,0x7F,0x01,0xD0, + 0x0C,0x49,0x00,0xE0,0x00,0x21,0xFE,0xF7,0x19,0xFC,0xFF,0xF7,0x23,0xFF,0xFB,0xF7, + 0x11,0xFC,0x7C,0xBD,0x98,0x04,0x00,0x20,0x00,0x8C,0x00,0x00,0x10,0x06,0x00,0x20, + 0xA0,0x8D,0x00,0x00,0x32,0x05,0x00,0x20,0xD6,0x04,0x00,0x20,0xAC,0x03,0x00,0x20, + 0x60,0x03,0x00,0x20,0x19,0x61,0x00,0x00,0x70,0xB5,0x09,0x24,0xA4,0x03,0x01,0x21, + 0x05,0x78,0x11,0xE0,0x06,0x22,0x4A,0x43,0x12,0x18,0x83,0x8A,0x96,0x8A,0xD2,0x8A, + 0x9B,0x1B,0xC6,0x8A,0x5B,0x43,0xB2,0x1A,0x52,0x43,0x9A,0x18,0xA2,0x42,0x02,0xDD, + 0x00,0x20,0xC0,0x43,0x70,0xBD,0x49,0x1C,0x8D,0x42,0xEB,0xDC,0x00,0x20,0x70,0xBD, + 0xFF,0xB5,0x83,0xB0,0x6A,0x46,0x10,0x21,0x0C,0x20,0x51,0x5E,0x10,0x5E,0x8E,0x46, + 0x88,0x42,0x02,0xDA,0x02,0x46,0x0B,0x46,0x01,0xE0,0x0A,0x46,0x03,0x46,0x6D,0x46, + 0x18,0x24,0x14,0x21,0x2C,0x5F,0x69,0x5E,0xA4,0x46,0xA1,0x42,0x02,0xDA,0x0C,0x46, + 0x65,0x46,0x00,0xE0,0x0D,0x46,0xA3,0x42,0x46,0xDB,0x95,0x42,0x44,0xDB,0x6C,0x46, + 0x0E,0x22,0x12,0x23,0xA2,0x5E,0xE3,0x5E,0x00,0x93,0x9A,0x42,0x02,0xDA,0x17,0x46, + 0x1E,0x46,0x01,0xE0,0x1F,0x46,0x16,0x46,0x16,0x23,0x25,0x46,0xE3,0x5E,0x1A,0x24, + 0x2C,0x5F,0x01,0x94,0xA3,0x42,0x02,0xDA,0x1C,0x46,0x01,0x9D,0x00,0xE0,0x1D,0x46, + 0xA6,0x42,0x29,0xDB,0xBD,0x42,0x27,0xDB,0x01,0x9C,0xD6,0x1A,0xE7,0x1A,0x64,0x46, + 0x64,0x1A,0x45,0x1A,0x66,0x43,0x7D,0x43,0x02,0x94,0xAD,0x1B,0x74,0x46,0x66,0x1A, + 0x00,0x9C,0x7E,0x43,0xE7,0x1A,0x02,0x9C,0x67,0x43,0xF4,0x1B,0x65,0x40,0x00,0x2D, + 0x12,0xDC,0x0C,0x1A,0x00,0x99,0x9D,0x1A,0x73,0x46,0x89,0x1A,0x1B,0x1A,0x4C,0x43, + 0x5D,0x43,0x64,0x1B,0x65,0x46,0x28,0x1A,0x48,0x43,0x01,0x99,0x89,0x1A,0x59,0x43, + 0x40,0x1A,0x44,0x40,0x00,0x2C,0x02,0xDD,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x01,0x20, + 0xFB,0xE7,0x00,0x00,0xF0,0xB5,0x14,0x4A,0x14,0x4F,0x12,0x68,0x11,0x4D,0x13,0x46, + 0x20,0x33,0x1C,0x7C,0x5E,0x7C,0x23,0x46,0x7F,0x78,0xA0,0x32,0xA9,0x6A,0x28,0x6A, + 0x73,0x43,0x14,0x7D,0xFF,0x43,0xBF,0x07,0x03,0xD1,0xD4,0x7D,0xA9,0x6C,0x28,0x6C, + 0x33,0x46,0x00,0x22,0x0A,0xE0,0x0D,0x88,0x06,0x88,0xAD,0x1B,0xA5,0x42,0x01,0xDD, + 0x01,0x20,0xF0,0xBD,0x89,0x1C,0x80,0x1C,0x52,0x1C,0x92,0xB2,0x9A,0x42,0xF2,0xD3, + 0x00,0x20,0xF0,0xBD,0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20,0xF6,0x04,0x00,0x20, + 0xF0,0xB5,0x6F,0x48,0x8F,0xB0,0x00,0x6D,0x08,0x90,0x6E,0x48,0x00,0x68,0x20,0x30, + 0x41,0x7C,0x07,0x91,0x00,0x7C,0x06,0x90,0x00,0x20,0x05,0x90,0x04,0x90,0x06,0x46, + 0x03,0x90,0x69,0x48,0x0D,0x90,0xC0,0x7B,0x0E,0x90,0xA8,0xE0,0x00,0x25,0xA0,0xE0, + 0x70,0x43,0x40,0x19,0x41,0x00,0x0C,0x90,0x08,0x98,0x44,0x5E,0x13,0x20,0xC0,0x43, + 0x84,0x42,0x03,0xDA,0x04,0x98,0x00,0x19,0x04,0x90,0x04,0xE0,0x14,0x2C,0x02,0xDD, + 0x05,0x98,0x00,0x19,0x05,0x90,0x03,0x98,0x00,0x28,0x7E,0xD1,0x0E,0x98,0x32,0x28, + 0x7B,0xD2,0x1E,0x2C,0x79,0xDD,0x00,0x20,0x02,0x90,0x00,0x2E,0x7F,0xD0,0x06,0x98, + 0x40,0x1E,0x0B,0x90,0x86,0x42,0x7A,0xDA,0x00,0x2D,0x78,0xD0,0x07,0x98,0x40,0x1E, + 0x0A,0x90,0x85,0x42,0x73,0xDA,0x07,0x9A,0x70,0x1E,0x50,0x43,0x40,0x19,0x08,0x9A, + 0x40,0x00,0x82,0x18,0x13,0x46,0x20,0x3B,0x1E,0x27,0xDF,0x5F,0xA7,0x42,0x66,0xDA, + 0x08,0x9B,0x18,0x5E,0xA0,0x42,0x62,0xDA,0x02,0x20,0x10,0x5E,0xA0,0x42,0x5E,0xDA, + 0xC9,0x18,0x08,0x46,0x20,0x38,0x1E,0x22,0x82,0x5E,0xA2,0x42,0x57,0xDA,0x07,0x9A, + 0x70,0x1C,0x50,0x43,0x40,0x19,0x40,0x00,0xC2,0x18,0x13,0x46,0x20,0x3B,0x1E,0x27, + 0xDF,0x5F,0xA7,0x42,0x4B,0xDC,0x08,0x9B,0x18,0x5E,0xA0,0x42,0x47,0xDC,0x02,0x20, + 0x10,0x5E,0xA0,0x42,0x43,0xDC,0x02,0x20,0x08,0x5E,0xA0,0x42,0x3F,0xDC,0x37,0xA0, + 0x00,0x68,0x01,0x27,0x09,0x90,0x01,0x90,0x00,0x20,0x00,0x90,0x03,0x21,0xFB,0xF7, + 0x59,0xF9,0x01,0xAA,0x10,0x5C,0x51,0x5C,0x78,0x43,0x79,0x43,0x80,0x19,0x49,0x19, + 0x40,0xB2,0x49,0xB2,0x00,0x28,0x15,0xDB,0x0B,0x9A,0x90,0x42,0x12,0xDC,0x00,0x29, + 0x10,0xDB,0x0A,0x9A,0x91,0x42,0x0D,0xDC,0x07,0x9A,0x50,0x43,0x40,0x18,0x0C,0x99, + 0x00,0xB2,0x81,0x42,0x06,0xD0,0x08,0x99,0x40,0x00,0x08,0x5A,0x02,0x99,0x40,0x18, + 0x00,0xB2,0x02,0x90,0x00,0x98,0x40,0x1C,0xC0,0xB2,0x00,0x90,0x09,0x28,0xD5,0xD3, + 0x7F,0x1C,0xFF,0xB2,0x02,0x2F,0x03,0xD8,0x00,0xE0,0x08,0xE0,0x09,0x98,0xCA,0xE7, + 0x02,0x98,0x00,0x19,0x00,0xB2,0x0A,0x28,0x01,0xDA,0x01,0x20,0x03,0x90,0x6D,0x1C, + 0xED,0xB2,0x07,0x98,0x85,0x42,0x00,0xD2,0x5A,0xE7,0x76,0x1C,0xF6,0xB2,0x06,0x98, + 0x86,0x42,0x00,0xD2,0x52,0xE7,0x04,0x99,0x05,0x98,0x40,0x18,0x10,0x49,0x88,0x42, + 0x07,0xDA,0x0D,0x98,0x00,0x21,0xC1,0x73,0x0D,0x98,0x01,0x21,0x81,0x71,0x0F,0xB0, + 0xF0,0xBD,0x03,0x98,0x00,0x28,0x03,0xD0,0x0D,0x98,0x64,0x21,0xC1,0x73,0xF6,0xE7, + 0x0E,0x98,0x00,0x28,0xF3,0xD0,0x0D,0x99,0x40,0x1E,0xC8,0x73,0xEF,0xE7,0x00,0x00, + 0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20,0xB8,0x04,0x00,0x20,0xFF,0x00,0x01,0x00, + 0x78,0xEC,0xFF,0xFF,0x10,0xB5,0xFF,0xF7,0xF9,0xFD,0x0B,0x4C,0x20,0x78,0x10,0x28, + 0x04,0xD0,0x11,0x28,0xFA,0xD1,0xFF,0xF7,0xC7,0xF8,0xF7,0xE7,0x00,0xF0,0x02,0xFD, + 0x00,0xF0,0x52,0xFB,0x00,0xF0,0x76,0xFD,0x00,0xF0,0x4E,0xFC,0x00,0xF0,0x5C,0xFB, + 0x00,0xF0,0x1C,0xFD,0xEA,0xE7,0x00,0x00,0x98,0x04,0x00,0x20,0x03,0x68,0x0B,0x60, + 0x01,0x68,0xD2,0x1C,0x89,0x18,0x89,0x08,0x89,0x00,0x01,0x60,0x70,0x47,0xF3,0xB5, + 0x81,0xB0,0x02,0x98,0x00,0x27,0x40,0x1E,0x00,0x90,0x29,0xE0,0x54,0x20,0x01,0x99, + 0x78,0x43,0x46,0x18,0x30,0x7C,0x01,0x07,0x09,0x0F,0x01,0x29,0x1E,0xD9,0x00,0x09, + 0x1C,0xD1,0x7D,0x1C,0x17,0xE0,0x54,0x20,0x01,0x99,0x68,0x43,0x44,0x18,0x20,0x7C, + 0x01,0x07,0x09,0x0F,0x01,0x29,0x0D,0xD9,0x00,0x09,0x0B,0xD1,0x23,0x68,0x62,0x6A, + 0x31,0x68,0x70,0x6A,0xFF,0xF7,0x34,0xFE,0x00,0x28,0x03,0xD0,0x30,0x68,0x21,0x68, + 0x31,0x60,0x20,0x60,0x6D,0x1C,0x02,0x98,0x85,0x42,0xE4,0xD3,0x00,0x98,0x7F,0x1C, + 0x87,0x42,0xD3,0xD3,0xFE,0xBD,0x00,0x00,0x10,0xB5,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x54,0x22,0x20,0x46,0xC0,0x30,0x41,0x69,0x00,0x69,0x89,0x78,0x51,0x43,0xFB,0xF7, + 0xDA,0xF8,0x02,0x48,0xA0,0x60,0x00,0x20,0x10,0xBD,0x00,0x00,0x81,0x4F,0x00,0x00, + 0xF7,0xB5,0x90,0xB0,0x10,0x98,0x0C,0x25,0xC0,0x30,0x01,0x69,0x07,0x91,0x44,0x69, + 0xFF,0x22,0xA0,0x78,0x06,0x90,0x0A,0x21,0x03,0xA8,0xFB,0xF7,0xBD,0xF8,0x00,0x20, + 0x02,0x90,0x0D,0xE0,0x54,0x21,0x07,0x9A,0x41,0x43,0x89,0x18,0x09,0x7C,0x09,0x07, + 0x05,0xD0,0x02,0x9A,0x03,0xA9,0x88,0x54,0x02,0x99,0x49,0x1C,0x02,0x91,0x40,0x1C, + 0x06,0x99,0x88,0x42,0xEE,0xDB,0x02,0x99,0x12,0x98,0x88,0x42,0x00,0xDC,0x08,0x46, + 0x46,0x00,0x46,0x43,0x77,0x19,0x0A,0x90,0x00,0xF0,0x68,0xFA,0x08,0x90,0x38,0x46, + 0x00,0xF0,0x82,0xFA,0x39,0x46,0x08,0x98,0xFB,0xF7,0x9D,0xF8,0x08,0x98,0xFF,0x22, + 0x30,0x18,0x29,0x46,0x09,0x90,0xFB,0xF7,0x8F,0xF8,0x12,0x99,0x02,0x98,0x48,0x43, + 0x0F,0x90,0x00,0x28,0x77,0xD0,0x08,0x46,0x02,0x99,0x88,0x42,0x00,0xDC,0x08,0x46, + 0xC0,0xB2,0x0B,0x90,0x70,0x20,0x00,0x5B,0x40,0x34,0x00,0x90,0xA0,0x7D,0x00,0x27, + 0x0E,0x90,0x85,0xE0,0x00,0x26,0x7E,0xE0,0x02,0x98,0x5F,0x4D,0x87,0x42,0x73,0xDA, + 0x12,0x98,0x86,0x42,0x70,0xDA,0x03,0xA8,0xC0,0x5D,0x54,0x21,0x48,0x43,0x07,0x99, + 0x44,0x18,0x11,0x98,0x31,0x01,0x08,0x18,0x00,0x68,0x01,0x90,0x69,0x46,0x06,0x20, + 0x08,0x5E,0x0C,0x90,0x04,0x20,0x08,0x5E,0x23,0x46,0x0D,0x90,0x40,0x33,0x01,0x93, + 0x02,0x21,0x00,0x20,0x59,0x5E,0x18,0x5E,0x0C,0x9B,0x0D,0x9A,0x00,0xF0,0x03,0xFD, + 0x05,0x46,0x02,0x20,0x20,0x5E,0x01,0x9B,0x84,0x46,0x02,0x21,0x00,0x20,0x00,0x22, + 0x59,0x5E,0x18,0x5E,0xA2,0x5E,0x63,0x46,0x00,0xF0,0xF5,0xFC,0x01,0x90,0x02,0x21, + 0x00,0x20,0x61,0x5E,0x20,0x5E,0x0C,0x9B,0x0D,0x9A,0x00,0xF0,0xEC,0xFC,0x00,0x99, + 0x8D,0x42,0x39,0xDB,0x88,0x42,0x37,0xDB,0x62,0x7C,0x01,0x21,0xD2,0x09,0x07,0xD1, + 0x22,0x7C,0x0E,0x9B,0x12,0x07,0x12,0x0F,0x5A,0x43,0x32,0x2A,0x00,0xDB,0x00,0x21, + 0x01,0x9A,0x00,0x2A,0x26,0xD0,0x00,0x29,0x24,0xD1,0x01,0x99,0x2A,0x11,0x8A,0x42, + 0x12,0xDC,0x40,0x43,0x49,0x43,0x41,0x1A,0x28,0x46,0x68,0x43,0x08,0x1A,0x01,0x99, + 0xC0,0x01,0x69,0x43,0xFA,0xF7,0xE4,0xFF,0x80,0x38,0x00,0x28,0x04,0xDD,0x80,0x28, + 0x03,0xDB,0x80,0x20,0x01,0xE0,0x1F,0xE0,0x00,0x20,0x01,0x9A,0x00,0x99,0x80,0x11, + 0x89,0x18,0x41,0x43,0x00,0x98,0x08,0x18,0x0E,0x99,0x10,0x29,0x00,0xDD,0x40,0x00, + 0x85,0x42,0x01,0xDD,0x24,0x4D,0x6D,0x1E,0x0B,0x98,0x78,0x43,0x80,0x19,0x41,0x00, + 0x08,0x98,0x76,0x1C,0x45,0x52,0x0B,0x98,0x86,0x42,0x00,0xDA,0x7C,0xE7,0x7F,0x1C, + 0x0B,0x98,0x87,0x42,0x00,0xDA,0x75,0xE7,0x0F,0x98,0x01,0x28,0x0E,0xD0,0x00,0x28, + 0x09,0xD0,0x00,0x23,0xDB,0x43,0x12,0x9A,0x01,0x93,0x00,0x92,0x08,0xA8,0x07,0xC8, + 0x02,0x9B,0x00,0xF0,0x2B,0xF8,0x00,0x20,0x03,0xAA,0x11,0xE0,0x08,0x98,0x01,0x88, + 0x11,0x48,0x40,0x1E,0x81,0x42,0xF6,0xD2,0x09,0x99,0x00,0x20,0x08,0x70,0xF2,0xE7, + 0x09,0x99,0x09,0x5C,0xFF,0x29,0x02,0xD0,0x53,0x5C,0x09,0x99,0x0B,0x54,0x40,0x1C, + 0x12,0x99,0x88,0x42,0xF4,0xDB,0x0A,0x46,0x09,0x9B,0x11,0x99,0x10,0x98,0x00,0xF0, + 0xAD,0xF8,0x08,0x98,0x00,0xF0,0xC8,0xF9,0x06,0x99,0x07,0x98,0xFF,0xF7,0xA7,0xFE, + 0x06,0x98,0x13,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0x7F,0x00,0x00,0xFF,0xB5,0x81,0xB0, + 0x04,0x46,0x15,0x46,0x00,0xF0,0x7A,0xF9,0x06,0x46,0xB4,0x20,0x00,0xF0,0x94,0xF9, + 0x00,0x20,0x2A,0x46,0x6A,0x43,0x0C,0xE0,0x41,0x00,0x67,0x5A,0x17,0x4B,0x9F,0x42, + 0x01,0xD3,0x5B,0x1C,0x63,0x52,0x15,0x4B,0x67,0x5A,0x5B,0x1C,0xDB,0x1B,0x63,0x52, + 0x40,0x1C,0x82,0x42,0xF0,0xD8,0x2A,0x46,0x21,0x46,0x30,0x46,0x01,0xF0,0x2E,0xF9, + 0xFF,0x22,0x0A,0x99,0x02,0x98,0xFA,0xF7,0x8F,0xFF,0x00,0x23,0x0D,0xE0,0xF0,0x5C, + 0x04,0x99,0x88,0x42,0x08,0xD2,0xF1,0x56,0x69,0x43,0xC9,0x18,0x49,0x00,0x61,0x5A, + 0x00,0x29,0x01,0xD0,0x02,0x99,0xC8,0x54,0x5B,0x1C,0x0A,0x98,0x83,0x42,0xEE,0xD3, + 0x30,0x46,0x00,0xF0,0x81,0xF9,0x05,0xB0,0xF0,0xBD,0x00,0x00,0xFE,0x7F,0x00,0x00, + 0xF8,0xB5,0x8E,0x46,0x01,0x68,0x00,0x91,0x24,0x21,0x6C,0x46,0x00,0x22,0x41,0x5E, + 0xA2,0x5E,0x02,0x23,0x8A,0x1A,0x26,0x21,0x41,0x5E,0xE3,0x5E,0xC9,0x1A,0x16,0x23, + 0xC3,0x5E,0x9B,0x18,0x18,0x22,0x82,0x5E,0x54,0x18,0x19,0x46,0x22,0x46,0x59,0x43, + 0x62,0x43,0x8F,0x18,0x41,0x7C,0x00,0x91,0xCD,0x09,0x71,0x46,0x40,0x31,0x46,0x7D, + 0x8C,0x46,0x71,0x46,0x42,0x8B,0x76,0x43,0x20,0x31,0xBE,0x42,0x15,0xDD,0x00,0x2D, + 0x07,0xD1,0x67,0x46,0xBF,0x7D,0x18,0x4E,0xBA,0x18,0xB2,0x42,0x00,0xDC,0x16,0x46, + 0x32,0x46,0x89,0x78,0x0A,0x26,0x71,0x43,0x91,0x42,0x03,0xDA,0x01,0x25,0x00,0x23, + 0x1C,0x46,0x1A,0x46,0x00,0x21,0x01,0x77,0x13,0xE0,0xB6,0x00,0xBE,0x42,0x01,0xDA, + 0xCE,0x79,0x01,0xE0,0x06,0x7F,0x76,0x1C,0x06,0x77,0xC9,0x79,0xF6,0xB2,0x8E,0x42, + 0x07,0xD1,0x00,0x25,0x61,0x46,0x49,0x7D,0x2A,0x46,0x2B,0x46,0x2C,0x46,0x41,0x75, + 0xE8,0xE7,0x00,0x99,0x49,0x06,0x49,0x0E,0xED,0x01,0x29,0x43,0x41,0x74,0x42,0x83, + 0xC3,0x82,0x04,0x83,0xF8,0xBD,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xB5,0x85,0xB0, + 0xC0,0x30,0x03,0x90,0x04,0x69,0x40,0x69,0x00,0x90,0x80,0x78,0x01,0x90,0x00,0x20, + 0x84,0x46,0x01,0x46,0x02,0x90,0x3F,0xE0,0x08,0x98,0x47,0x5C,0xFF,0x2F,0x40,0xD0, + 0x54,0x20,0x78,0x43,0x00,0x19,0x42,0x7B,0x0E,0x01,0x53,0x00,0xD5,0x18,0x06,0x9B, + 0xF3,0x18,0x5E,0x7B,0xAA,0x19,0x92,0x08,0x04,0x92,0xC5,0x7A,0x6E,0x00,0xAD,0x19, + 0xDE,0x7A,0xAA,0x19,0x45,0x6A,0x85,0x62,0x05,0x68,0x92,0x08,0x45,0x62,0x96,0x46, + 0x45,0x7B,0x85,0x74,0x1A,0x46,0x1B,0x68,0x96,0x68,0x55,0x68,0xD2,0x68,0x68,0xC0, + 0x0C,0x38,0xC2,0x60,0x04,0x9A,0x42,0x73,0x72,0x46,0xC2,0x72,0x02,0x7C,0x12,0x07, + 0x12,0x0F,0x02,0x74,0x0A,0x2A,0x06,0xD2,0x04,0x23,0xDA,0x41,0x9B,0x06,0xD2,0x18, + 0x1C,0x23,0xDA,0x41,0x02,0x74,0x01,0x20,0xB8,0x40,0x62,0x46,0x10,0x43,0x84,0x46, + 0x02,0x98,0x40,0x1C,0x02,0x90,0x49,0x1C,0x07,0x98,0x81,0x42,0xBC,0xD3,0x00,0x21, + 0x68,0xE0,0x01,0x98,0xC2,0xB2,0x00,0x20,0x07,0xE0,0x54,0x23,0x43,0x43,0x1B,0x19, + 0x1B,0x7C,0x1B,0x07,0x03,0xD0,0x40,0x1C,0xC0,0xB2,0x90,0x42,0xF5,0xD3,0xFF,0x23, + 0x90,0x42,0x00,0xD2,0x03,0x46,0x9E,0x46,0xFF,0x2B,0xE4,0xD0,0x18,0x46,0x54,0x22, + 0x50,0x43,0x00,0x19,0x42,0x7C,0x80,0x23,0x1A,0x43,0x42,0x74,0x04,0x92,0x00,0x9A, + 0x40,0x32,0x12,0x7D,0x42,0x75,0x00,0x9A,0x20,0x32,0x93,0x7A,0xD2,0x7A,0x9A,0x18, + 0x52,0x08,0x02,0x75,0x06,0x9A,0x0B,0x01,0x9A,0x18,0x13,0x46,0xE8,0xCB,0xE8,0xC0, + 0x10,0x38,0x15,0x68,0x45,0x62,0x55,0x7B,0x85,0x74,0x15,0x68,0x05,0x62,0x0C,0xCA, + 0x43,0x64,0x02,0x64,0x02,0x7C,0x73,0x46,0x12,0x09,0x12,0x01,0x52,0x1C,0x02,0x74, + 0x04,0x9A,0x5B,0x06,0xD2,0x09,0xD2,0x01,0x5B,0x0E,0x1A,0x43,0x42,0x74,0x72,0x46, + 0x01,0x20,0x90,0x40,0x62,0x46,0x10,0x43,0x84,0x46,0xAC,0xE7,0x01,0x20,0x88,0x40, + 0x62,0x46,0x10,0x42,0x15,0xD1,0x54,0x20,0x48,0x43,0x00,0x19,0x02,0x7C,0x13,0x07, + 0x0F,0xD0,0x13,0x07,0x12,0x09,0x52,0x1C,0x1B,0x0F,0x12,0x01,0x13,0x43,0x03,0x74, + 0x42,0x7C,0xD2,0x09,0x05,0xD1,0x43,0x6A,0x83,0x62,0x03,0x68,0x43,0x62,0x02,0x6C, + 0x02,0x60,0x49,0x1C,0x01,0x98,0x81,0x42,0xE0,0xDB,0x00,0x25,0x13,0xE0,0x54,0x20, + 0x68,0x43,0x00,0x19,0x01,0x7C,0x09,0x07,0x09,0x0F,0x01,0x29,0x0A,0xD9,0x03,0x99, + 0x49,0x69,0x89,0x68,0x09,0x06,0x02,0xD5,0x02,0x99,0x01,0x29,0x08,0xD0,0x00,0x99, + 0xFF,0xF7,0xCE,0xFE,0x6D,0x1C,0x01,0x98,0x85,0x42,0xE8,0xDB,0x09,0xB0,0xF0,0xBD, + 0x41,0x7C,0x49,0x06,0x49,0x0E,0x41,0x74,0xF4,0xE7,0x00,0x00,0x09,0x48,0x01,0x21, + 0x00,0x68,0xC1,0x70,0x82,0x78,0x91,0x00,0x09,0x18,0x09,0x1D,0x00,0x2A,0x04,0xD0, + 0x0A,0x1F,0x13,0x88,0x52,0x88,0x9A,0x18,0x0A,0x80,0x09,0x88,0x40,0x30,0x08,0x18, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x02,0x48,0x00,0x21,0x00,0x68,0xC1,0x70, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x10,0xB5,0x0D,0x49,0x00,0x22,0x09,0x68, + 0x00,0x28,0xCA,0x70,0x0B,0xD0,0x0B,0x4A,0xC0,0x1C,0x10,0x40,0x8A,0x78,0x0B,0x88, + 0x92,0x00,0x52,0x18,0x94,0x88,0x1B,0x1B,0x9B,0xB2,0x98,0x42,0x01,0xD9,0x00,0x20, + 0x10,0xBD,0xD0,0x80,0x88,0x78,0x40,0x1C,0x88,0x70,0x01,0x20,0x10,0xBD,0x00,0x00, + 0x94,0x21,0x00,0x20,0xFC,0xFF,0x00,0x00,0x30,0xB5,0x08,0x49,0x09,0x68,0x8B,0x78, + 0x0C,0x46,0x9A,0x00,0x52,0x18,0x15,0x88,0x40,0x34,0x2C,0x19,0x84,0x42,0x03,0xD1, + 0x5B,0x1E,0x8B,0x70,0x50,0x88,0x30,0xBD,0x00,0x20,0x30,0xBD,0x94,0x21,0x00,0x20, + 0x04,0x4A,0x40,0x39,0x10,0x60,0x01,0x80,0x00,0x21,0x81,0x70,0xC1,0x70,0x81,0x80, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x10,0xB5,0xFA,0xF7,0x69,0xFE,0x00,0x28, + 0x05,0xDA,0xFC,0xF7,0xC1,0xF9,0x03,0x48,0x01,0x21,0x81,0x71,0x10,0xBD,0x00,0xF0, + 0xF4,0xFD,0x10,0xBD,0xB8,0x04,0x00,0x20,0xF8,0xB5,0x75,0x4F,0x24,0x20,0x78,0x70, + 0xFD,0xF7,0x9A,0xFA,0x3C,0x46,0x20,0x34,0x60,0x7B,0x00,0x25,0x40,0x06,0x00,0x28, + 0x10,0xD0,0x01,0xE0,0x00,0xF0,0x7E,0xFA,0xFE,0xF7,0xD8,0xFF,0x00,0x28,0xF9,0xD1, + 0x60,0x7B,0xC1,0x09,0x40,0x06,0x40,0x0E,0xFC,0xF7,0x84,0xFD,0x65,0x73,0x01,0x20, + 0xA0,0x71,0xF8,0xBD,0x78,0x7A,0x67,0x4E,0x01,0x02,0x30,0x68,0x3A,0x7A,0xFF,0x30, + 0x11,0x43,0x41,0x30,0x42,0x7B,0x03,0x7B,0x10,0x02,0x18,0x43,0x81,0x42,0x12,0xD9, + 0xFF,0xF7,0x48,0xFB,0x00,0x28,0x0E,0xD0,0x30,0x68,0xFF,0x30,0x41,0x30,0x41,0x7B, + 0x02,0x7B,0x09,0x02,0x11,0x43,0x0A,0x39,0x39,0x72,0x09,0x0A,0x79,0x72,0x00,0x7C, + 0x00,0xF0,0x26,0xFD,0x1E,0xE0,0x00,0x21,0x02,0x20,0xFD,0xF7,0xD1,0xFA,0x39,0x1D, + 0xFA,0xF7,0x9E,0xFD,0x78,0x7E,0x39,0x7E,0x00,0x02,0x08,0x43,0x30,0x68,0x16,0xD0, + 0xFF,0x30,0x41,0x30,0x00,0x7C,0x00,0xF0,0x13,0xFD,0x01,0x22,0x21,0x21,0x08,0x20, + 0x01,0xF0,0x74,0xFB,0x78,0x7E,0x39,0x7E,0x00,0x02,0x08,0x43,0x40,0x1E,0x38,0x76, + 0x00,0x0A,0x78,0x76,0x00,0x21,0x01,0x20,0xFD,0xF7,0xB2,0xFA,0xF8,0xBD,0xFF,0x21, + 0x9C,0x31,0x09,0x5C,0x00,0x29,0x18,0xD0,0xA1,0x7B,0x00,0x29,0x15,0xD1,0x79,0x7A, + 0x3A,0x7A,0x09,0x02,0x11,0x43,0x01,0xD0,0x3D,0x75,0x0D,0xE0,0x16,0x21,0x79,0x56, + 0x05,0x29,0x02,0xDD,0x39,0x7D,0x49,0x1C,0x05,0xE0,0x4A,0x1D,0x05,0xDA,0x39,0x7D, + 0x00,0x29,0x01,0xD0,0x49,0x1E,0x39,0x75,0xBD,0x75,0xB9,0x7F,0x3D,0x46,0x00,0x29, + 0x0C,0xD1,0x61,0x78,0x00,0x29,0x09,0xD0,0x01,0x46,0xFF,0x31,0x41,0x31,0xCA,0x7B, + 0x8B,0x7B,0x11,0x02,0x19,0x43,0x29,0x72,0x09,0x0A,0x69,0x72,0x69,0x7A,0x2A,0x7A, + 0x09,0x02,0x11,0x43,0x04,0xD1,0xFF,0x30,0x41,0x30,0x00,0x7C,0x00,0xF0,0xC8,0xFC, + 0x68,0x7A,0x29,0x7A,0x02,0x02,0x30,0x68,0x0A,0x43,0xFF,0x30,0x41,0x30,0x41,0x7B, + 0x03,0x7B,0x09,0x02,0x19,0x43,0x8A,0x42,0x02,0xD1,0x40,0x7C,0x00,0xF0,0xB8,0xFC, + 0x30,0x68,0xFF,0x30,0x81,0x30,0xC0,0x7E,0x00,0x28,0x08,0xD0,0xA0,0x7B,0x00,0x28, + 0x05,0xD1,0x28,0x7D,0x00,0x28,0x02,0xD0,0x08,0x20,0xFC,0xF7,0x1D,0xF9,0xE8,0x7F, + 0x21,0x24,0x00,0x28,0x06,0xD1,0x30,0x68,0xFF,0x30,0x41,0x30,0x80,0x7D,0x00,0x28, + 0x00,0xD0,0x22,0x24,0x22,0x2C,0x02,0xD1,0x01,0x20,0xFC,0xF7,0x7B,0xFE,0x02,0x20, + 0xFC,0xF7,0x0A,0xF9,0x01,0x22,0x21,0x46,0x0A,0x20,0x01,0xF0,0xF7,0xFA,0x06,0x46, + 0x22,0x2C,0x02,0xD1,0x00,0x20,0xFC,0xF7,0x6D,0xFE,0x30,0x07,0x04,0xD4,0x01,0x22, + 0x21,0x21,0x08,0x20,0x01,0xF0,0xEA,0xFA,0xE8,0x7F,0x40,0x1E,0xFE,0x28,0x00,0xD2, + 0xE8,0x77,0x00,0x21,0x01,0x20,0xFD,0xF7,0x2B,0xFA,0x00,0xF0,0x07,0xFD,0xF8,0xBD, + 0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0xF0,0xB5,0xBD,0xB0,0x00,0x20,0x4D,0x49, + 0x00,0x90,0x0A,0x79,0xCB,0x78,0x11,0x02,0x4B,0x4A,0x01,0x20,0x12,0x7E,0x19,0x43, + 0x91,0x42,0x00,0xD8,0x00,0x20,0x49,0x4C,0x49,0x4E,0x20,0x82,0x23,0x21,0x71,0x70, + 0x30,0x1D,0xFA,0xF7,0xD4,0xFC,0x47,0x4A,0x11,0x68,0x88,0x42,0x04,0xD9,0x41,0x1A, + 0xC9,0x02,0x01,0x23,0xDB,0x03,0x03,0xE0,0x41,0x1A,0xC9,0x02,0x0F,0x23,0xDB,0x02, + 0xC9,0x18,0x09,0x0C,0x61,0x82,0x10,0x60,0x68,0x46,0xFA,0xF7,0xBB,0xFD,0x3D,0x48, + 0x71,0x7F,0x00,0x1D,0x08,0x22,0xF0,0x29,0x81,0x68,0x01,0xD1,0x11,0x43,0x00,0xE0, + 0x91,0x43,0x81,0x60,0x38,0x48,0x01,0xA9,0x40,0x68,0x00,0xF0,0xCE,0xFF,0x04,0x1E, + 0x00,0xDA,0x00,0x24,0x32,0x4D,0xFF,0x21,0x20,0x35,0xE8,0x78,0x9B,0x31,0x00,0x09, + 0x00,0x01,0xC0,0xB2,0x20,0x43,0xE8,0x70,0x30,0x48,0x00,0x68,0x09,0x5C,0x02,0x29, + 0x11,0xD1,0x71,0x7C,0x00,0x29,0x0C,0xD1,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A, + 0x08,0x02,0x10,0x43,0x01,0xF0,0x60,0xFA,0x28,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7, + 0x4D,0xFD,0x00,0x20,0xF0,0x70,0x70,0x7F,0xFF,0x28,0x0A,0xD1,0x30,0x7C,0x00,0x28, + 0x17,0xD1,0x30,0x7D,0xE1,0xB2,0x02,0x07,0x12,0x0F,0x01,0xA8,0xFE,0xF7,0x82,0xFA, + 0x0F,0xE0,0xF0,0x28,0x11,0xD1,0x1B,0x4F,0x13,0x20,0x44,0x37,0x38,0x56,0x80,0x1C, + 0x07,0xD0,0x01,0x20,0xE8,0x70,0xF8,0x7C,0xFE,0xF7,0x1E,0xFA,0xFE,0x20,0xF8,0x74, + 0x03,0xE0,0xE1,0xB2,0x01,0xA8,0xFE,0xF7,0x8F,0xFA,0x6B,0x46,0x18,0x78,0x00,0x28, + 0x08,0xD1,0xB0,0x7E,0x00,0x28,0x05,0xD1,0x30,0x7C,0x00,0x28,0x02,0xD1,0x28,0x79, + 0xFF,0x28,0x01,0xD0,0x00,0x20,0x07,0xE0,0x70,0x7A,0x31,0x7A,0x00,0x02,0x08,0x43, + 0x0B,0x49,0x88,0x42,0x03,0xD2,0x40,0x1C,0x30,0x72,0x00,0x0A,0x70,0x72,0x3D,0xB0, + 0xF0,0xBD,0x00,0x00,0x60,0x03,0x00,0x20,0x16,0x05,0x00,0x20,0x60,0x1F,0x00,0x20, + 0x98,0x04,0x00,0x20,0x14,0x06,0x00,0x20,0x58,0x07,0x00,0x20,0x10,0x06,0x00,0x20, + 0xFF,0x7F,0x00,0x00,0x70,0xB5,0x0F,0x4D,0x21,0x20,0x68,0x70,0x0E,0x48,0x2C,0x46, + 0x80,0x78,0x20,0x34,0x60,0x71,0xA0,0x79,0x00,0x28,0x0F,0xD0,0xFA,0xF7,0x20,0xFD, + 0x00,0x20,0xA0,0x71,0x01,0x20,0x00,0xF0,0x8D,0xFC,0x00,0x21,0x02,0x20,0xFD,0xF7, + 0x5F,0xF9,0x29,0x1D,0xFA,0xF7,0x2C,0xFC,0x00,0xF0,0x6C,0xFC,0x00,0x20,0x00,0xF0, + 0x81,0xFC,0x70,0xBD,0x98,0x04,0x00,0x20,0xD6,0x04,0x00,0x20,0x70,0xB5,0x25,0x4D, + 0x26,0x20,0x68,0x70,0x28,0x7C,0x2C,0x46,0x20,0x34,0x00,0x28,0x10,0xD0,0x36,0x21, + 0x21,0x48,0xFA,0xF7,0x00,0xFC,0xFE,0xF7,0x19,0xFE,0x00,0x28,0x01,0xD0,0x00,0xF0, + 0xB9,0xF8,0x00,0xF0,0x0D,0xFB,0x00,0x28,0x1A,0xD0,0xFF,0x20,0x60,0x72,0x17,0xE0, + 0xFE,0xF7,0x0C,0xFE,0x00,0x28,0x13,0xD0,0x18,0x48,0x00,0x68,0xFF,0x30,0x81,0x30, + 0xC0,0x7E,0x00,0x28,0x02,0xD0,0xA0,0x7B,0x00,0x28,0x09,0xD0,0x00,0xF0,0xA2,0xF8, + 0x00,0xF0,0x05,0xFC,0x00,0x28,0x03,0xD0,0x00,0xF0,0xF2,0xFA,0x00,0xF0,0xFC,0xFB, + 0xFB,0xF7,0xFA,0xFF,0x00,0xF0,0x2E,0xFC,0x0A,0x48,0x0C,0x30,0xFA,0xF7,0xDF,0xFB, + 0x00,0x68,0x0B,0x49,0x88,0x42,0x02,0xD0,0x02,0x20,0xFE,0xF7,0x53,0xF9,0xE8,0x7A, + 0xA9,0x7A,0x00,0x02,0x08,0x43,0xFF,0x28,0x03,0xD2,0x40,0x1C,0xA8,0x72,0x00,0x0A, + 0xE8,0x72,0x70,0xBD,0x98,0x04,0x00,0x20,0x7A,0x01,0x00,0x20,0x10,0x06,0x00,0x20, + 0x5A,0xA5,0xAC,0xCA,0x01,0x48,0x00,0x68,0xC0,0x7E,0x70,0x47,0x10,0x06,0x00,0x20, + 0xFF,0xB5,0xFF,0x31,0x41,0x31,0x4D,0x68,0x00,0x21,0x81,0xB0,0x07,0x46,0x1E,0x46, + 0x0C,0x46,0xE0,0x00,0x40,0x19,0x82,0x8A,0x92,0x0B,0xB2,0x42,0x05,0xD1,0x83,0x69, + 0x29,0x46,0x38,0x46,0x03,0x9A,0x98,0x47,0x01,0x46,0x64,0x1C,0x15,0x2C,0xF0,0xDB, + 0x08,0x46,0x05,0xB0,0xF0,0xBD,0x00,0x00,0x10,0xB5,0x04,0x46,0x08,0x4B,0x4B,0x22, + 0x02,0x21,0x00,0xF0,0x19,0xF8,0xFF,0x34,0x41,0x34,0x64,0x68,0xFF,0xF7,0x4E,0xFD, + 0xC0,0x34,0xE0,0x60,0x80,0x20,0xFF,0xF7,0x67,0xFD,0x00,0x20,0x10,0xBD,0x00,0x00, + 0xE1,0x5A,0x00,0x00,0x10,0xB5,0x03,0x4B,0x3C,0x22,0x02,0x21,0x00,0xF0,0x04,0xF8, + 0x00,0x20,0x10,0xBD,0xF5,0x5A,0x00,0x00,0x30,0xB5,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x00,0x20,0xC5,0x00,0x2D,0x19,0xAD,0x69,0x00,0x2D,0x05,0xD0,0x15,0x28,0x02,0xD0, + 0x40,0x1C,0x15,0x28,0xF5,0xDB,0x30,0xBD,0xC0,0x00,0x00,0x19,0x84,0x8A,0x89,0x03, + 0xA4,0x04,0xA4,0x0C,0x0C,0x43,0xA1,0x0B,0x89,0x03,0x92,0x04,0x92,0x0C,0x11,0x43, + 0x81,0x82,0x83,0x61,0x30,0xBD,0x10,0xB5,0x84,0x1A,0x00,0x2C,0x00,0xDC,0x14,0x1A, + 0xC8,0x1A,0xA2,0xB2,0x00,0x28,0x00,0xDC,0x58,0x1A,0x80,0xB2,0x52,0x43,0x41,0x00, + 0x91,0x42,0x01,0xD3,0x80,0xB2,0x10,0xBD,0x40,0x43,0x80,0x18,0x00,0xF0,0x62,0xFD, + 0x10,0xBD,0x00,0x00,0x70,0xB5,0x0B,0x4C,0x36,0x20,0xE5,0x79,0x0A,0x49,0x68,0x43, + 0x41,0x18,0x36,0x22,0x09,0x48,0xFA,0xF7,0x0F,0xFB,0x60,0x7A,0xFF,0x28,0x00,0xD0, + 0x65,0x72,0x6D,0x1C,0x08,0x2D,0x02,0xD3,0x00,0x20,0xE0,0x71,0x70,0xBD,0xE5,0x71, + 0x70,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0xB0,0x01,0x00,0x20,0x7A,0x01,0x00,0x20, + 0x10,0xB5,0xD4,0x23,0x5B,0x58,0x5B,0x7D,0x5B,0x08,0xFB,0xF7,0xBC,0xFF,0x00,0x20, + 0x10,0xBD,0x00,0x00,0xF8,0xB5,0xC0,0x31,0x49,0x69,0x00,0x91,0x00,0x27,0x15,0x21, + 0x14,0x23,0x41,0x56,0xC3,0x56,0x3C,0x46,0x59,0x43,0x27,0x23,0xBC,0x46,0x3E,0x46, + 0x3D,0x46,0xDB,0x43,0x02,0x68,0x0C,0xE0,0x00,0x20,0x10,0x5E,0x28,0x28,0x02,0xDD, + 0xC7,0x19,0x76,0x1C,0x03,0xE0,0x98,0x42,0x01,0xDA,0x04,0x19,0x6D,0x1C,0x49,0x1E, + 0x92,0x1C,0x00,0x29,0xF0,0xD1,0x00,0x2D,0x04,0xDD,0x29,0x46,0x20,0x46,0xFA,0xF7, + 0xB7,0xFA,0x84,0x46,0x12,0x48,0x84,0x42,0x05,0xDA,0x00,0x2C,0x00,0xDC,0x64,0x42, + 0x64,0x37,0xBC,0x42,0x0C,0xDC,0x4F,0x20,0xC0,0x43,0x84,0x45,0x01,0xDA,0x00,0x2E, + 0x06,0xD0,0x14,0x2D,0x0F,0xDD,0x84,0x45,0x0D,0xDA,0x0A,0x36,0xAE,0x42,0x0A,0xDA, + 0x00,0x98,0xFF,0x21,0x40,0x30,0x42,0x7C,0x53,0x1C,0xFF,0x2B,0x00,0xD2,0x51,0x1C, + 0x41,0x74,0x00,0x20,0xF8,0xBD,0x00,0x98,0x00,0x21,0x40,0x30,0xF8,0xE7,0x00,0x00, + 0x0C,0xFE,0xFF,0xFF,0x70,0x47,0x70,0x47,0xA5,0x20,0x70,0x47,0x00,0x20,0x70,0x47, + 0x70,0x47,0x00,0x00,0xF8,0xB5,0x5B,0x4E,0x5B,0x4B,0xF2,0x78,0xB0,0x78,0x1B,0x68, + 0x11,0x02,0x41,0x18,0x5C,0x7E,0x8D,0xB2,0x1B,0x7E,0x71,0x89,0x24,0x02,0x1C,0x43, + 0x0B,0x1B,0xDC,0xB2,0x73,0x78,0x00,0x2B,0x09,0xD0,0x0B,0x0A,0x33,0x71,0x71,0x71, + 0xB0,0x71,0xF2,0x71,0x30,0x1D,0xF0,0x60,0x00,0x1D,0x70,0x61,0x58,0xE0,0x4D,0x49, + 0x00,0x2C,0x49,0x69,0x6C,0xD1,0x4D,0x4F,0x31,0x61,0x39,0x46,0x20,0x31,0x03,0x46, + 0xFA,0xF7,0x0A,0xFB,0x0D,0x08,0x0F,0x11,0x16,0x1F,0x2B,0x2E,0x30,0x32,0x34,0x5E, + 0x5E,0x50,0x5E,0x00,0x00,0x2A,0x01,0xD1,0x10,0x20,0x00,0xE0,0x11,0x20,0x38,0x70, + 0xF8,0xBD,0x3A,0x74,0x1A,0xE0,0x01,0x20,0x88,0x70,0x00,0x20,0xF8,0x70,0xF8,0xBD, + 0x00,0x21,0x08,0x46,0xFC,0xF7,0xC4,0xFF,0x00,0x21,0x01,0x20,0xFD,0xF7,0x9E,0xFB, + 0xFE,0xE7,0x00,0x2A,0x05,0xD1,0x01,0x20,0xB8,0x77,0xF8,0x77,0x00,0x20,0x48,0x70, + 0xF8,0xBD,0x00,0x20,0xB8,0x77,0xF8,0x77,0xF8,0xBD,0x4A,0x70,0x7A,0x74,0xF8,0xBD, + 0x8A,0x72,0xF8,0xBD,0xFA,0x77,0xF8,0xBD,0x0A,0x70,0xF8,0xBD,0x00,0x2A,0x01,0xD1, + 0x00,0x21,0x00,0xE0,0x01,0x21,0x05,0x20,0xFC,0xF7,0xA2,0xFF,0x70,0x78,0x00,0x28, + 0xF3,0xD1,0x00,0x2C,0xF1,0xD0,0x71,0x69,0xF0,0x68,0x09,0x1A,0xA9,0x42,0x43,0xDD, + 0x00,0x28,0x01,0xD0,0x40,0x19,0xF0,0x60,0x30,0x69,0x00,0x28,0xE5,0xD0,0x40,0x19, + 0x30,0x61,0xF8,0xBD,0x00,0x2A,0x01,0xD1,0xFF,0x20,0x04,0xE0,0x01,0x2A,0x01,0xD1, + 0xF0,0x20,0x00,0xE0,0x00,0x20,0x78,0x77,0x00,0x20,0x08,0x72,0xC8,0x71,0xF8,0xBD, + 0x01,0x46,0x20,0x39,0x10,0x29,0xFA,0xD8,0x19,0x49,0x08,0x70,0xCA,0x70,0xF8,0xBD, + 0x10,0x2C,0x0E,0xD2,0x31,0x61,0x13,0x49,0xA0,0x00,0x18,0x31,0x08,0x58,0x11,0x4A, + 0x61,0x00,0x58,0x32,0xF0,0x60,0x51,0x5A,0x41,0x18,0x71,0x61,0x02,0x2C,0xCA,0xD8, + 0x10,0xE0,0x2F,0x2C,0xC7,0xD2,0x0B,0x49,0xA0,0x00,0x78,0x31,0x40,0x18,0x09,0x4A, + 0x40,0x38,0x61,0x00,0xF4,0x32,0x00,0x68,0x89,0x18,0x20,0x39,0xF0,0x60,0x09,0x88, + 0x40,0x18,0x70,0x61,0x30,0x61,0xB6,0xE7,0x00,0x20,0xF0,0x60,0x30,0x61,0x70,0x61, + 0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x06,0x00,0x20,0x98,0x04,0x00,0x20, + 0xC8,0x04,0x00,0x20,0xF8,0xB5,0x45,0x48,0x43,0x49,0x41,0x60,0x44,0x49,0x81,0x60, + 0x44,0x49,0x04,0x27,0x0C,0x68,0x44,0x49,0xC4,0x60,0x01,0x61,0x43,0x49,0x41,0x61, + 0x43,0x49,0x81,0x61,0x43,0x49,0xC1,0x61,0x43,0x49,0x01,0x62,0x43,0x49,0x41,0x62, + 0x9C,0x21,0x40,0x30,0x41,0x80,0x40,0x21,0x81,0x80,0xFF,0x21,0xFD,0x31,0xC1,0x80, + 0x30,0x21,0x01,0x81,0x47,0x81,0x48,0x21,0x81,0x81,0x36,0x21,0xC1,0x81,0x44,0x21, + 0x01,0x82,0x0A,0x21,0x41,0x82,0x20,0x46,0x20,0x30,0x06,0x7C,0x43,0x7C,0x32,0x48, + 0x35,0x46,0x5D,0x43,0x0C,0x30,0x00,0x93,0xFA,0xF7,0xD9,0xF9,0x2B,0x49,0x34,0x4A, + 0x60,0x31,0x08,0x60,0x08,0x46,0x7C,0x30,0x07,0x80,0x53,0x6A,0x4B,0x60,0x6B,0x00, + 0x43,0x80,0x17,0x6D,0x8F,0x60,0x83,0x80,0x97,0x6A,0xCF,0x60,0xC3,0x80,0xD3,0x6A, + 0x0B,0x61,0x05,0x81,0x53,0x6B,0x4B,0x61,0x73,0x00,0x43,0x81,0x55,0x6D,0x8D,0x61, + 0x83,0x81,0x95,0x6B,0xCD,0x61,0xC3,0x81,0xD3,0x6B,0x0B,0x62,0x06,0x82,0x53,0x6C, + 0x4B,0x62,0x00,0x9B,0x5B,0x00,0x43,0x82,0x95,0x6D,0x8D,0x62,0x83,0x82,0x95,0x6C, + 0xCD,0x62,0xC3,0x82,0xD2,0x6C,0x0A,0x63,0x00,0x9B,0x03,0x83,0xFF,0x22,0x7D,0x32, + 0x23,0x46,0x15,0x5D,0x80,0x33,0x9A,0x7D,0x5B,0x7D,0x00,0x2D,0x01,0xD0,0x5A,0x43, + 0x00,0xE0,0xD2,0x18,0x17,0x4B,0x5D,0x6A,0x4D,0x63,0x55,0x00,0x45,0x83,0x1E,0x6A, + 0x8E,0x63,0x85,0x83,0x9E,0x6A,0xCE,0x63,0xC5,0x83,0xDD,0x69,0x0D,0x64,0x02,0x84, + 0xDA,0x6A,0x4A,0x64,0xE2,0x7E,0x42,0x84,0x01,0x22,0x52,0x07,0x8A,0x64,0x03,0x21, + 0x49,0x03,0x81,0x84,0xF8,0xBD,0x00,0x00,0x32,0x05,0x00,0x20,0x18,0x00,0x00,0x20, + 0xCE,0x05,0x00,0x20,0x10,0x06,0x00,0x20,0x98,0x04,0x00,0x20,0xC8,0x04,0x00,0x20, + 0x32,0x01,0x00,0x20,0x7A,0x01,0x00,0x20,0x60,0x03,0x00,0x20,0xCD,0x04,0x00,0x20, + 0xAC,0x03,0x00,0x20,0x44,0x04,0x00,0x20,0x10,0xB5,0x19,0x4A,0x11,0x89,0x00,0x29, + 0x01,0xD1,0x10,0x70,0x23,0xE0,0x01,0x29,0x10,0xD1,0x11,0x78,0x09,0x02,0x01,0x43, + 0x14,0x48,0x00,0x68,0x43,0x7E,0x04,0x7E,0x18,0x02,0x20,0x43,0x2F,0x30,0x81,0x42, + 0x02,0xD1,0x01,0x20,0x50,0x70,0x12,0xE0,0x51,0x81,0x10,0xE0,0x04,0x29,0x04,0xD2, + 0x53,0x78,0x00,0x2B,0x08,0xD1,0x50,0x54,0x06,0xE0,0x53,0x69,0x11,0x69,0x99,0x42, + 0x02,0xD2,0x08,0x70,0x49,0x1C,0x11,0x61,0x10,0x89,0xFF,0x28,0x07,0xD2,0x10,0x89, + 0x40,0x1C,0x80,0xB2,0x10,0x81,0x04,0x28,0x01,0xD1,0xFF,0xF7,0x6B,0xFE,0x10,0xBD, + 0x00,0x00,0x00,0x20,0x10,0x06,0x00,0x20,0x10,0xB5,0x0E,0x49,0xA5,0x24,0x4A,0x69, + 0xC8,0x68,0x90,0x42,0x02,0xD2,0x04,0x78,0x40,0x1C,0xC8,0x60,0x0A,0x48,0x40,0x7C, + 0x00,0x28,0x0D,0xD1,0x09,0x48,0x00,0x68,0xFF,0x30,0x81,0x30,0x80,0x7E,0x02,0x28, + 0x06,0xD1,0xC9,0x68,0x06,0x48,0x81,0x42,0x02,0xD1,0x00,0x20,0xFD,0xF7,0xD6,0xF9, + 0x20,0x46,0x10,0xBD,0x00,0x00,0x00,0x20,0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0x7D,0x01,0x00,0x20,0x10,0xB5,0x1F,0x2A,0x06,0xD2,0x04,0x4C,0x93,0x00,0xE0,0x50, + 0x50,0x00,0x22,0x46,0x7C,0x32,0x11,0x52,0x10,0xBD,0x00,0x00,0x78,0x00,0x00,0x20, + 0x02,0x49,0x00,0x20,0x08,0x81,0x48,0x70,0x70,0x47,0x00,0x00,0x00,0x00,0x00,0x20, + 0xF8,0xB5,0x27,0x4C,0x00,0x25,0x27,0x4E,0xA5,0x70,0x30,0x68,0x23,0x46,0xFF,0x30, + 0x81,0x30,0x81,0x7E,0x01,0x27,0x20,0x7B,0x20,0x3B,0x01,0x29,0x02,0xD0,0x5A,0x7C, + 0x00,0x2A,0x19,0xD0,0x39,0x46,0x1F,0x46,0xD9,0x70,0x00,0x28,0x02,0xD1,0x01,0x20, + 0xFD,0xF7,0x9C,0xF9,0x30,0x68,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A,0x08,0x02, + 0x10,0x43,0x00,0xF0,0xA1,0xFE,0x05,0x46,0x20,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7, + 0x8D,0xF9,0x00,0x20,0xF8,0x70,0x21,0xE0,0x02,0x29,0x12,0xD1,0xD9,0x78,0x1E,0x46, + 0x00,0x29,0x06,0xD0,0x00,0x28,0x0A,0xD1,0xFD,0xF7,0x80,0xF9,0x01,0x20,0xFC,0xF7, + 0xC9,0xFD,0x20,0x7B,0x00,0x28,0x02,0xD1,0x01,0x20,0xFD,0xF7,0x77,0xF9,0xF7,0x70, + 0x0C,0xE0,0x00,0x28,0x02,0xD1,0x01,0x20,0xFD,0xF7,0x70,0xF9,0x01,0x20,0xFC,0xF7, + 0xB9,0xFD,0x20,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7,0x68,0xF9,0x28,0x46,0xF8,0xBD, + 0xB8,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0x10,0xB5,0x13,0x4C,0x01,0x46,0x20,0x7A, + 0x36,0x22,0x50,0x43,0x11,0x4A,0x80,0x18,0x36,0x22,0xFA,0xF7,0x65,0xF8,0x21,0x7A, + 0xE0,0x79,0x0B,0x46,0x49,0x1C,0x00,0x22,0x81,0x42,0x0B,0xD1,0x41,0x1C,0x20,0x72, + 0x08,0x29,0x00,0xD2,0x42,0x1C,0x08,0x49,0xE2,0x71,0x20,0x39,0x88,0x7D,0x40,0x1E, + 0x88,0x75,0x10,0xBD,0x07,0x2B,0x05,0xD1,0x00,0x28,0x01,0xD1,0x01,0x20,0xE0,0x71, + 0x22,0x72,0x10,0xBD,0x21,0x72,0x10,0xBD,0xB8,0x04,0x00,0x20,0xB0,0x01,0x00,0x20, + 0x10,0xB5,0x04,0x49,0x0A,0x7F,0x82,0x42,0x03,0xD0,0x08,0x77,0x00,0x21,0xFD,0xF7, + 0x85,0xF9,0x10,0xBD,0x98,0x04,0x00,0x20,0xF8,0xB5,0x2A,0x4D,0x00,0x26,0x2F,0x46, + 0x08,0x3F,0x0C,0x46,0x08,0x28,0x37,0xD0,0x0F,0xDC,0x01,0x28,0x1E,0xD0,0x02,0x28, + 0x27,0xD0,0x04,0x28,0x19,0xD1,0xFA,0xF7,0x7F,0xF8,0xAC,0x60,0xBE,0x70,0x03,0x21, + 0x04,0x20,0xFA,0xF7,0x91,0xF8,0x04,0x20,0x0D,0xE0,0x10,0x28,0x2F,0xD0,0x20,0x28, + 0x0B,0xD1,0x01,0x20,0xFA,0xF7,0x70,0xF8,0x6C,0x61,0x7E,0x71,0x00,0x21,0x01,0x20, + 0xFA,0xF7,0x82,0xF8,0x01,0x20,0xFA,0xF7,0x73,0xF8,0xF8,0xBD,0x02,0x20,0xFA,0xF7, + 0x63,0xF8,0x2C,0x60,0x3E,0x70,0x01,0x21,0x02,0x20,0xFA,0xF7,0x75,0xF8,0x02,0x20, + 0xF1,0xE7,0x03,0x20,0xFA,0xF7,0x58,0xF8,0x6C,0x60,0x7E,0x70,0x00,0x21,0x03,0x20, + 0xFA,0xF7,0x6A,0xF8,0x03,0x20,0xE6,0xE7,0x05,0x20,0xFA,0xF7,0x4D,0xF8,0xEC,0x60, + 0xFE,0x70,0x02,0x21,0x05,0x20,0xFA,0xF7,0x5F,0xF8,0x05,0x20,0xDB,0xE7,0x06,0x20, + 0xFA,0xF7,0x42,0xF8,0x2C,0x61,0x3E,0x71,0x02,0x21,0x06,0x20,0xFA,0xF7,0x54,0xF8, + 0x06,0x20,0xD0,0xE7,0x50,0x20,0x00,0x20,0x70,0xB5,0x12,0x4D,0x28,0x7C,0x00,0x28, + 0x0E,0xD1,0x2C,0x46,0x20,0x34,0xA0,0x7B,0x00,0x28,0x09,0xD1,0xFE,0xF7,0x16,0xFA, + 0xE1,0x78,0x00,0x29,0x05,0xD0,0x00,0x28,0x05,0xD1,0xA8,0x7D,0x40,0x1C,0xA8,0x75, + 0x70,0xBD,0x00,0x28,0xFC,0xD0,0xFF,0xF7,0xAD,0xFC,0x00,0xF0,0x10,0xF8,0x00,0x28, + 0xF6,0xD0,0xFF,0xF7,0xFD,0xFE,0x00,0x28,0x01,0xD0,0xFF,0x20,0x60,0x72,0x00,0xF0, + 0x03,0xF8,0x70,0xBD,0x98,0x04,0x00,0x20,0x70,0x47,0x70,0x47,0x70,0x47,0x01,0x20, + 0x70,0x47,0x70,0x47,0xF0,0xB5,0x96,0x46,0x9C,0x46,0x00,0x24,0x13,0xE0,0x65,0x00, + 0x42,0x5B,0x7D,0x23,0xDB,0x00,0xD2,0x1A,0x96,0xB2,0x46,0x53,0x62,0x46,0x17,0x5D, + 0xCB,0x1A,0xBA,0x06,0x92,0x0E,0x5A,0x43,0x7B,0x06,0x01,0xD5,0xB2,0x1A,0x00,0xE0, + 0xB2,0x18,0x42,0x53,0x64,0x1C,0x74,0x45,0xE9,0xD3,0xF0,0xBD,0x10,0xB5,0x04,0x78, + 0xCB,0xB2,0x8C,0x42,0x00,0xDD,0x03,0x70,0x84,0x78,0x8C,0x42,0x00,0xDA,0x83,0x70, + 0x43,0x78,0xD1,0xB2,0x93,0x42,0x00,0xDD,0x41,0x70,0xC3,0x78,0x93,0x42,0x00,0xDA, + 0xC1,0x70,0x10,0xBD,0x70,0xB5,0x0A,0x4C,0x65,0x78,0x26,0x78,0x28,0x46,0x70,0x43, + 0x42,0x00,0x21,0x6A,0x20,0x6D,0xF9,0xF7,0x77,0xFF,0x6A,0x00,0x21,0x6B,0x60,0x6D, + 0xF9,0xF7,0x72,0xFF,0x72,0x00,0x21,0x6C,0xA0,0x6D,0xF9,0xF7,0x6D,0xFF,0x70,0xBD, + 0xAC,0x03,0x00,0x20,0xF0,0xB5,0x2B,0x4C,0x06,0x46,0x27,0x46,0x20,0x3F,0x38,0x46, + 0x61,0x7D,0x08,0x30,0x85,0xB0,0x28,0x4D,0x03,0x90,0x00,0x29,0x28,0xD0,0x28,0x46, + 0x20,0x38,0x01,0x7F,0x25,0x48,0x00,0x68,0xFF,0x30,0x41,0x30,0x00,0x7C,0x81,0x42, + 0x1E,0xD1,0x00,0x2E,0x02,0xD0,0xFC,0xF7,0x75,0xF8,0x19,0xE0,0x20,0x48,0x21,0x4B, + 0x41,0x6C,0xD8,0x6A,0x00,0x22,0x02,0x92,0x01,0x91,0x00,0x90,0x19,0x4A,0x1B,0x6A, + 0x20,0x3A,0x1C,0x48,0x03,0x99,0xFC,0xF7,0x43,0xFA,0x17,0x48,0x21,0x7D,0x20,0x38, + 0x42,0x7D,0xB8,0x78,0xFC,0xF7,0xC8,0xFD,0xA1,0x7D,0x00,0x29,0x00,0xD0,0x68,0x71, + 0x12,0x48,0x00,0x68,0x80,0x30,0x00,0x7D,0xFC,0xF7,0x62,0xFB,0x10,0x48,0x11,0x4B, + 0x41,0x6C,0xD8,0x6A,0x6A,0x46,0x43,0xC2,0x0A,0x4A,0x1B,0x6A,0x20,0x3A,0x0D,0x48, + 0x03,0x99,0xFC,0xF7,0x25,0xFA,0x69,0x79,0x38,0x7A,0x08,0x22,0x00,0x23,0xFC,0xF7, + 0x77,0xF9,0x00,0x20,0xFC,0xF7,0x10,0xFB,0x00,0x2E,0x01,0xD0,0xFC,0xF7,0x0C,0xFC, + 0x05,0xB0,0xF0,0xBD,0xF6,0x04,0x00,0x20,0xB8,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0x60,0x03,0x00,0x20,0xAC,0x03,0x00,0x20,0x70,0xB5,0x48,0x79,0x0C,0x46,0xFF,0x28, + 0x17,0xD1,0xD0,0x78,0x00,0x09,0x0F,0xD0,0x0D,0x46,0x40,0x35,0x00,0x21,0x69,0x5E, + 0xA0,0x6B,0x4A,0x00,0x21,0x6B,0xF9,0xF7,0xF7,0xFE,0x18,0x20,0x28,0x5E,0xA1,0x6C, + 0x42,0x00,0x20,0x6D,0xF9,0xF7,0xF0,0xFE,0x00,0x20,0x60,0x71,0x20,0x72,0x64,0x20, + 0xE0,0x71,0x70,0xBD,0x70,0xB5,0x04,0x46,0xD0,0x78,0x0D,0x46,0x00,0x09,0x33,0xD0, + 0x90,0x68,0xC0,0x07,0x22,0x48,0x20,0x56,0x0C,0xD0,0x42,0x00,0x61,0x68,0xA8,0x6B, + 0xF9,0xF7,0xDA,0xFE,0x14,0x20,0x20,0x56,0xA1,0x68,0x42,0x00,0x28,0x6D,0xF9,0xF7, + 0xD3,0xFE,0x21,0xE0,0x42,0x00,0x61,0x68,0x28,0x69,0xF9,0xF7,0xCD,0xFE,0x14,0x20, + 0x20,0x56,0xA1,0x68,0x42,0x00,0x68,0x69,0xF9,0xF7,0xC6,0xFE,0x15,0x20,0x20,0x56, + 0xA9,0x6B,0x42,0x00,0x60,0x68,0xF9,0xF7,0xBF,0xFE,0x14,0x20,0x20,0x56,0x29,0x6D, + 0x42,0x00,0xA0,0x68,0xF9,0xF7,0xB8,0xFE,0x29,0x69,0xA8,0x6B,0xA9,0x63,0x28,0x61, + 0x69,0x69,0x28,0x6D,0x29,0x65,0x68,0x61,0x00,0x24,0x03,0xE0,0x01,0x2C,0x0B,0xD0, + 0x02,0x2C,0x09,0xD0,0x18,0x20,0x60,0x43,0x40,0x19,0x28,0x21,0x41,0x5E,0x4A,0x00, + 0x81,0x69,0x00,0x6A,0xF9,0xF7,0xA0,0xFE,0x64,0x1C,0x05,0x2C,0xEE,0xDB,0x70,0xBD, + 0x15,0x00,0x00,0x00,0xF7,0xB5,0x00,0x20,0x82,0xB0,0x1F,0x4E,0x07,0x46,0x05,0x46, + 0x01,0x90,0x03,0x98,0x80,0x28,0x03,0xD1,0x01,0x21,0x02,0x98,0xFB,0xF7,0x98,0xFC, + 0x00,0x20,0x69,0x46,0x01,0xE0,0x08,0x88,0x40,0x1C,0x08,0x80,0x08,0x88,0x26,0x28, + 0xF9,0xD3,0x04,0x20,0xFB,0xF7,0xB0,0xFA,0x14,0x49,0x03,0x98,0x08,0x43,0x14,0x49, + 0x08,0x80,0x00,0x22,0x20,0x21,0x04,0x20,0x00,0xF0,0x98,0xFC,0x04,0x98,0x04,0x88, + 0x01,0x98,0x00,0x19,0x01,0x90,0x03,0x98,0x80,0x28,0x03,0xD1,0x08,0x21,0x02,0x98, + 0xFB,0xF7,0x76,0xFC,0xA7,0x42,0x00,0xD2,0x27,0x46,0xA6,0x42,0x00,0xD9,0x26,0x46, + 0x6D,0x1C,0xAD,0xB2,0x06,0x2D,0xCC,0xD3,0x01,0x98,0xB9,0x19,0x40,0x1A,0x80,0x03, + 0x00,0x0C,0x05,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0xFF,0x00,0x00,0x63,0x04,0x00,0x00, + 0x00,0x10,0x00,0x40,0x10,0xB5,0x04,0x48,0xC0,0x68,0x80,0x47,0x02,0x49,0x01,0x20, + 0x08,0x39,0xC8,0x70,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0xF7,0xB5,0x84,0xB0, + 0x04,0x98,0x04,0x9E,0x0C,0x30,0x01,0x90,0x04,0x98,0x04,0x9F,0x18,0x30,0x04,0x9D, + 0x14,0x46,0x02,0x90,0x24,0x36,0x3C,0x37,0x54,0x35,0xFF,0x22,0x0C,0x21,0x04,0x98, + 0xF9,0xF7,0x52,0xFE,0x30,0x21,0x30,0x46,0xF9,0xF7,0x55,0xFE,0x00,0x21,0x15,0xE0, + 0x0A,0x46,0x62,0x43,0x00,0x20,0x96,0x46,0x4A,0x00,0x94,0x46,0x0B,0xE0,0x72,0x46, + 0x13,0x18,0x05,0x9A,0x5B,0x00,0xD2,0x5A,0x63,0x46,0xF3,0x5E,0x93,0x42,0x01,0xDA, + 0x63,0x46,0xF2,0x52,0x40,0x1C,0xA0,0x42,0xF1,0xD3,0x49,0x1C,0xA1,0x42,0xE7,0xD3, + 0x00,0x20,0x44,0xE0,0x00,0x20,0x03,0xE0,0x42,0x00,0x23,0x49,0xA9,0x52,0x40,0x1C, + 0xA0,0x42,0xF9,0xD3,0x60,0x00,0x03,0x90,0x34,0xE0,0x18,0x21,0x01,0x98,0xF9,0xF7, + 0x2A,0xFE,0x23,0x46,0x05,0x9A,0x04,0x99,0x00,0x98,0xFD,0xF7,0x75,0xFD,0x00,0x28, + 0x2B,0xD1,0x19,0x49,0x09,0xE0,0x02,0x9A,0x12,0x5C,0x00,0x2A,0x04,0xD1,0x42,0x00, + 0xAA,0x5E,0x8A,0x42,0x00,0xDA,0x11,0x46,0x40,0x1C,0xA0,0x42,0xF3,0xD3,0x00,0x20, + 0x15,0xE0,0x01,0x9A,0x12,0x5C,0x00,0x2A,0x03,0xD0,0x42,0x00,0xB3,0x5A,0x5B,0x1A, + 0xB3,0x52,0x02,0x9A,0x12,0x5C,0x00,0x2A,0x04,0xD0,0x42,0x00,0xBB,0x5A,0x5B,0x18, + 0xBB,0x52,0x03,0xE0,0x42,0x00,0xAB,0x5A,0x5B,0x1A,0xAB,0x52,0x40,0x1C,0xA0,0x42, + 0xE7,0xD3,0x03,0x98,0x40,0x1E,0x03,0x90,0xC7,0xD2,0x00,0x98,0x40,0x1C,0x00,0x90, + 0xA0,0x42,0xB7,0xD3,0x07,0xB0,0xF0,0xBD,0xFF,0x7F,0x00,0x00,0x10,0xB5,0x04,0x48, + 0x00,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x08,0x70,0x10,0xBD,0x00,0x00, + 0x50,0x20,0x00,0x20,0x00,0x21,0x82,0x0F,0x00,0xD1,0x80,0x00,0x01,0x22,0xD2,0x03, + 0x53,0x00,0x98,0x42,0x00,0xD2,0x80,0x22,0x11,0x43,0x0B,0x46,0x4B,0x43,0x83,0x42, + 0x00,0xD9,0x51,0x40,0x52,0x08,0xF7,0xD1,0x80,0x0F,0x01,0xD1,0x49,0x1C,0x49,0x08, + 0x88,0xB2,0x70,0x47,0xF3,0xB5,0xFF,0x20,0x45,0x30,0x83,0xB0,0x40,0x58,0x0D,0x46, + 0x00,0x90,0x01,0x68,0x00,0x29,0x08,0xD0,0x14,0x22,0x03,0x99,0x00,0x24,0x8A,0x56, + 0x2E,0x46,0x20,0x36,0x01,0x92,0x02,0x90,0x1B,0xE0,0x00,0x20,0x05,0xB0,0xF0,0xBD, + 0x02,0x98,0x54,0x22,0xC0,0x30,0x01,0x69,0x20,0x46,0x50,0x43,0x02,0x46,0x10,0x32, + 0x8A,0x5C,0x13,0x09,0x0C,0xD0,0x13,0x07,0xF7,0x78,0x1B,0x0F,0xBB,0x42,0x03,0xD9, + 0x33,0x79,0x12,0x09,0x9A,0x42,0x03,0xD9,0x08,0x18,0x54,0x21,0xF9,0xF7,0x9B,0xFD, + 0x64,0x1C,0xA8,0x78,0xA0,0x42,0xE3,0xD8,0x79,0x20,0x40,0x5D,0xFF,0x28,0x05,0xD0, + 0x01,0x23,0x00,0x22,0x29,0x46,0x03,0x98,0xFF,0xF7,0xDA,0xF9,0x00,0x98,0x29,0x46, + 0x02,0x68,0x03,0x98,0x90,0x47,0xAC,0x7C,0x20,0x2C,0xCF,0xD0,0xE9,0x78,0x09,0x09, + 0xCC,0xD0,0x00,0x21,0x07,0xE0,0x03,0x9A,0x4B,0x00,0x92,0x68,0xD5,0x5E,0x65,0x43, + 0x6D,0x11,0xD5,0x52,0x49,0x1C,0x01,0x9A,0x91,0x42,0xF4,0xDB,0xBE,0xE7,0xF3,0xB5, + 0x08,0x46,0xFF,0x30,0x85,0xB0,0x41,0x30,0x02,0x90,0x45,0x68,0x01,0x91,0x8C,0x78, + 0x0E,0x46,0xA4,0x1C,0xFE,0xF7,0x2A,0xFF,0x24,0x01,0x00,0x90,0x20,0x46,0xFE,0xF7, + 0x43,0xFF,0x21,0x46,0x00,0x98,0xF9,0xF7,0x5E,0xFD,0x01,0x9C,0x00,0x20,0x40,0x34, + 0x20,0x72,0x02,0x23,0x31,0x46,0x00,0x9A,0x05,0x98,0xFF,0xF7,0xA1,0xF9,0x20,0x7A, + 0x00,0x27,0x00,0x28,0x0C,0xD1,0x20,0x7C,0x00,0x28,0x09,0xD0,0x6B,0x68,0x00,0x2B, + 0x06,0xD0,0x29,0x46,0x00,0x9A,0x05,0x98,0x98,0x47,0x07,0x1E,0x00,0xDD,0x27,0x72, + 0x60,0x7B,0x0A,0x28,0x01,0xD3,0x01,0x20,0xA0,0x74,0xA0,0x7F,0x00,0x28,0x01,0xD0, + 0x00,0x20,0x20,0x72,0x03,0x23,0x31,0x46,0x00,0x9A,0x05,0x98,0xFF,0xF7,0x80,0xF9, + 0x05,0x98,0x40,0x8A,0xA0,0x75,0xAB,0x68,0x00,0x2B,0x03,0xD0,0x22,0x7A,0x28,0x46, + 0x00,0x99,0x98,0x47,0xEA,0x68,0x00,0x2A,0x03,0xD0,0xD0,0x20,0x40,0x59,0x01,0x99, + 0x90,0x47,0x28,0x46,0xC0,0x30,0x03,0x90,0x01,0x69,0x01,0x98,0xF9,0xF7,0x06,0xFF, + 0x01,0x99,0x00,0x26,0x20,0x31,0x8C,0x46,0x01,0x99,0x30,0x46,0x8B,0x78,0x0D,0xE0, + 0x03,0x99,0x54,0x22,0x09,0x69,0x42,0x43,0x10,0x32,0x89,0x5C,0x62,0x46,0x09,0x07, + 0xD2,0x78,0x09,0x0F,0x91,0x42,0x00,0xD9,0x76,0x1C,0x40,0x1C,0x83,0x42,0xEF,0xDC, + 0x66,0x72,0x00,0x98,0xFE,0xF7,0x00,0xFF,0x29,0x69,0x00,0x29,0x02,0xD0,0x02,0x98, + 0x40,0x68,0x88,0x47,0x00,0x2F,0x02,0xDA,0x38,0x46,0x07,0xB0,0xF0,0xBD,0x30,0x46, + 0xFB,0xE7,0x70,0xB5,0xFF,0x30,0x41,0x30,0x40,0x68,0x0C,0x46,0xC0,0x30,0x85,0x68, + 0x00,0x20,0x60,0x34,0x20,0x76,0x0C,0xE0,0x06,0x22,0x42,0x43,0x52,0x19,0x96,0x8A, + 0x43,0x00,0xCE,0x52,0xD2,0x8A,0x5B,0x18,0x9A,0x87,0x22,0x7E,0x52,0x1C,0x22,0x76, + 0x40,0x1C,0x2A,0x78,0x82,0x42,0xEF,0xDC,0x70,0xBD,0xF0,0xB5,0xC0,0x30,0x00,0x27, + 0x46,0x69,0x04,0x69,0x85,0xB0,0x0D,0x46,0x38,0x46,0x6A,0xE0,0x20,0x7C,0x01,0x07, + 0x30,0x46,0x20,0x30,0x03,0x90,0xC0,0x78,0x09,0x0F,0x81,0x42,0x01,0xD8,0x54,0x34, + 0x5D,0xE0,0x60,0x7C,0x01,0xAB,0x40,0x06,0x40,0x0E,0x28,0x70,0x00,0x93,0x20,0x46, + 0x33,0x46,0x01,0x22,0x21,0x46,0x20,0x30,0xF9,0xF7,0xC4,0xFE,0x01,0x98,0xE8,0x60, + 0x01,0xAB,0x00,0x93,0x33,0x46,0x00,0x22,0x21,0x46,0x20,0x46,0xF9,0xF7,0xBA,0xFE, + 0x01,0x98,0xA8,0x60,0x60,0x68,0x68,0x61,0x20,0x7C,0x01,0x09,0x03,0x98,0x00,0x79, + 0x81,0x42,0x68,0x78,0x03,0xD8,0x80,0x09,0x80,0x01,0x40,0x1C,0x01,0xE0,0x80,0x09, + 0x80,0x01,0x68,0x70,0xE0,0x7C,0xFF,0x28,0x01,0xD2,0x40,0x1C,0xE0,0x74,0xA8,0x70, + 0x20,0x7C,0x00,0x09,0x68,0x78,0x12,0xD0,0x40,0x06,0x40,0x0E,0x68,0x70,0x61,0x7B, + 0xE9,0x80,0xE1,0x7A,0xE9,0x70,0xBF,0x21,0x08,0x40,0x21,0x7B,0x89,0x07,0xC9,0x0F, + 0x89,0x01,0x08,0x43,0x68,0x70,0x20,0x7C,0x00,0x09,0x03,0xD0,0x11,0xE0,0x80,0x21, + 0x08,0x43,0xEB,0xE7,0x01,0xAB,0x00,0x93,0x20,0x46,0x33,0x46,0x02,0x22,0x21,0x46, + 0x40,0x30,0xF9,0xF7,0x7F,0xFE,0x01,0x98,0x28,0x61,0x60,0x7A,0x68,0x71,0x20,0x7A, + 0x28,0x71,0xB0,0x78,0x7F,0x1C,0x18,0x35,0x54,0x34,0xB8,0x42,0x05,0xD0,0x02,0x98, + 0x40,0x1C,0x02,0x90,0xB1,0x78,0x81,0x42,0x90,0xDC,0x38,0x46,0x05,0xB0,0xF0,0xBD, + 0xFF,0xB5,0x06,0x46,0xFF,0x30,0x37,0x46,0x21,0x30,0xFF,0x37,0xC1,0x8B,0x41,0x37, + 0x83,0xB0,0x38,0x68,0xFE,0xF7,0x64,0xFE,0xF0,0x1D,0x03,0x21,0xF9,0x30,0x01,0x75, + 0x41,0x75,0x31,0x46,0x4E,0x4A,0x0C,0x31,0x3C,0x23,0x00,0x20,0x0C,0x5C,0xFF,0x2C, + 0x01,0xD1,0x14,0x5C,0x0C,0x54,0x40,0x1C,0x98,0x42,0xF7,0xDB,0x34,0x46,0x48,0x34, + 0x2A,0x21,0x20,0x46,0xF9,0xF7,0x37,0xFC,0xB0,0x88,0xF1,0x88,0x40,0x43,0x49,0x43, + 0x40,0x18,0xFF,0xF7,0x4F,0xFE,0x35,0x46,0x20,0x35,0x69,0x79,0x48,0x43,0x64,0x21, + 0xF9,0xF7,0xD8,0xFB,0x20,0x85,0x68,0x78,0x64,0x21,0xC0,0x01,0xF9,0xF7,0xD2,0xFB, + 0x20,0x73,0xA8,0x79,0x64,0x21,0xC0,0x01,0xF9,0xF7,0xCC,0xFB,0x60,0x73,0x01,0x20, + 0xA0,0x72,0x0A,0x20,0x20,0x72,0xFE,0x20,0xE0,0x72,0x64,0x21,0x7B,0x20,0x81,0x55, + 0xFE,0xF7,0xD4,0xFD,0xD8,0x21,0x45,0x18,0x04,0x46,0x78,0x60,0xF9,0xF7,0x0B,0xFC, + 0x21,0x46,0xC0,0x31,0x0D,0x61,0xB0,0x78,0x54,0x22,0x50,0x43,0xC0,0x1C,0x87,0x08, + 0x4E,0x61,0xBC,0x20,0x06,0x99,0x01,0x51,0x30,0x46,0xBF,0x00,0xFF,0x30,0xD8,0x37, + 0x17,0x30,0x06,0x22,0x27,0xA1,0xF9,0xF7,0xCF,0xFB,0x35,0x46,0xFF,0x35,0x1C,0x35, + 0x28,0x78,0x00,0x28,0x01,0xD1,0x2D,0x20,0x28,0x70,0x6D,0x1C,0x38,0x46,0xFE,0xF7, + 0xCB,0xFD,0x00,0x20,0x07,0x46,0x00,0x90,0x17,0xE0,0xF8,0x00,0x04,0x99,0x01,0x90, + 0x09,0x58,0x00,0x29,0x10,0xD0,0x30,0x46,0x88,0x47,0x04,0x99,0x01,0x98,0x00,0x9A, + 0x41,0x18,0x48,0x68,0x00,0x78,0x90,0x42,0x02,0xD0,0x00,0x90,0x28,0x70,0x6D,0x1C, + 0x48,0x68,0x40,0x78,0x28,0x70,0x6D,0x1C,0x7F,0x1C,0x05,0x98,0x87,0x42,0xE4,0xDB, + 0x00,0x20,0x28,0x70,0x02,0x46,0x51,0x1C,0xD0,0x00,0x03,0x19,0x10,0xE0,0xC8,0x00, + 0x00,0x19,0x9D,0x8A,0x86,0x8A,0xB5,0x42,0x09,0xD9,0x9E,0x69,0x5D,0x69,0xB4,0x46, + 0x87,0x69,0x46,0x69,0x9F,0x61,0x5E,0x61,0x66,0x46,0x86,0x61,0x45,0x61,0x49,0x1C, + 0x15,0x29,0xEC,0xDB,0x52,0x1C,0x15,0x2A,0xE5,0xDB,0x07,0xB0,0xF0,0xBD,0x00,0x00, + 0x08,0x6F,0x00,0x00,0x31,0x33,0x30,0x39,0x31,0x00,0x00,0x00,0xFF,0xB5,0xC0,0x30, + 0x8F,0xB0,0x47,0x69,0x04,0x69,0x12,0x98,0x0D,0x46,0x41,0x00,0x89,0x1C,0x01,0x26, + 0x0C,0x91,0x36,0x03,0x49,0x43,0x30,0x46,0xF9,0xF7,0x5A,0xFB,0x0D,0x90,0x12,0x99, + 0x30,0x46,0x49,0x1C,0xF9,0xF7,0x54,0xFB,0x0E,0x90,0x00,0x20,0x06,0x46,0x0B,0x90, + 0x79,0xE0,0x20,0x7C,0x39,0x46,0x20,0x31,0x00,0x07,0xCA,0x78,0x00,0x0F,0x90,0x42, + 0x01,0xD8,0x54,0x34,0x6E,0xE0,0x22,0x6A,0x03,0x92,0xE2,0x6A,0x04,0x92,0x22,0x6B, + 0x05,0x92,0x22,0x68,0x06,0x92,0x62,0x6A,0x07,0x92,0xA0,0x6A,0x08,0x90,0x06,0x98, + 0x90,0x42,0x0D,0xD0,0x04,0x9A,0x03,0x98,0x90,0x42,0x09,0xD0,0x68,0x78,0x80,0x06, + 0x06,0xD0,0x20,0x7C,0x02,0x07,0xC8,0x78,0x12,0x0F,0x80,0x1C,0x82,0x42,0x04,0xD2, + 0x20,0x6A,0x09,0x90,0x20,0x68,0x0A,0x90,0x2E,0xE0,0x11,0x98,0x00,0x90,0x00,0x20, + 0x01,0x90,0x0E,0x98,0x02,0x90,0x20,0x7C,0x02,0x07,0xC8,0x78,0x12,0x0F,0x80,0x1C, + 0x82,0x42,0x08,0xD9,0x11,0x99,0x12,0x98,0x40,0x1A,0x40,0x1C,0x00,0x90,0x0C,0x98, + 0x01,0x90,0x0D,0x98,0x02,0x90,0x00,0x22,0x69,0x46,0x03,0xA8,0xFA,0xF7,0x54,0xF9, + 0x69,0x46,0x88,0x84,0x01,0x22,0x03,0xA8,0xFA,0xF7,0x4E,0xF9,0x69,0x46,0xC8,0x84, + 0x00,0x22,0x06,0xA8,0xFA,0xF7,0x48,0xF9,0x69,0x46,0x08,0x85,0x01,0x22,0x06,0xA8, + 0xFA,0xF7,0x42,0xF9,0x69,0x46,0x48,0x85,0x09,0xAB,0x00,0x93,0x3B,0x46,0x01,0x22, + 0x21,0x46,0x09,0xA8,0xF9,0xF7,0x36,0xFD,0x0A,0xAB,0x00,0x93,0x3B,0x46,0x00,0x22, + 0x21,0x46,0x0A,0xA8,0xF9,0xF7,0x2E,0xFD,0x09,0x98,0xE8,0x60,0x0A,0x98,0xA8,0x60, + 0x68,0x78,0x54,0x34,0x80,0x09,0x80,0x01,0x40,0x1C,0x68,0x70,0x0B,0x98,0x40,0x1C, + 0x18,0x35,0x0B,0x90,0x76,0x1C,0xB8,0x78,0xB0,0x42,0x82,0xDC,0x0B,0x98,0x13,0xB0, + 0xF0,0xBD,0x00,0x00,0x30,0xB4,0x10,0x4B,0x58,0x88,0x58,0x80,0xEF,0xF3,0x08,0x82, + 0x0E,0x49,0x48,0x68,0x82,0x42,0x01,0xD8,0x0D,0x4A,0x02,0x60,0x0B,0x48,0x8A,0x7B, + 0x40,0x7C,0x00,0x2A,0x04,0xD1,0x0A,0x89,0x4C,0x89,0x42,0x43,0xA2,0x42,0x01,0xD2, + 0xA0,0x22,0x9A,0x80,0x40,0x1C,0x48,0x74,0x08,0x68,0x00,0x28,0x01,0xD0,0x30,0xBC, + 0x00,0x47,0x30,0xBC,0x70,0x47,0x00,0x00,0x00,0x02,0x00,0x40,0x68,0x20,0x00,0x20, + 0x78,0x56,0x34,0x12,0xFF,0xB5,0x83,0xB0,0x06,0x46,0x68,0x46,0x12,0x25,0x45,0x5F, + 0x14,0x24,0x18,0x22,0xAC,0x46,0x04,0x5F,0x82,0x5E,0x10,0x23,0x1A,0x21,0x16,0x25, + 0xC3,0x5E,0x41,0x5E,0x45,0x5F,0x94,0x42,0x08,0xD1,0x8D,0x42,0x00,0xD0,0x23,0x46, + 0x33,0x80,0x60,0x46,0x70,0x80,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x48,0x1B,0x12,0x1B, + 0x61,0x46,0xE7,0x1A,0x69,0x1A,0x47,0x43,0x51,0x43,0x79,0x1A,0x00,0x91,0x01,0x46, + 0x02,0x92,0x01,0x90,0x51,0x43,0x01,0x27,0x40,0x43,0x52,0x43,0x7F,0x04,0xB8,0x42, + 0x06,0xDC,0xBA,0x42,0x04,0xDC,0xB9,0x42,0x02,0xDC,0x7F,0x42,0xB9,0x42,0x04,0xDA, + 0xC0,0x1C,0xD2,0x1C,0x80,0x10,0x92,0x10,0x89,0x10,0x67,0x46,0x7F,0x1B,0x4F,0x43, + 0x21,0x46,0x41,0x43,0x7F,0x18,0x81,0x18,0x53,0x43,0x48,0x10,0x18,0x18,0x38,0x18, + 0xF9,0xF7,0x5E,0xFA,0x07,0x46,0x01,0x98,0x39,0x1B,0x48,0x43,0x02,0x99,0xF9,0xF7, + 0x57,0xFA,0x40,0x19,0x37,0x80,0x70,0x80,0x00,0x98,0xC5,0xE7,0xC3,0x6A,0x03,0x63, + 0x03,0x6A,0xC3,0x62,0x12,0x68,0x42,0x63,0x41,0x7C,0xC9,0x09,0x01,0xD0,0x83,0x63, + 0x70,0x47,0x02,0x62,0x70,0x47,0xF7,0xB5,0x04,0x46,0x00,0x78,0x00,0x27,0x00,0x28, + 0x10,0xD0,0x06,0x21,0x48,0x43,0x00,0x19,0x10,0x23,0x0E,0x22,0xC3,0x5E,0x82,0x5E, + 0x02,0x98,0x01,0xB2,0x01,0x98,0x00,0xB2,0xFE,0xF7,0x15,0xFF,0x07,0x46,0x20,0x78, + 0x1E,0x28,0x03,0xD2,0x20,0x78,0x40,0x1C,0x20,0x70,0x2C,0xE0,0xE0,0x8B,0xA1,0x8C, + 0x01,0x26,0x42,0x18,0x02,0x25,0x06,0x20,0x68,0x43,0x01,0x19,0x08,0x8B,0xC9,0x8B, + 0x40,0x18,0x90,0x42,0x01,0xDA,0x02,0x46,0x2E,0x46,0x6D,0x1C,0x1D,0x2D,0xF2,0xDB, + 0x06,0x20,0x70,0x43,0x05,0x19,0x1C,0x23,0x1A,0x22,0x10,0x21,0x0E,0x20,0xEB,0x5E, + 0xAA,0x5E,0x69,0x5E,0x28,0x5E,0xFE,0xF7,0xEE,0xFE,0xE8,0x83,0x09,0xE0,0x06,0x20, + 0x70,0x43,0x00,0x19,0x01,0x46,0x1A,0x31,0x14,0x30,0x06,0x22,0xF9,0xF7,0x14,0xFA, + 0x76,0x1C,0x1D,0x2E,0xF3,0xDB,0x21,0x78,0x06,0x22,0x51,0x43,0x09,0x19,0x01,0x98, + 0xC8,0x81,0x21,0x78,0x02,0x98,0x51,0x43,0x09,0x19,0x08,0x82,0x20,0x78,0x50,0x43, + 0x00,0x19,0x47,0x82,0x00,0x20,0xFE,0xBD,0x70,0xB5,0x64,0x21,0x48,0x43,0x06,0x46, + 0x00,0x24,0x0D,0x4D,0x0C,0xE0,0xFF,0xF7,0x44,0xFA,0xA8,0x78,0x00,0x28,0x10,0xD1, + 0x01,0x20,0xFB,0xF7,0x2F,0xFF,0x00,0x21,0x0B,0x20,0xFB,0xF7,0x59,0xFF,0x64,0x1C, + 0xB4,0x42,0xF0,0xD3,0xA8,0x78,0x00,0x28,0x03,0xD1,0x01,0x20,0xA8,0x70,0x00,0x20, + 0x70,0xBD,0x01,0x20,0x70,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0xF0,0xB5,0x00,0x24, + 0x1B,0x4F,0x1C,0x4E,0x04,0x25,0x3B,0x78,0x00,0x2B,0x01,0xD0,0x01,0x23,0x1C,0x43, + 0x7B,0x79,0x00,0x2B,0x01,0xD0,0x20,0x23,0x1C,0x43,0x7B,0x78,0x00,0x2B,0x01,0xD0, + 0x02,0x23,0x1C,0x43,0xFB,0x78,0x00,0x2B,0x01,0xD0,0x08,0x23,0x1C,0x43,0xBB,0x78, + 0x00,0x2B,0x00,0xD0,0x2C,0x43,0x3B,0x79,0x00,0x2B,0x01,0xD0,0x10,0x23,0x1C,0x43, + 0x23,0x46,0x03,0x42,0x0D,0xD1,0x20,0x29,0xDD,0xD0,0x22,0x29,0x02,0xD1,0x33,0x69, + 0x2B,0x43,0x33,0x61,0x30,0xBF,0x22,0x29,0xD5,0xD1,0x33,0x69,0xAB,0x43,0x33,0x61, + 0xD1,0xE7,0x00,0x2A,0x01,0xD0,0xFA,0xF7,0xD7,0xFD,0x20,0x46,0xF0,0xBD,0x00,0x00, + 0x48,0x20,0x00,0x20,0x00,0xED,0x00,0xE0,0x00,0x00,0x00,0x00,0x41,0x5F,0x00,0x00, + 0x69,0x5E,0x00,0x00,0xD9,0x5E,0x00,0x00,0x9D,0x5B,0x00,0x00,0xA1,0x5B,0x00,0x00, + 0x97,0x5B,0x00,0x00,0x99,0x5B,0x00,0x00,0xAC,0xCA,0xFF,0xFF,0x32,0x33,0x34,0x35, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x51,0x52, + 0x53,0x54,0x55,0x56,0x57,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x03,0x04,0x05,0x06,0x07,0xFF,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x89,0x09,0x00,0x00,0x47,0x6F,0x00,0x00,0xF9,0x16,0x00,0x00, + 0x4A,0x6F,0x00,0x00,0x59,0x4F,0x00,0x00,0x44,0x6F,0x00,0x00,0xB5,0x3F,0x00,0x00, + 0x50,0x6F,0x00,0x00,0x25,0x5A,0x00,0x00,0x53,0x6F,0x00,0x00,0x49,0x44,0x00,0x00, + 0x4D,0x6F,0x00,0x00,0x48,0x59,0x4E,0x43,0x53,0x54,0x01,0x02,0x04,0x08,0x00,0x04, + 0x02,0x01,0x03,0x06,0x0C,0x12,0x18,0x1E,0x24,0x2A,0x06,0x0C,0x12,0x18,0x1E,0x24, + 0x30,0x3C,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0x01, + 0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0xFF,0xFF,0x01,0x01,0x01, + 0xFF,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF,0xFF, + 0xFF,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01, + 0x01,0x01,0xFF,0xFF,0x82,0x00,0x00,0x82,0x00,0x00,0x02,0x82,0x01,0x81,0x01,0x01, + 0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x81,0x81,0x01,0x01,0x01, + 0x81,0x81,0x01,0x01,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x02,0x02,0x02,0x00,0x00, + 0x00,0x02,0x00,0x02,0x81,0x81,0x81,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02, + 0x02,0x02,0x82,0x02,0xFF,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF,0x01, + 0x01,0x01,0x01,0xFF,0x81,0x01,0x01,0x01,0x01,0x81,0x01,0x01,0x01,0x01,0x81,0x01, + 0x01,0x01,0x01,0x81,0x3B,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14,0x05,0x0A,0x20,0x28, + 0x28,0x28,0x19,0x1E,0x2A,0x11,0x64,0x64,0x0A,0x08,0x0F,0x5A,0x28,0x64,0x64,0x01, + 0x01,0x05,0x32,0x01,0x28,0x14,0x46,0x28,0x32,0x96,0x03,0x5A,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4D,0x30,0x00,0x42,0x31,0x00,0x43,0x31,0x00,0x47,0x31,0x00, + 0x46,0x32,0x00,0x70,0x34,0x00,0x00,0x00,0x68,0x6F,0x00,0x00,0x00,0x00,0x00,0x20, + 0x98,0x21,0x00,0x00,0x32,0x02,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xA8,0x9F,0xB0, + 0x0C,0x22,0xCA,0xCA,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x2A,0xCB,0xCB, + 0x00,0x00,0x00,0x00,0xA5,0xA5,0xCA,0xCA,0x00,0xD0,0x05,0x00,0x00,0x05,0x20,0x03, + 0x00,0x01,0x01,0x01,0x20,0x10,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x1E,0x00,0x00,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x02, + 0x03,0x04,0x05,0x06,0x07,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,0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C,0x1B, + 0x1A,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x0D,0x0C,0x0B,0x0A,0x09,0x43,0x42,0x41, + 0x40,0x3F,0x3E,0x3D,0x3C,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x31,0x39,0x40,0x00,0x00,0x00,0x00,0x00,0x2B,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14, + 0x05,0x0A,0x20,0x1E,0x3C,0x14,0x19,0x1E,0x2D,0x33,0x32,0x32,0x06,0x08,0x0F,0x5A, + 0x28,0x1E,0x64,0x01,0x01,0x0A,0x01,0x05,0x28,0x0A,0x4D,0x14,0x32,0x96,0x03,0x5A, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x80, + 0x0C,0x3C,0x08,0x00,0x90,0x01,0x00,0x00,0x00,0x58,0x02,0x03,0x02,0x31,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x01,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x4D,0x00,0x11,0x01,0x11,0x00,0x00,0x64,0x00,0x02,0x01,0x01,0x30,0x00,0x00, + 0x1E,0x50,0xB0,0x28,0x03,0x03,0x28,0x14,0x50,0xB0,0x28,0x03,0x03,0x32,0x14,0x28, + 0xD8,0x28,0x03,0x03,0x32,0x00,0x00,0x00,0xF4,0x01,0x01,0x00,0x00,0x00,0x00,0x00, + 0x01,0x20,0x0F,0x08,0x02,0x02,0x00,0x00,0x20,0x01,0x00,0x03,0x05,0x01,0x06,0x07, + 0x03,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x03,0x04,0x01,0x03,0x06,0x00, + 0x03,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0xC8,0x00,0x00,0x01,0x20,0x01,0x03,0x50, + 0x28,0x32,0xC8,0x00,0x08,0x01,0x01,0x10,0x04,0x03,0x11,0x1C,0x2D,0x36,0x14,0x23, + 0x30,0x38,0x18,0x28,0x33,0x3C,0x0F,0x13,0x21,0x0F,0x17,0x28,0x0F,0x1C,0x30,0x0F, + 0x13,0x0F,0x17,0x0F,0x1C,0xC8,0x06,0x08,0x78,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0x1A,0xCE,0x59, + 0x00,0x00,0x04,0x03,0x68,0x65,0x6C,0x6C,0x6F,0x20,0x68,0x79,0x6E,0x21,0x21,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xA3,0xF9,0xE8, + 0x3A,0xCE,0xCE,0xE6, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw2.h b/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw2.h new file mode 100644 index 000000000000..8731030f71a0 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst66xx_fw2.h @@ -0,0 +1,2584 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst66xx_fw2.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE2_H +#define HYNITRON_FIRMWARE2_H + +static const uint8_t fw_module2[] = { + 0xF8,0x5F,0x00,0x20,0xFD,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x8D,0x45,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xD9,0x1C,0x00,0x00,0x4D,0x65,0x00,0x00,0xFD,0x48,0x00,0x00, + 0xB1,0x1C,0x00,0x00,0x35,0x64,0x00,0x00,0x75,0x45,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x48,0x85,0x46,0x00,0xF0,0x76,0xF8,0x00,0x48,0x00,0x47,0xA5,0x4E,0x00,0x00, + 0xF8,0x5F,0x00,0x20,0x30,0xB5,0x0B,0x46,0x01,0x46,0x00,0x20,0x20,0x22,0x01,0x24, + 0x09,0xE0,0x0D,0x46,0xD5,0x40,0x9D,0x42,0x05,0xD3,0x1D,0x46,0x95,0x40,0x49,0x1B, + 0x25,0x46,0x95,0x40,0x40,0x19,0x15,0x46,0x52,0x1E,0x00,0x2D,0xF1,0xDC,0x30,0xBD, + 0x70,0xB5,0x00,0x24,0x25,0x46,0x00,0x28,0x01,0xDA,0x01,0x24,0x40,0x42,0x00,0x29, + 0x01,0xDA,0x01,0x25,0x49,0x42,0xFF,0xF7,0xDD,0xFF,0xAC,0x42,0x00,0xD0,0x40,0x42, + 0x00,0x2C,0x00,0xD0,0x49,0x42,0x70,0xBD,0x10,0xB5,0x43,0x1A,0x93,0x42,0x09,0xD2, + 0x83,0x18,0x88,0x18,0x03,0xE0,0x40,0x1E,0x01,0x78,0x5B,0x1E,0x19,0x70,0x52,0x1E, + 0xF9,0xD2,0x10,0xBD,0x03,0x46,0x0B,0x43,0x9B,0x07,0x0A,0xD1,0x02,0xE0,0x08,0xC9, + 0x12,0x1F,0x08,0xC0,0x04,0x2A,0xFA,0xD2,0x03,0xE0,0x0B,0x78,0x03,0x70,0x49,0x1C, + 0x40,0x1C,0x52,0x1E,0xF9,0xD2,0x10,0xBD,0xD2,0xB2,0x01,0xE0,0x02,0x70,0x40,0x1C, + 0x49,0x1E,0xFB,0xD2,0x70,0x47,0x00,0x22,0xF6,0xE7,0x10,0xB5,0x04,0x46,0x08,0x46, + 0x11,0x46,0x02,0x46,0x20,0x46,0xFF,0xF7,0xEF,0xFF,0x20,0x46,0x10,0xBD,0x02,0x1D, + 0x03,0x21,0x52,0x1E,0x13,0x78,0x00,0x02,0x18,0x43,0x49,0x1E,0xF9,0xD5,0x70,0x47, + 0x03,0x46,0x03,0x22,0x08,0x70,0x49,0x1C,0x00,0x0A,0x52,0x1E,0xFA,0xD5,0x18,0x46, + 0x70,0x47,0x00,0x00,0x06,0x4C,0x01,0x25,0x06,0x4E,0x05,0xE0,0x20,0x46,0xE3,0x68, + 0x07,0xC8,0x2B,0x43,0x98,0x47,0x10,0x34,0xB4,0x42,0xF7,0xD3,0xFF,0xF7,0x7C,0xFF, + 0x58,0x6F,0x00,0x00,0x68,0x6F,0x00,0x00,0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40, + 0x40,0x09,0x02,0x4A,0x80,0x00,0x80,0x18,0x01,0x60,0x70,0x47,0x80,0xE1,0x00,0xE0, + 0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40,0x40,0x09,0x02,0x4A,0x80,0x00,0x80,0x18, + 0x01,0x60,0x70,0x47,0x00,0xE1,0x00,0xE0,0x83,0x07,0xFF,0x22,0xDB,0x0E,0x9A,0x40, + 0x89,0x07,0x09,0x0E,0x99,0x40,0x00,0x28,0x0B,0xDA,0x00,0x07,0x00,0x0F,0x08,0x38, + 0x83,0x08,0x08,0x48,0x9B,0x00,0x18,0x18,0xC3,0x69,0x93,0x43,0x0B,0x43,0xC3,0x61, + 0x70,0x47,0x83,0x08,0x04,0x48,0x9B,0x00,0x18,0x18,0x03,0x68,0x93,0x43,0x0B,0x43, + 0x03,0x60,0x70,0x47,0x00,0xED,0x00,0xE0,0x00,0xE4,0x00,0xE0,0x10,0xB5,0x01,0xF0, + 0x2F,0xFD,0xFF,0xF7,0x35,0xFF,0x10,0xBD,0x30,0xB4,0x74,0x46,0x64,0x1E,0x25,0x78, + 0x64,0x1C,0xAB,0x42,0x00,0xD2,0x1D,0x46,0x63,0x5D,0x5B,0x00,0xE3,0x18,0x30,0xBC, + 0x18,0x47,0x02,0xE0,0x08,0xC8,0x12,0x1F,0x08,0xC1,0x00,0x2A,0xFA,0xD1,0x70,0x47, + 0x70,0x47,0x00,0x20,0x01,0xE0,0x01,0xC1,0x12,0x1F,0x00,0x2A,0xFB,0xD1,0x70,0x47, + 0xF8,0xB5,0x31,0x4F,0x00,0x25,0xB8,0x7A,0x81,0x06,0x14,0xD5,0x2F,0x4C,0x21,0x28, + 0x05,0xD1,0x40,0x22,0x2E,0x49,0x20,0x46,0xFF,0xF7,0x3E,0xFF,0x09,0xE0,0x22,0x28, + 0x07,0xD1,0x2C,0x48,0x40,0x22,0x01,0x68,0x29,0x48,0xA8,0x31,0xFF,0xF7,0x34,0xFF, + 0xEF,0xE7,0x00,0x20,0xB8,0x72,0x25,0x4C,0x01,0x26,0x38,0x34,0xA0,0x7A,0x05,0x28, + 0x01,0xD9,0xA6,0x74,0x01,0x25,0x24,0x49,0x20,0x48,0x0A,0x68,0x78,0x30,0xC2,0x60, + 0x4A,0x68,0x42,0x62,0x89,0x68,0xC1,0x63,0x01,0x46,0x80,0x39,0x1E,0x48,0x06,0xF0, + 0x79,0xF9,0x00,0x20,0xA0,0x74,0x60,0x7B,0x0A,0x28,0x00,0xD9,0xA6,0x74,0x04,0xF0, + 0x0F,0xFD,0x1A,0x48,0x40,0x78,0x80,0x07,0x05,0xD1,0xF8,0x7B,0x00,0x28,0x02,0xD0, + 0xA6,0x74,0x00,0x20,0x60,0x74,0x10,0x49,0xA0,0x7E,0x20,0x39,0x48,0x75,0x0F,0x49, + 0x62,0x7E,0x08,0x39,0x08,0x46,0x20,0x30,0x0A,0x2A,0x01,0xD8,0x00,0x2D,0x04,0xD0, + 0x03,0x22,0xC2,0x70,0x02,0x71,0x0E,0x77,0x06,0xE0,0x09,0x4A,0xD3,0x7E,0xC3,0x70, + 0x13,0x7F,0x03,0x71,0x10,0x7D,0x08,0x77,0x60,0x7C,0x05,0x28,0x02,0xD9,0x00,0x20, + 0xC0,0x43,0xF8,0xBD,0x00,0x20,0xF8,0xBD,0xB8,0x04,0x00,0x20,0x20,0x06,0x00,0x20, + 0xCE,0x05,0x00,0x20,0x10,0x06,0x00,0x20,0x60,0x1F,0x00,0x20,0xF6,0x04,0x00,0x20, + 0x03,0x48,0x00,0x21,0x41,0x74,0xFF,0x22,0x20,0x30,0x42,0x76,0x01,0x77,0x70,0x47, + 0x58,0x06,0x00,0x20,0x10,0xB5,0x04,0x46,0x08,0x49,0x09,0x48,0x06,0xF0,0x7F,0xF9, + 0x06,0x49,0x40,0x31,0x0A,0x7A,0x22,0x70,0x04,0x4A,0x92,0x68,0x92,0x07,0x04,0xD5, + 0x0A,0x7A,0x00,0x2A,0x01,0xD0,0x01,0x22,0x8A,0x74,0x10,0xBD,0x18,0x06,0x00,0x20, + 0x60,0x1F,0x00,0x20,0xF0,0xB5,0x8D,0xB0,0x5A,0x48,0xFF,0x22,0x40,0x21,0x0C,0x90, + 0xFF,0xF7,0xD2,0xFE,0x57,0x48,0x90,0x21,0x6C,0x30,0xFF,0xF7,0xD4,0xFE,0x03,0x21, + 0x55,0x48,0xC9,0x02,0xC1,0x83,0x01,0x46,0x28,0x31,0x20,0x30,0x53,0x4B,0x01,0x60, + 0x50,0x4A,0x18,0x7D,0x08,0x3A,0x50,0x70,0x5C,0x7D,0x51,0x49,0x14,0x70,0x09,0x68, + 0xC0,0x01,0x8D,0x7E,0x95,0x70,0xD5,0x78,0x2D,0x09,0x2D,0x01,0xAD,0x1C,0xED,0xB2, + 0x2D,0x07,0x2D,0x0F,0xD5,0x70,0x90,0x80,0xE0,0x01,0xD0,0x80,0x08,0x46,0xD4,0x1D, + 0xE8,0x30,0xF9,0x34,0x60,0x60,0x34,0x30,0xA0,0x60,0xE8,0x38,0xE0,0x60,0x34,0x30, + 0x20,0x61,0x10,0x46,0x80,0x30,0x9E,0x6A,0x06,0x61,0x5E,0x6A,0x46,0x61,0x56,0x78, + 0x12,0x78,0x96,0x46,0x72,0x43,0x82,0x83,0x01,0x22,0x82,0x77,0x0A,0x46,0xFF,0x32, + 0x81,0x32,0x02,0x62,0x2A,0x09,0x94,0x46,0xD7,0x07,0x02,0x46,0x00,0x25,0x40,0x32, + 0x00,0x2F,0x05,0xD0,0x9F,0x6C,0x17,0x60,0x5F,0x6C,0x57,0x60,0x96,0x81,0x00,0xE0, + 0x95,0x81,0x66,0x46,0xB7,0x07,0x33,0x4E,0x06,0xD5,0x9F,0x6B,0x87,0x62,0x5F,0x6B, + 0xC7,0x62,0x77,0x46,0xB7,0x82,0x00,0xE0,0xB5,0x82,0xFF,0x31,0x95,0x73,0x88,0x31, + 0x11,0x61,0xB5,0x75,0x81,0x63,0x27,0x49,0x2B,0x48,0x08,0x39,0x4A,0x78,0x02,0x75, + 0x09,0x78,0x41,0x75,0x19,0x6D,0x01,0x60,0x59,0x6D,0x41,0x60,0x99,0x6D,0x81,0x60, + 0x23,0x4F,0x40,0x22,0x25,0x49,0x0C,0x98,0xFF,0xF7,0x3E,0xFE,0x30,0x22,0x24,0x49, + 0x68,0x46,0xFF,0xF7,0x39,0xFE,0x1B,0x48,0x06,0x22,0x69,0x46,0x08,0x38,0x00,0x23, + 0x06,0xF0,0xFE,0xF9,0x17,0x4D,0xFE,0x20,0x38,0x35,0xE8,0x74,0x29,0x46,0x28,0x22, + 0xD6,0x31,0x1C,0x48,0xFF,0xF7,0x28,0xFE,0x1A,0x48,0x29,0x46,0xBC,0x31,0x22,0x30, + 0x0A,0x7E,0x82,0x71,0x49,0x7E,0x18,0x4E,0xC1,0x71,0x30,0x1D,0xFF,0xF7,0x4F,0xFE, + 0x29,0x46,0x44,0x39,0x08,0x60,0x28,0x7E,0x00,0x28,0x01,0xD0,0x01,0x20,0xB0,0x74, + 0x0D,0x48,0x14,0x22,0x7A,0x21,0x18,0x30,0x05,0xF0,0x34,0xFD,0x38,0x68,0x00,0x79, + 0x03,0x28,0x02,0xD1,0x20,0x7D,0x03,0x28,0x02,0xD0,0x03,0x20,0x03,0xF0,0xB2,0xFB, + 0x0D,0xB0,0xF0,0xBD,0x20,0x06,0x00,0x20,0x38,0x07,0x00,0x20,0xAC,0x03,0x00,0x20, + 0x10,0x06,0x00,0x20,0xB8,0x06,0x00,0x20,0x60,0x1F,0x00,0x20,0xCE,0x05,0x00,0x20, + 0x14,0x6E,0x00,0x00,0x50,0x01,0x00,0x20,0x98,0x04,0x00,0x20,0x38,0xB5,0x00,0x23, + 0x1C,0xE0,0x54,0x22,0x5A,0x43,0x54,0x18,0x22,0x7C,0x12,0x07,0x15,0xD0,0x22,0x46, + 0x24,0x68,0x00,0x94,0x40,0x32,0x6C,0x46,0x24,0x88,0x15,0x89,0x64,0x19,0x0C,0x25, + 0x55,0x5F,0x6D,0x10,0x64,0x19,0x14,0x80,0x6C,0x46,0x64,0x88,0x55,0x89,0x64,0x19, + 0x0E,0x25,0x55,0x5F,0x6D,0x10,0x64,0x19,0x54,0x80,0x5B,0x1C,0x82,0x78,0x9A,0x42, + 0xDF,0xDC,0x38,0xBD,0xFF,0xB5,0x85,0xB0,0x9F,0x88,0x00,0x97,0x00,0x25,0x02,0x24, + 0x45,0x5F,0x7F,0x1E,0xDE,0x88,0x04,0x5F,0x02,0x97,0xBD,0x42,0x02,0xD8,0x70,0x1E, + 0x84,0x42,0x68,0xD9,0x00,0x2A,0x66,0xDD,0x0B,0x46,0x48,0x33,0x00,0x20,0x02,0x27, + 0x18,0x5E,0xDF,0x5F,0x40,0x00,0x7F,0x00,0x02,0x2A,0x05,0xD1,0x04,0x22,0x9A,0x5E, + 0x10,0x18,0x06,0x22,0x9A,0x5E,0xD7,0x19,0x00,0x9A,0x6B,0x00,0x9A,0x1A,0x53,0x1C, + 0x00,0x2B,0x01,0xDD,0x52,0x1C,0x00,0xE0,0xD2,0x43,0x94,0x46,0x62,0x00,0x92,0x1B, + 0x53,0x1C,0x00,0x2B,0x01,0xDD,0x52,0x1C,0x00,0xE0,0xD2,0x43,0x03,0x92,0x09,0x7C, + 0x09,0x09,0x49,0x1C,0x48,0x43,0x4F,0x43,0x01,0x90,0x00,0x28,0x0C,0xD0,0x00,0x99, + 0x60,0x46,0x40,0x1A,0x41,0x03,0x01,0x20,0x40,0x03,0x08,0x18,0x01,0x99,0x00,0x29, + 0x00,0xDC,0x49,0x42,0xFF,0xF7,0x6C,0xFD,0x04,0x90,0x00,0x2F,0x42,0xD0,0x03,0x98, + 0x80,0x1B,0x41,0x03,0x01,0x20,0x40,0x03,0x08,0x18,0x39,0x1E,0x00,0xDC,0x79,0x42, + 0xFF,0xF7,0x5E,0xFD,0x04,0x99,0x81,0x42,0x00,0xDC,0x01,0x46,0x01,0x20,0x40,0x03, + 0x81,0x42,0x00,0xDD,0x00,0x21,0x01,0x98,0x01,0x22,0x48,0x43,0x12,0x03,0x4F,0x43, + 0x80,0x18,0xB9,0x18,0x89,0x13,0x62,0x1A,0x80,0x13,0x94,0x46,0x02,0x9F,0x2B,0x1A, + 0x01,0x22,0xBB,0x42,0x03,0xD8,0x77,0x1E,0xBC,0x45,0x00,0xD8,0x92,0x1E,0x50,0x43, + 0x45,0x19,0x4A,0x43,0x14,0x19,0x00,0x20,0x01,0x46,0x00,0x2D,0x05,0xDD,0x02,0x9A, + 0x29,0x46,0x95,0x42,0x01,0xDB,0x00,0x99,0x49,0x1E,0x0E,0x9A,0x00,0x2C,0x11,0x80, + 0x04,0xDD,0x71,0x1E,0x20,0x46,0x8C,0x42,0x00,0xDB,0x70,0x1E,0x0E,0x99,0x48,0x80, + 0x09,0xB0,0xF0,0xBD,0x00,0x20,0xC5,0xE7,0xFE,0xB5,0x41,0x48,0x3F,0x4E,0x00,0x68, + 0x01,0x46,0x20,0x30,0x04,0x7C,0x45,0x7C,0x20,0x46,0x68,0x43,0x00,0x90,0x3D,0x48, + 0x80,0x08,0x80,0x00,0x01,0x90,0x94,0x20,0x47,0x5C,0x20,0x46,0x39,0x46,0xFF,0xF7, + 0xF9,0xFC,0x00,0x29,0x01,0xD1,0x00,0x20,0x00,0xE0,0x78,0x1A,0x00,0x19,0x00,0x05, + 0x02,0x0C,0x35,0x49,0x01,0xA8,0x04,0xF0,0x19,0xFC,0x34,0x48,0x33,0x49,0x84,0x61, + 0xC5,0x61,0x00,0x98,0x40,0x00,0x02,0x90,0x08,0x62,0x48,0x62,0x88,0x62,0x2C,0x48, + 0x00,0x68,0x80,0x30,0x07,0x7D,0x20,0x46,0x39,0x46,0xFF,0xF7,0xDB,0xFC,0x00,0x29, + 0x01,0xD1,0x00,0x20,0x00,0xE0,0x78,0x1A,0x00,0x19,0x28,0x49,0x68,0x43,0xC8,0x62, + 0x60,0x00,0x08,0x63,0x48,0x63,0x88,0x63,0xCC,0x63,0x24,0x4A,0x69,0x00,0x11,0x64, + 0x51,0x64,0x91,0x64,0xD5,0x64,0x21,0x4B,0x02,0x9A,0x1A,0x65,0x1A,0x46,0x50,0x65, + 0x10,0x46,0x11,0x25,0x00,0x24,0x07,0x46,0x81,0x65,0xA0,0x00,0xC1,0x19,0x88,0x69, + 0x18,0x31,0x82,0xB2,0x01,0xA8,0x04,0xF0,0xE1,0xFB,0x64,0x1C,0xE4,0xB2,0xAC,0x42, + 0xF3,0xD3,0x17,0x49,0x01,0x98,0xFF,0xF7,0x13,0xFD,0x16,0x49,0x02,0x46,0xB0,0x42, + 0x09,0xD2,0xB0,0x1A,0x80,0xB2,0x08,0x77,0x02,0x0A,0x4A,0x77,0x01,0x21,0x89,0x02, + 0x88,0x42,0x06,0xD8,0x02,0xE0,0x00,0x20,0x08,0x77,0x48,0x77,0x01,0x20,0x03,0xF0, + 0x71,0xFA,0x08,0x48,0x01,0x99,0xC0,0x1E,0x09,0x1A,0xFF,0xF7,0xE4,0xFC,0x01,0x99, + 0x09,0x48,0x08,0x60,0x03,0x20,0x02,0xF0,0x23,0xFA,0xFE,0xBD,0xF8,0x5F,0x00,0x20, + 0x10,0x06,0x00,0x20,0x9B,0x21,0x00,0x20,0xA4,0x03,0x00,0x20,0xAC,0x03,0x00,0x20, + 0xA4,0x04,0x00,0x20,0x32,0x01,0x00,0x20,0x5A,0xA5,0xAC,0xCA,0x70,0xB5,0x05,0x46, + 0x0C,0x46,0x00,0x2B,0x05,0xD0,0x01,0x46,0x52,0x00,0x20,0x46,0xFF,0xF7,0x9C,0xFC, + 0x70,0xBD,0x00,0x20,0x08,0xE0,0x43,0x00,0xE1,0x5E,0x4E,0x00,0x89,0x19,0xEE,0x5E, + 0x89,0x19,0x89,0x10,0xE1,0x52,0x40,0x1C,0x90,0x42,0xF4,0xDB,0x70,0xBD,0x70,0xB5, + 0x48,0x79,0x01,0x26,0x0D,0x46,0x00,0x28,0x03,0xD1,0x28,0x7A,0x00,0x28,0x00,0xD0, + 0x00,0x26,0x00,0x24,0x18,0x20,0x60,0x43,0x40,0x19,0x18,0x30,0x41,0x68,0x00,0x29, + 0x05,0xD0,0x10,0x22,0x82,0x5E,0x00,0x68,0x33,0x46,0xFF,0xF7,0xCF,0xFF,0x64,0x1C, + 0x05,0x2C,0xEF,0xDB,0x70,0xBD,0xF0,0xB5,0x86,0x46,0x8C,0x46,0x00,0x25,0x18,0x20, + 0x68,0x43,0x70,0x44,0x28,0x22,0x82,0x5E,0xC4,0x69,0x83,0x69,0x52,0x1E,0x16,0xD4, + 0x20,0x30,0x81,0x7A,0x00,0x29,0x03,0xD0,0x56,0x00,0xA7,0x5B,0x99,0x5B,0x0A,0xE0, + 0x61,0x46,0x00,0x29,0x04,0xD0,0x56,0x00,0x9F,0x5B,0xA1,0x5B,0x79,0x18,0x03,0xE0, + 0x56,0x00,0x9F,0x5B,0xA1,0x5B,0x79,0x1A,0x99,0x53,0x52,0x1E,0xE9,0xD5,0x6D,0x1C, + 0x05,0x2D,0xDC,0xDB,0xF0,0xBD,0xF3,0xB5,0x83,0xB0,0x04,0x98,0x04,0x9C,0xC0,0x78, + 0x74,0x34,0x00,0x07,0x00,0x0F,0x01,0x28,0x14,0xD0,0x21,0x46,0x04,0x9A,0x03,0x98, + 0x05,0xF0,0x32,0xFD,0x60,0x79,0x00,0x25,0x03,0x28,0x1F,0xD2,0x04,0x99,0x22,0x7A, + 0x09,0x7B,0x8A,0x42,0x1A,0xD2,0x04,0x99,0xE2,0x79,0x49,0x7B,0x8A,0x42,0x05,0xD2, + 0x40,0x1C,0x04,0xE0,0x00,0x20,0x60,0x71,0x05,0xB0,0xF0,0xBD,0x00,0x20,0x60,0x71, + 0x21,0x46,0x03,0x98,0xFF,0xF7,0x93,0xFF,0x20,0x7A,0x40,0x1C,0x20,0x72,0x00,0x20, + 0x20,0x71,0xE0,0x6A,0x01,0x25,0x00,0x78,0xA0,0x71,0x61,0xE0,0x04,0x9E,0x40,0x36, + 0xB0,0x7C,0x00,0x28,0x08,0xD0,0x01,0x21,0x20,0x46,0x03,0xF0,0x11,0xFF,0x00,0x20, + 0x20,0x71,0x04,0x98,0x40,0x7C,0x52,0xE0,0x00,0x21,0x20,0x46,0x03,0xF0,0x08,0xFF, + 0x32,0x7E,0x21,0x46,0x03,0x98,0x03,0xF0,0x63,0xFE,0x00,0x90,0x20,0x79,0x40,0x1C, + 0xC0,0xB2,0x20,0x71,0xA1,0x79,0x88,0x42,0x42,0xD3,0x00,0x98,0x00,0x28,0x07,0xD0, + 0x28,0x21,0x61,0x5E,0x60,0x6A,0x40,0x18,0x00,0x21,0x61,0x5E,0xFF,0xF7,0x13,0xFC, + 0x00,0x25,0x18,0x20,0x68,0x43,0x02,0x19,0x18,0x32,0x51,0x68,0x00,0x29,0x26,0xD0, + 0x90,0x68,0x01,0x90,0xD0,0x68,0x86,0x46,0x10,0x20,0x10,0x5E,0x1D,0xE0,0x43,0x00, + 0x01,0x9F,0xCA,0x5E,0xFE,0x5E,0xB4,0x46,0xB2,0x42,0x16,0xD0,0x76,0x46,0x36,0x56, + 0x32,0x2E,0x12,0xDC,0x31,0x27,0xFF,0x43,0xBE,0x42,0x0E,0xDB,0x00,0x9F,0x00,0x2F, + 0x05,0xD0,0x62,0x46,0xCA,0x52,0x00,0x22,0x73,0x46,0x1A,0x54,0x05,0xE0,0x62,0x45, + 0x01,0xDA,0x52,0x1C,0x00,0xE0,0x52,0x1E,0xCA,0x52,0x40,0x1E,0xDF,0xD5,0x6D,0x1C, + 0x05,0x2D,0xCE,0xDB,0x00,0x20,0x20,0x71,0xE0,0x6A,0x01,0x25,0x00,0x78,0xA0,0x71, + 0x21,0x46,0x04,0x9A,0x03,0x98,0x05,0xF0,0xC5,0xFC,0x00,0x21,0x20,0x46,0xFF,0xF7, + 0x3A,0xFF,0x28,0x46,0x80,0xE7,0x00,0x00,0x70,0xB5,0x04,0x46,0x74,0x34,0xFF,0x21, + 0x61,0x71,0x01,0x78,0x18,0x4A,0x49,0x1C,0x4D,0x08,0x41,0x78,0x49,0x1C,0x49,0x08, + 0x4D,0x43,0xFF,0x21,0x25,0x80,0x45,0x31,0x09,0x58,0x0A,0x60,0x01,0x46,0x01,0x22, + 0x20,0x46,0x00,0xF0,0x23,0xF8,0x60,0x6A,0x00,0x28,0x01,0xD0,0x00,0x20,0x70,0xBD, + 0x04,0xF0,0x74,0xFD,0x03,0x46,0x00,0x21,0x18,0x22,0x4A,0x43,0x12,0x19,0x18,0x32, + 0x10,0x26,0x96,0x5F,0x00,0x2E,0x06,0xDD,0x10,0x26,0xD0,0x60,0x96,0x5F,0x30,0x18, + 0x00,0x29,0x00,0xD1,0x40,0x19,0x49,0x1C,0x05,0x29,0xED,0xDB,0xC4,0x1A,0x20,0x46, + 0x04,0xF0,0x7A,0xFD,0x20,0x46,0x70,0xBD,0x47,0x08,0x00,0x00,0xF7,0xB5,0x05,0x46, + 0x82,0xB0,0x0F,0x78,0x48,0x78,0x00,0x90,0xE8,0x69,0x00,0x24,0x0E,0x46,0x00,0x28, + 0x33,0xD0,0x04,0xF0,0x4B,0xFD,0x02,0x46,0x28,0x6A,0x00,0x28,0x12,0xD1,0x04,0x98, + 0x00,0x28,0x16,0xD0,0x00,0x20,0x18,0x21,0x41,0x43,0x49,0x19,0xCB,0x69,0x00,0x2B, + 0x05,0xD0,0x63,0x00,0x9B,0x18,0x0B,0x62,0x28,0x23,0xCB,0x5E,0x1C,0x19,0x40,0x1C, + 0x05,0x28,0xF0,0xDB,0xF0,0x78,0x00,0x09,0x0F,0xD0,0xB0,0x68,0xC0,0x07,0x03,0xD0, + 0x0B,0xE0,0x01,0x20,0x68,0x72,0xF5,0xE7,0x60,0x00,0x80,0x18,0x28,0x61,0xE0,0x19, + 0x41,0x00,0x89,0x18,0x69,0x61,0x00,0x99,0x44,0x18,0x64,0x00,0x21,0x46,0x10,0x46, + 0xFF,0xF7,0x59,0xFB,0x20,0x46,0x04,0xF0,0x37,0xFD,0x20,0x46,0x05,0xB0,0xF0,0xBD, + 0xF8,0xB5,0x04,0x46,0x05,0x46,0x07,0x46,0x48,0x34,0x88,0x68,0x34,0x37,0x0E,0x46, + 0x40,0x07,0x1A,0xD5,0x00,0x21,0x04,0x20,0x79,0x5E,0x38,0x5E,0x00,0x22,0x09,0x1A, + 0xA2,0x5E,0x00,0x01,0x89,0x18,0x06,0x22,0x51,0x43,0x08,0x18,0x00,0x11,0x38,0x80, + 0x02,0x21,0xB8,0x5E,0x79,0x5E,0x02,0x22,0x09,0x1A,0xA2,0x5E,0x00,0x01,0x89,0x18, + 0x06,0x22,0x51,0x43,0x08,0x18,0x00,0x11,0x78,0x80,0x02,0x23,0x00,0x22,0x26,0x21, + 0x24,0x20,0xFB,0x5E,0xBA,0x5E,0x69,0x5E,0x28,0x5E,0x04,0xF0,0xCC,0xFF,0xC1,0x00, + 0x00,0x91,0x06,0x23,0x04,0x22,0x26,0x21,0x24,0x20,0xFB,0x5E,0xBA,0x5E,0x69,0x5E, + 0x28,0x5E,0x04,0xF0,0xC0,0xFF,0x00,0x99,0xC0,0x00,0x09,0x18,0x13,0xD0,0x00,0x9A, + 0x40,0x43,0x52,0x43,0x12,0x18,0x56,0x20,0x80,0x5D,0x41,0x43,0x10,0x46,0xFF,0xF7, + 0xCF,0xFA,0x0A,0x22,0xA2,0x5E,0x00,0x23,0x11,0x18,0x00,0x29,0x0B,0xD0,0x6F,0x7C, + 0xFF,0x09,0x02,0xD0,0x07,0xE0,0x00,0x20,0xF3,0xE7,0x52,0x43,0x40,0x43,0x10,0x18, + 0xFF,0xF7,0xBE,0xFA,0x03,0x46,0x1B,0xB2,0x63,0x81,0x20,0x36,0x30,0x7A,0x71,0x7A, + 0x40,0x00,0x4F,0x00,0x00,0x22,0xC1,0x1B,0x18,0x1A,0x02,0xD4,0x01,0x22,0x52,0x02, + 0x06,0xE0,0xD8,0x1B,0x00,0x28,0x03,0xDD,0x40,0x02,0xFF,0xF7,0xA9,0xFA,0x02,0x46, + 0x10,0x46,0x50,0x43,0x03,0x12,0xB0,0x7A,0x00,0xF0,0xDD,0xF8,0x07,0x46,0xF0,0x7A, + 0x00,0xF0,0xD9,0xF8,0x03,0x26,0x36,0x02,0xB2,0x1A,0x39,0x1A,0x5A,0x43,0x4A,0x43, + 0x01,0x21,0x49,0x04,0x51,0x18,0x89,0x14,0x0E,0x18,0x08,0x20,0x20,0x5E,0x81,0x19, + 0x1B,0xD0,0xB0,0x42,0x12,0xDA,0x2B,0x7C,0x04,0x22,0x1B,0x07,0x1B,0x0F,0x05,0x2B, + 0x00,0xD3,0x02,0x22,0x72,0x43,0x50,0x43,0x40,0x18,0xFF,0xF7,0x81,0xFA,0x00,0xB2, + 0x20,0x81,0xB0,0x42,0x00,0xDA,0x06,0x46,0x26,0x81,0x06,0xE0,0x40,0x43,0x76,0x43, + 0x80,0x19,0x40,0x1A,0xFF,0xF7,0x74,0xFA,0x20,0x81,0x08,0x20,0x20,0x5E,0x80,0x21, + 0x08,0x1A,0xF8,0xBD,0xF0,0xB5,0x04,0x46,0x06,0x46,0x0F,0x46,0x15,0x46,0x34,0x30, + 0x0E,0xC8,0x85,0xB0,0x48,0x34,0x68,0x46,0x05,0xF0,0xBC,0xFF,0x30,0x6C,0x08,0x21, + 0x01,0x90,0x61,0x5E,0x20,0x22,0x49,0x43,0x89,0x11,0x10,0x46,0x20,0x29,0x00,0xDC, + 0x08,0x46,0x00,0x2D,0x6B,0x46,0x06,0xD0,0x06,0x21,0x59,0x5E,0x12,0x1A,0x51,0x43, + 0x02,0x22,0x9A,0x5E,0x05,0xE0,0x04,0x21,0x59,0x5E,0x12,0x1A,0x51,0x43,0x00,0x22, + 0x9A,0x5E,0x6D,0x00,0x42,0x43,0x88,0x18,0x61,0x5F,0x2A,0x19,0x04,0x23,0x02,0x92, + 0x01,0x91,0xD3,0x5E,0x40,0x11,0x5A,0x10,0x10,0x18,0x0B,0x18,0x38,0x46,0x78,0x43, + 0x00,0x11,0x02,0x46,0x7A,0x43,0x9C,0x46,0xD2,0x11,0xF9,0x00,0xD3,0x00,0xD3,0x1A, + 0xC7,0x00,0xDB,0x19,0x4F,0x00,0xCF,0x19,0xDF,0x1B,0x01,0x23,0xDB,0x02,0xFF,0x18, + 0x63,0x46,0x5F,0x43,0xBC,0x46,0x53,0x00,0x5B,0x42,0x87,0x00,0xDB,0x19,0x0A,0x27, + 0x4F,0x43,0xDB,0x1B,0x01,0x27,0x7F,0x03,0x34,0x36,0xDB,0x19,0x77,0x5F,0xAE,0x19, + 0x7B,0x43,0x06,0x27,0x9C,0x44,0x78,0x43,0x93,0x00,0x1B,0x1A,0x4F,0x43,0xDF,0x19, + 0x01,0x23,0xDB,0x02,0xFF,0x18,0x04,0x23,0xF3,0x5E,0x03,0x93,0x5F,0x43,0x63,0x46, + 0xFB,0x18,0x97,0x00,0xD2,0x19,0x10,0x1A,0xCA,0x00,0x51,0x1A,0x40,0x18,0x08,0x21, + 0x71,0x5E,0x48,0x43,0xC0,0x18,0x03,0x21,0x09,0x03,0x4A,0x10,0x80,0x18,0xFF,0xF7, + 0xF7,0xF9,0x03,0x9B,0x01,0x99,0xC3,0x1A,0x02,0x9A,0x59,0x1A,0x91,0x80,0x63,0x53, + 0x05,0xB0,0xF0,0xBD,0xF8,0xB5,0x04,0x46,0x34,0x34,0x05,0x46,0x0E,0x46,0x48,0x35, + 0x17,0x46,0x02,0x21,0x8A,0x00,0x12,0x19,0x13,0x46,0x20,0x3B,0x49,0x1E,0xDB,0x69, + 0x49,0xB2,0x13,0x60,0x00,0x29,0xF5,0xDC,0x01,0x68,0x21,0x60,0x00,0x7C,0x00,0x07, + 0x00,0x0F,0x02,0x28,0x0E,0xD1,0x21,0x5E,0x06,0x23,0x04,0x22,0x00,0x20,0xE3,0x5E, + 0xA2,0x5E,0x20,0x5E,0x04,0xF0,0xAF,0xFE,0xC0,0x00,0x39,0x46,0xFF,0xF7,0xB2,0xF9, + 0x68,0x81,0x2E,0x81,0xF8,0xBD,0x32,0x28,0x04,0xDA,0x83,0x21,0xC9,0x01,0x48,0x43, + 0x00,0x14,0x70,0x47,0x64,0x21,0x08,0x1A,0xBF,0x21,0x40,0x43,0x09,0x02,0x48,0x43, + 0x00,0x15,0x80,0x21,0x08,0x1A,0x70,0x47,0x70,0xB5,0x53,0x00,0xC2,0x5E,0x1D,0x18, + 0x0C,0x68,0x8E,0x68,0x4B,0x68,0x04,0x20,0x21,0x46,0x28,0x5E,0x71,0x43,0x00,0x2B, + 0x10,0xD0,0x08,0x26,0xAE,0x5F,0x80,0x00,0x80,0x1A,0x80,0x1B,0x15,0x1A,0xAD,0x19, + 0x65,0x43,0x54,0x00,0x00,0x1B,0x58,0x43,0x28,0x18,0x48,0x43,0x00,0x0B,0x80,0x18, + 0x00,0xB2,0x70,0xBD,0x12,0x1A,0x51,0x43,0x09,0x0B,0x08,0x18,0xF8,0xE7,0x00,0x00, + 0xFF,0xB5,0x00,0x20,0x8B,0xB0,0x00,0x90,0x07,0x90,0x05,0x90,0x01,0x90,0x04,0x46, + 0x05,0x46,0x1A,0x79,0x98,0x79,0x04,0x90,0x58,0x79,0x03,0x90,0xD8,0x79,0x02,0x90, + 0x0D,0x98,0x1E,0x46,0x40,0x78,0x06,0x90,0x00,0x20,0x08,0x90,0x0C,0x98,0x00,0x28, + 0x10,0xD1,0x04,0x98,0x52,0x1E,0x40,0x1C,0x04,0x90,0x03,0x98,0x40,0x1E,0x03,0x90, + 0x02,0x98,0x03,0x99,0x40,0x1C,0x02,0x90,0x40,0x1A,0x40,0x1C,0x06,0x90,0x50,0x43, + 0x40,0x18,0x08,0x90,0x00,0x20,0x86,0x46,0x5B,0xE0,0x03,0x99,0x55,0xE0,0x06,0x98, + 0x50,0x43,0x43,0x18,0x08,0x98,0x18,0x1A,0x03,0xB2,0x0B,0x98,0x5F,0x00,0xC0,0x5F, + 0x00,0x28,0x49,0xDD,0x0C,0x9F,0x00,0x2F,0x0E,0xD0,0xFB,0x5C,0x37,0x7B,0xBF,0x08, + 0xBB,0x42,0x01,0xD0,0x0F,0x2B,0x3F,0xD3,0x15,0x2B,0x00,0xD1,0x40,0x10,0x40,0x23, + 0x40,0x28,0x00,0xDC,0x03,0x46,0x9E,0x44,0x07,0x9B,0x83,0x42,0x03,0xDA,0x03,0xB2, + 0x07,0x93,0x32,0x72,0x71,0x72,0x01,0x23,0x5B,0x02,0x98,0x42,0x00,0xDA,0x03,0x46, + 0x5B,0x43,0x00,0x98,0x9C,0x46,0xC0,0x18,0x00,0x90,0x18,0x46,0x5B,0x08,0x48,0x43, + 0xC0,0x18,0x09,0x93,0x05,0x9B,0xC0,0x01,0x18,0x41,0x04,0xE0,0x05,0x9B,0x64,0x10, + 0x5B,0x1C,0x40,0x10,0x05,0x93,0x01,0x23,0x27,0x18,0x1B,0x06,0x9F,0x42,0xF5,0xDA, + 0x24,0x18,0x60,0x46,0x09,0x9B,0x50,0x43,0xC0,0x18,0x01,0x9B,0xC0,0x01,0x18,0x41, + 0x04,0xE0,0x01,0x9B,0x6D,0x10,0x5B,0x1C,0x40,0x10,0x01,0x93,0x01,0x23,0x2F,0x18, + 0x1B,0x06,0x9F,0x42,0xF5,0xDA,0x2D,0x18,0x49,0x1C,0x02,0x98,0x81,0x42,0xA6,0xDD, + 0x52,0x1C,0x04,0x98,0x82,0x42,0xA0,0xDD,0x0C,0x98,0x00,0x28,0x0B,0xD0,0x71,0x46, + 0x15,0x4A,0xFF,0x20,0x89,0x1D,0x91,0x42,0x04,0xDA,0x70,0x46,0x0C,0x21,0x80,0x1D, + 0xFF,0xF7,0xF6,0xF8,0xF0,0x72,0x00,0x98,0x00,0x28,0x19,0xDD,0x01,0x46,0x05,0x98, + 0x01,0x41,0x20,0x46,0xFF,0xF7,0xEC,0xF8,0x04,0x46,0x00,0x99,0x01,0x98,0x01,0x41, + 0x28,0x46,0xFF,0xF7,0xE5,0xF8,0x05,0x46,0x01,0x21,0x20,0x46,0x0D,0x9A,0x00,0xF0, + 0x25,0xFC,0x30,0x80,0x00,0x21,0x28,0x46,0x0D,0x9A,0x00,0xF0,0x1F,0xFC,0x70,0x80, + 0x00,0x20,0x0F,0xB0,0xF0,0xBD,0x00,0x00,0xF4,0x0B,0x00,0x00,0xFF,0xB5,0x10,0x88, + 0x89,0xB0,0x15,0x46,0x00,0x28,0x7E,0xD0,0x0A,0x99,0x0A,0x9A,0x49,0x78,0x12,0x78, + 0x10,0x20,0x51,0x43,0x09,0x09,0x10,0x29,0x00,0xD3,0x08,0x46,0x04,0x90,0x04,0xF0, + 0xBD,0xFA,0x00,0x90,0x0A,0x98,0x80,0x78,0x80,0x1C,0x07,0x90,0x00,0x20,0x06,0x90, + 0x28,0x46,0x08,0x30,0x05,0x90,0x00,0x20,0xB8,0xE0,0xC4,0x00,0x05,0x98,0x26,0x18, + 0x0A,0x98,0xB1,0x79,0x40,0x7F,0x81,0x42,0x6F,0xD9,0x06,0x9B,0x07,0x98,0x83,0x42, + 0x13,0xDB,0xFF,0x21,0x00,0x20,0x08,0xE0,0x0C,0x9A,0x07,0x01,0xBA,0x18,0x52,0x7B, + 0x8A,0x42,0x01,0xDA,0x11,0x46,0x03,0x46,0x40,0x1C,0x07,0x9A,0x90,0x42,0xF3,0xDB, + 0x60,0x19,0x80,0x7B,0x88,0x42,0x58,0xDB,0x01,0xE0,0x58,0x1C,0x06,0x90,0x0C,0x98, + 0x19,0x01,0x0C,0x18,0x20,0x7B,0x31,0x79,0x80,0x07,0x89,0x08,0x80,0x0F,0x89,0x00, + 0x08,0x43,0x20,0x73,0x31,0x79,0x40,0x08,0xC9,0x07,0x40,0x00,0xC9,0x0F,0x08,0x43, + 0x20,0x73,0xFD,0x21,0x08,0x40,0x31,0x79,0x89,0x07,0xC9,0x0F,0x49,0x00,0x08,0x43, + 0x20,0x73,0xB0,0x79,0x60,0x73,0x70,0x79,0xA0,0x72,0x00,0x20,0xE0,0x72,0x30,0x68, + 0x60,0x60,0xF0,0x78,0x71,0x78,0x32,0x78,0x40,0x1A,0xB1,0x78,0x40,0x1C,0x89,0x1A, + 0x32,0x79,0x49,0x1C,0xD2,0x07,0x75,0xD1,0x02,0x46,0x04,0x9B,0x4A,0x43,0x9A,0x42, + 0x70,0xDA,0x0A,0x9A,0x92,0x68,0x92,0x06,0x6C,0xD5,0x80,0x1C,0x89,0x1C,0x02,0x90, + 0x01,0x91,0x48,0x43,0x41,0x00,0x00,0x98,0xFF,0xF7,0x8D,0xF8,0x30,0x78,0x09,0x99, + 0x40,0x1E,0x14,0x22,0x00,0xE0,0x5B,0xE0,0x8A,0x56,0x71,0x78,0x50,0x43,0x40,0x18, + 0x40,0x1E,0x86,0x46,0x01,0x99,0x00,0x20,0x01,0x23,0x49,0x1E,0x08,0x91,0x2A,0xE0, + 0x02,0x9A,0x01,0x21,0x52,0x1E,0x94,0x46,0x21,0xE0,0x3D,0xE0,0x09,0x9A,0x14,0x26, + 0x96,0x57,0x72,0x46,0x5E,0x43,0x8A,0x18,0xB2,0x18,0x6E,0x68,0x27,0x7B,0xB6,0x5C, + 0xBF,0x08,0xBE,0x42,0x01,0xD0,0x0F,0x2E,0x10,0xD3,0x09,0x9E,0x52,0x00,0x36,0x68, + 0xB2,0x5E,0x00,0x2A,0x04,0xDD,0x40,0x26,0x40,0x2A,0x00,0xDC,0x16,0x46,0x30,0x18, + 0x02,0x9E,0x5E,0x43,0x76,0x18,0x77,0x00,0x00,0x9E,0xF2,0x53,0x49,0x1C,0x61,0x45, + 0xDC,0xDB,0x08,0x99,0x5B,0x1C,0x8B,0x42,0xD2,0xDB,0x15,0x4B,0xFF,0x21,0x82,0x1D, + 0x9A,0x42,0x04,0xDA,0x0C,0x21,0x80,0x1D,0xFF,0xF7,0x0A,0xF8,0x01,0x46,0xE1,0x72, + 0x00,0x9B,0x01,0x9A,0x18,0x46,0x02,0x99,0x03,0xF0,0xD6,0xF8,0x23,0x46,0x00,0x21, + 0x0A,0x9A,0x00,0x98,0xFF,0xF7,0x6C,0xFE,0x03,0x98,0x40,0x1C,0x00,0x21,0x03,0x90, + 0x69,0x5E,0x81,0x42,0x01,0xDD,0x40,0xE7,0x04,0xE0,0x04,0xF0,0x05,0xFA,0x06,0x98, + 0x0D,0xB0,0xF0,0xBD,0x09,0x98,0x69,0x68,0x00,0x68,0x23,0x46,0x0A,0x9A,0xE9,0xE7, + 0xF4,0x0B,0x00,0x00,0xFF,0xB5,0x86,0x46,0x00,0x20,0x85,0xB0,0x00,0x90,0x01,0x90, + 0x04,0x46,0x06,0x46,0x05,0x46,0x0F,0x78,0x88,0x78,0x8C,0x46,0x03,0x90,0x2F,0xE0, + 0x60,0x46,0x43,0x78,0xC0,0x78,0x02,0x90,0x26,0xE0,0x71,0x46,0x14,0x20,0x08,0x56, + 0x0A,0x68,0x78,0x43,0xC0,0x18,0x41,0x00,0x52,0x5E,0x00,0x2A,0x1A,0xDD,0x0E,0x99, + 0x08,0x5C,0x08,0x99,0x08,0x40,0x07,0x99,0x88,0x42,0x01,0xD0,0x15,0x28,0x11,0xD1, + 0x00,0x99,0x89,0x18,0x00,0x91,0x11,0x46,0x51,0x43,0x4D,0x19,0x11,0x46,0xB2,0x42, + 0x00,0xDC,0x31,0x46,0x0E,0x46,0x01,0x99,0x49,0x1C,0x01,0x91,0x10,0x99,0x8A,0x42, + 0x00,0xDB,0x64,0x1C,0x02,0x98,0x5B,0x1C,0x98,0x42,0xD6,0xDA,0x03,0x98,0x7F,0x1C, + 0xB8,0x42,0xCD,0xDA,0x10,0x99,0x00,0x20,0x8E,0x42,0x36,0xDB,0x0F,0x9F,0x0A,0x20, + 0x47,0x43,0x39,0x46,0x00,0x98,0xFE,0xF7,0x9B,0xFF,0x40,0x1C,0x40,0x21,0x40,0x28, + 0x00,0xDA,0x01,0x46,0x88,0x00,0x01,0x46,0xFF,0x22,0x41,0x43,0x81,0x32,0x10,0x1A, + 0x41,0x43,0xC8,0x12,0x01,0x21,0x89,0x02,0x46,0x18,0x01,0x99,0x08,0x20,0x09,0x19, + 0x08,0x29,0x00,0xDA,0x08,0x46,0x80,0x01,0x05,0xF0,0xDC,0xF9,0x68,0x43,0x00,0x99, + 0xFE,0xF7,0x7E,0xFF,0x0A,0x21,0x48,0x43,0x39,0x46,0xFE,0xF7,0x79,0xFF,0xAA,0x28, + 0x00,0xDB,0xAA,0x20,0x01,0x46,0xFF,0x22,0x41,0x43,0x01,0x32,0x10,0x1A,0x41,0x43, + 0x88,0x13,0x46,0x43,0x2B,0x20,0x46,0x43,0x70,0x14,0x09,0xB0,0xF0,0xBD,0x00,0x00, + 0xF7,0xB5,0x96,0xB0,0x17,0x98,0xC0,0x30,0x09,0x90,0xC0,0x68,0x00,0x28,0x7E,0xD0, + 0x16,0x98,0x15,0x26,0x14,0x24,0x86,0x57,0x04,0x57,0x07,0x68,0x09,0x98,0x21,0xC8, + 0x0E,0x90,0x04,0xF0,0x53,0xF9,0x03,0x46,0x0F,0x90,0x32,0x46,0x21,0x46,0x38,0x46, + 0x03,0xF0,0x22,0xF8,0x0F,0x98,0x06,0x90,0x00,0x20,0x31,0x46,0x61,0x43,0x01,0x91, + 0x12,0xE0,0x41,0x00,0x0F,0x9A,0x7B,0x5E,0x51,0x5E,0x49,0x10,0x5A,0x1A,0x14,0x32, + 0x00,0x21,0x02,0x2A,0x04,0xDB,0xFF,0x21,0xFF,0x2A,0x00,0xDA,0x11,0x46,0x09,0xB2, + 0x06,0x9A,0x11,0x54,0x01,0x99,0x40,0x1C,0x81,0x42,0xEA,0xDC,0x30,0x46,0x60,0x43, + 0x04,0xF0,0x4A,0xF9,0x04,0xF0,0x2A,0xF9,0x04,0x46,0xF0,0x20,0x04,0xF0,0x44,0xF9, + 0xF0,0x21,0x20,0x46,0xFE,0xF7,0x5F,0xFF,0x09,0x98,0x00,0x21,0xC0,0x68,0x00,0x90, + 0x41,0x5E,0x00,0x22,0x8C,0x46,0x10,0x46,0x16,0xE0,0x00,0x99,0xC3,0x00,0x5B,0x18, + 0x19,0x7B,0xCE,0x07,0xF6,0x0F,0x01,0x01,0x76,0x1C,0x09,0x19,0x8E,0x72,0xDF,0x68, + 0x9E,0x68,0x4F,0x60,0x0E,0x60,0x0E,0x79,0x76,0x08,0x76,0x00,0x0E,0x71,0xD9,0x7B, + 0x91,0x42,0x00,0xDD,0x0A,0x46,0x40,0x1C,0x61,0x46,0x60,0x45,0xE5,0xDB,0x09,0x98, + 0x40,0x69,0x40,0x30,0xC2,0x73,0x0E,0x00,0x03,0xD1,0x07,0x21,0x28,0x46,0xFE,0xF7, + 0x32,0xFF,0x01,0x98,0x5A,0x21,0x40,0x10,0x5A,0x28,0x00,0xDD,0x01,0x46,0x09,0x98, + 0x11,0x96,0x40,0x69,0x02,0x7F,0x00,0x2A,0x78,0xD0,0x40,0x30,0xC0,0x7B,0x88,0x42, + 0x74,0xDC,0x76,0xB2,0x68,0x46,0x06,0x74,0x00,0x27,0x38,0x46,0x00,0xE0,0xFF,0xE1, + 0x05,0x96,0x0E,0xE0,0x02,0x01,0x11,0x19,0x8B,0x78,0xA2,0x5C,0x9A,0x1A,0xCB,0x78, + 0x49,0x78,0x59,0x1A,0x51,0x18,0x89,0x1C,0xB9,0x42,0x00,0xDC,0x39,0x46,0x0F,0x46, + 0x40,0x1C,0xB0,0x42,0xEE,0xDB,0x00,0x2F,0x58,0xD0,0x04,0xF0,0xC7,0xF8,0x10,0x90, + 0x38,0x01,0xC0,0x1B,0x18,0x30,0x04,0xF0,0xDF,0xF8,0x2F,0xE0,0x68,0x46,0x10,0x27, + 0xC7,0x57,0x0F,0x2F,0x2C,0xDA,0x30,0x46,0x00,0x01,0x10,0x38,0x00,0x19,0x84,0x46, + 0x80,0x7A,0x76,0x1E,0x01,0x28,0x21,0xD0,0x38,0x01,0x00,0x19,0x00,0x21,0x01,0x60, + 0x41,0x60,0x81,0x60,0xC1,0x60,0x01,0x79,0xBA,0x00,0x89,0x07,0x89,0x0F,0x11,0x43, + 0x01,0x71,0x00,0x23,0x17,0x9A,0x03,0x93,0x10,0x99,0x6B,0x46,0x07,0xC3,0x63,0x46, + 0x0E,0x9A,0x06,0x99,0x16,0x98,0x02,0xF0,0x7B,0xF8,0x00,0x28,0x06,0xD0,0x02,0xDD, + 0x7F,0x1C,0x68,0x46,0x07,0x74,0x68,0x46,0x10,0x26,0x86,0x57,0x00,0x2E,0xCD,0xD1, + 0x10,0x22,0x68,0x46,0x82,0x56,0x00,0x21,0x08,0x46,0x06,0xE0,0x03,0x01,0x1B,0x19, + 0xDB,0x89,0x00,0x2B,0x00,0xD0,0x49,0x1C,0x40,0x1C,0x90,0x42,0xF6,0xDB,0x00,0x20, + 0x28,0x56,0x90,0x42,0x32,0xDD,0x05,0x22,0xAA,0x56,0x05,0x98,0x82,0x42,0x2D,0xD1, + 0x04,0x20,0x28,0x56,0x88,0x42,0x29,0xDA,0x00,0x27,0x22,0xE0,0x19,0xE1,0x0F,0x2E, + 0x24,0xDA,0x38,0x01,0x00,0x19,0x84,0x46,0xC0,0x89,0x00,0x28,0x18,0xD0,0x30,0x01, + 0x00,0x19,0x01,0x79,0xB2,0x00,0x89,0x07,0x89,0x0F,0x11,0x43,0x01,0x71,0x50,0x23, + 0x17,0x9A,0x03,0x93,0x10,0x99,0x6B,0x46,0x07,0xC3,0x63,0x46,0x0E,0x9A,0x06,0x99, + 0x16,0x98,0x02,0xF0,0x35,0xF8,0x00,0x28,0x02,0xD0,0x76,0x1C,0x68,0x46,0x06,0x74, + 0x7F,0x1C,0x68,0x46,0x10,0x26,0x86,0x57,0xB7,0x42,0xD8,0xDB,0x09,0x98,0x40,0x69, + 0x12,0x90,0x80,0x68,0xC0,0x05,0x79,0xD5,0x00,0x20,0x69,0x46,0x10,0x26,0x28,0x56, + 0x8E,0x57,0xB0,0x42,0x03,0xDB,0x02,0x20,0x28,0x56,0xB0,0x42,0x6E,0xDA,0xFF,0x22, + 0x0F,0x21,0x05,0xA8,0xFE,0xF7,0x68,0xFE,0x00,0x21,0x14,0x96,0x57,0xE0,0x08,0x01, + 0x00,0x19,0x02,0x79,0xD2,0x07,0x51,0xD0,0x12,0x9A,0x84,0x46,0x92,0x78,0x00,0x20, + 0x13,0x92,0x49,0xE0,0x09,0x9A,0x13,0x69,0x54,0x22,0x42,0x43,0x16,0x46,0x1F,0x46, + 0x10,0x36,0x9B,0x5D,0x1B,0x07,0x3D,0xD0,0x36,0x1F,0xBB,0x5D,0x9B,0x07,0x39,0xD4, + 0x12,0x1D,0xBA,0x18,0x13,0x78,0x66,0x46,0x03,0x93,0x36,0x78,0x76,0x1C,0xB3,0x42, + 0x30,0xD8,0x53,0x78,0x66,0x46,0x01,0x93,0x76,0x78,0x76,0x1C,0xB3,0x42,0x29,0xD8, + 0x93,0x78,0x66,0x46,0x02,0x93,0xB6,0x78,0x76,0x1E,0xB3,0x42,0x22,0xDB,0xD2,0x78, + 0x63,0x46,0x00,0x92,0xDB,0x78,0x5B,0x1E,0x9A,0x42,0x1B,0xDB,0x05,0xAB,0x5A,0x56, + 0x56,0x1C,0x16,0xD0,0x54,0x23,0x5A,0x43,0x03,0x9E,0x02,0x9B,0x12,0x1D,0xBA,0x18, + 0x9B,0x1B,0x01,0x9F,0x00,0x9E,0xF6,0x1B,0x73,0x43,0x96,0x78,0x17,0x78,0xF6,0x1B, + 0xD7,0x78,0x52,0x78,0xBA,0x1A,0x56,0x43,0xB3,0x42,0x03,0xDD,0x05,0xAA,0x50,0x54, + 0x00,0xE0,0x58,0x54,0x13,0x9A,0x40,0x1C,0x82,0x42,0xB3,0xDC,0x49,0x1C,0x14,0x98, + 0x81,0x42,0xA4,0xDB,0x00,0x20,0x0A,0x90,0x0B,0x90,0x0C,0x90,0x0D,0x90,0x40,0x1E, + 0x03,0x90,0x14,0x98,0x00,0x26,0x40,0x1E,0x15,0x90,0x6A,0xE0,0x6B,0xE0,0x0A,0xA8, + 0x80,0x5D,0x01,0x28,0x63,0xD0,0x03,0x98,0x40,0x1C,0x03,0x90,0x05,0xA8,0x80,0x57, + 0x40,0x1C,0x5C,0xD0,0x77,0x1C,0x4A,0xE0,0x05,0xA8,0x81,0x57,0xC0,0x57,0x81,0x42, + 0x44,0xD1,0x30,0x01,0x00,0x19,0x12,0x90,0x41,0x79,0x38,0x01,0x03,0x19,0x5A,0x79, + 0x91,0x42,0x3B,0xD1,0x00,0x90,0x12,0x98,0x01,0x93,0x13,0x90,0x00,0x79,0x14,0x21, + 0x82,0x08,0x16,0x98,0x41,0x56,0x0E,0x98,0x02,0xF0,0xD3,0xFA,0x00,0x98,0x01,0x9B, + 0x21,0x5C,0x5A,0x78,0x12,0x98,0x04,0xF0,0x19,0xFE,0x01,0x9B,0x12,0x98,0xDA,0x78, + 0x99,0x78,0x04,0xF0,0x13,0xFE,0x13,0x98,0x01,0x9B,0xC0,0x79,0xD9,0x79,0x41,0x18, + 0x13,0x98,0xC1,0x71,0x09,0x98,0x0E,0x99,0x40,0x69,0x03,0x7D,0x82,0x7D,0x68,0x46, + 0x0E,0xC0,0x13,0x98,0xFF,0x23,0x00,0x79,0x12,0x99,0x82,0x08,0x16,0x98,0xFF,0xF7, + 0x99,0xFD,0x01,0x46,0x13,0x98,0x81,0x71,0x01,0x20,0x0A,0xA9,0xC8,0x55,0x69,0x46, + 0x08,0x7C,0x40,0x1E,0x08,0x74,0xFF,0x20,0x05,0xA9,0xC8,0x55,0x7F,0x1C,0x14,0x98, + 0x87,0x42,0xB1,0xDB,0x03,0x98,0x86,0x42,0x09,0xD0,0x31,0x01,0x09,0x19,0x0A,0x46, + 0x8C,0xCA,0x00,0x01,0x00,0x19,0xC9,0x68,0x8C,0xC0,0x0C,0x38,0xC1,0x60,0x15,0x98, + 0x76,0x1C,0x86,0x42,0x93,0xDB,0x10,0x98,0x03,0xF0,0x96,0xFF,0x68,0x46,0x10,0x26, + 0x86,0x57,0x00,0x21,0x08,0x46,0x07,0xE0,0x02,0x01,0x12,0x19,0xD2,0x89,0x00,0x2A, + 0x00,0xD0,0x49,0x1C,0x40,0x1C,0x40,0xB2,0xB0,0x42,0xF5,0xDB,0x05,0x22,0xAA,0x56, + 0x11,0x98,0x82,0x42,0x09,0xD0,0x2E,0x70,0x01,0x20,0x68,0x70,0x00,0x20,0xA8,0x70, + 0xE8,0x70,0x29,0x71,0x11,0x98,0x68,0x71,0x20,0xE0,0x00,0x20,0x28,0x56,0xB0,0x42, + 0x2C,0x48,0x28,0x56,0x16,0xD0,0x03,0x28,0x08,0xDA,0x2E,0x70,0x02,0x20,0x28,0x56, + 0xB0,0x42,0x01,0xD1,0xE8,0x78,0x10,0xE0,0x00,0x20,0x0E,0xE0,0x02,0x21,0x69,0x56, + 0xB1,0x42,0x02,0xD1,0xE9,0x78,0x49,0x1C,0x01,0xE0,0xAE,0x70,0x00,0x21,0xE9,0x70, + 0x40,0x10,0x02,0xE0,0x7F,0x28,0x01,0xDA,0x40,0x1C,0x68,0x70,0x09,0x98,0xC2,0x68, + 0x00,0x20,0x10,0x80,0x24,0xE0,0x01,0x01,0x09,0x19,0x8B,0x7A,0x00,0x2B,0x1E,0xD0, + 0x00,0x23,0xD3,0x5E,0x0F,0x2B,0x1A,0xDA,0xDB,0x00,0x9B,0x18,0x4F,0x68,0x0D,0x68, + 0xDF,0x60,0x9D,0x60,0x00,0x23,0xD3,0x5E,0x0F,0x79,0xDB,0x00,0x9B,0x18,0x1D,0x7B, + 0xBF,0x08,0xAD,0x07,0xAD,0x0F,0xBF,0x00,0x3D,0x43,0x1D,0x73,0x00,0x23,0xD3,0x5E, + 0x49,0x79,0xDB,0x00,0x9B,0x18,0x59,0x73,0x11,0x88,0x49,0x1C,0x11,0x80,0x40,0x1C, + 0xB0,0x42,0xD8,0xDB,0x09,0x98,0x18,0x9B,0x41,0x69,0x16,0x98,0xFF,0xF7,0x16,0xFC, + 0x05,0x46,0x20,0x46,0x03,0xF0,0x20,0xFF,0x0F,0x98,0x03,0xF0,0x1D,0xFF,0x28,0x46, + 0x19,0xB0,0xF0,0xBD,0x01,0x00,0x00,0x00,0xF8,0xB5,0x04,0x46,0x04,0xF0,0x7C,0xF9, + 0x66,0x78,0x25,0x78,0xFF,0x34,0x41,0x34,0x64,0x68,0x03,0xF0,0xCF,0xFE,0x27,0x46, + 0xC0,0x37,0x38,0x60,0x28,0x46,0x70,0x43,0x03,0xF0,0xE6,0xFE,0x03,0xF0,0xC6,0xFE, + 0x78,0x60,0x07,0x20,0x03,0xF0,0xE0,0xFE,0x07,0x21,0x78,0x68,0xFE,0xF7,0xFB,0xFC, + 0x01,0x48,0x60,0x60,0x00,0x20,0xF8,0xBD,0xE1,0x11,0x00,0x00,0xF8,0xB5,0x05,0x46, + 0x50,0x7E,0x00,0x29,0x01,0xD0,0x00,0x09,0x01,0xE0,0x00,0x07,0x00,0x0F,0x00,0x90, + 0x00,0x29,0x01,0xD0,0x94,0x7E,0x00,0xE0,0xD4,0x7E,0x00,0x29,0x01,0xD0,0x97,0x88, + 0x00,0xE0,0xD7,0x88,0x69,0x00,0xC8,0x1B,0x00,0x28,0x00,0xDC,0x78,0x1A,0x38,0x1A, + 0x80,0x26,0x40,0x10,0x30,0x1A,0x00,0x28,0x05,0xDD,0x40,0x00,0x60,0x43,0x31,0x46, + 0xFE,0xF7,0x96,0xFC,0x04,0x19,0x68,0x02,0x39,0x02,0x40,0x1A,0xFF,0x30,0x39,0x46, + 0x01,0x30,0x81,0x39,0xFE,0xF7,0x8C,0xFC,0xFF,0x21,0xC9,0x43,0x88,0x42,0x03,0xDD, + 0x49,0x42,0xFF,0x28,0x00,0xDC,0x01,0x46,0x08,0x46,0x48,0x43,0x02,0x12,0x00,0x20, + 0x02,0xE0,0x52,0x43,0x12,0x12,0x40,0x1C,0x00,0x9B,0x98,0x42,0xF9,0xDB,0x00,0x29, + 0x00,0xDA,0x52,0x42,0x70,0x10,0x50,0x43,0x60,0x43,0x00,0x02,0x64,0x21,0xFE,0xF7, + 0x6F,0xFC,0x29,0x04,0x08,0x18,0x00,0x14,0xF8,0xBD,0xF0,0xB5,0x83,0x78,0x20,0x31, + 0x00,0x25,0x00,0x2A,0x28,0xD1,0x8E,0x7B,0x0A,0x22,0xC4,0x88,0x56,0x43,0xAA,0x1E, + 0xB4,0x42,0x21,0xD3,0x4E,0x7B,0x0A,0x27,0x7E,0x43,0xB4,0x42,0x1C,0xD8,0x01,0x2B, + 0x06,0xD0,0x01,0x23,0x83,0x70,0x83,0x8A,0x03,0x81,0xC3,0x8A,0x43,0x81,0x15,0xE0, + 0x82,0x8A,0x03,0x89,0x44,0x89,0xD2,0x1A,0xC3,0x8A,0x09,0x7C,0x1B,0x1B,0x52,0x43, + 0x5B,0x43,0xC9,0x01,0xD2,0x18,0x49,0x43,0x8A,0x42,0x01,0xDA,0x01,0x22,0x01,0xE0, + 0x00,0x22,0xD2,0x43,0x85,0x70,0x0C,0xE0,0x01,0x2B,0x0A,0xD1,0x09,0x7B,0x83,0x88, + 0x0A,0x24,0x61,0x43,0x8B,0x42,0x04,0xD9,0x00,0x2A,0x02,0xDA,0x85,0x70,0x00,0x22, + 0x01,0xE0,0x51,0x1C,0x00,0xDB,0x85,0x70,0x50,0xB2,0xF0,0xBD,0xF7,0xB5,0x05,0x46, + 0xC0,0x35,0x84,0xB0,0x29,0x69,0x68,0x69,0x02,0x91,0x81,0x88,0x00,0x24,0x49,0x1E, + 0x00,0x91,0xC1,0x88,0x20,0x30,0x49,0x1E,0x01,0x91,0x03,0x90,0xC1,0x7B,0x64,0x20, + 0x40,0x1A,0x00,0x99,0x07,0x46,0x48,0x43,0xC8,0x21,0xFE,0xF7,0xFB,0xFB,0x06,0x46, + 0x01,0x99,0x38,0x46,0x48,0x43,0xC8,0x21,0xFE,0xF7,0xF4,0xFB,0x03,0x46,0x00,0x21, + 0x22,0xE0,0x54,0x20,0x02,0x9A,0x48,0x43,0x82,0x18,0x10,0x7C,0x07,0x07,0x03,0x98, + 0x3F,0x0F,0xC0,0x78,0x87,0x42,0x16,0xD9,0x20,0x27,0x05,0x98,0xD7,0x5F,0x07,0x60, + 0x22,0x20,0x10,0x5E,0x06,0x9A,0x10,0x60,0x05,0x9A,0x12,0x68,0xB2,0x42,0x0A,0xD3, + 0x98,0x42,0x08,0xD3,0x00,0x9F,0xBF,0x1B,0xBA,0x42,0x04,0xD8,0x01,0x9A,0xD2,0x1A, + 0x90,0x42,0x00,0xD8,0x64,0x1C,0x49,0x1C,0x68,0x69,0x80,0x78,0x88,0x42,0xD8,0xDC, + 0x20,0x46,0x07,0xB0,0xF0,0xBD,0x00,0x00,0x70,0xB5,0x0D,0x4C,0x0D,0x4D,0x20,0x68, + 0x20,0x30,0x01,0x7C,0x40,0x7C,0x41,0x43,0x49,0x00,0x28,0x6D,0xFE,0xF7,0x0B,0xFC, + 0x20,0x68,0x20,0x30,0x00,0x7C,0x41,0x00,0x68,0x6D,0xFE,0xF7,0x04,0xFC,0x20,0x68, + 0x20,0x30,0x40,0x7C,0x41,0x00,0xA8,0x6D,0xFE,0xF7,0xFD,0xFB,0x70,0xBD,0x00,0x00, + 0x10,0x06,0x00,0x20,0xAC,0x03,0x00,0x20,0xC3,0x07,0x00,0x21,0x09,0x4A,0x00,0x2B, + 0x00,0xD0,0x11,0x70,0x83,0x06,0x00,0xD5,0x51,0x71,0x83,0x07,0x00,0xD5,0x51,0x70, + 0x03,0x07,0x00,0xD5,0xD1,0x70,0x43,0x07,0x00,0xD5,0x91,0x70,0xC0,0x06,0x00,0xD5, + 0x11,0x71,0x70,0x47,0x48,0x20,0x00,0x20,0x10,0xB5,0x0E,0x4C,0xA0,0x7A,0xC1,0x06, + 0x16,0xD5,0x11,0x28,0x05,0xD1,0x5C,0x22,0x0B,0x49,0x0C,0x48,0xFE,0xF7,0xAC,0xFB, + 0x0A,0xE0,0x12,0x28,0x08,0xD1,0x0A,0x48,0x9C,0x22,0x01,0x68,0x06,0x48,0xFF,0x31, + 0xA1,0x31,0xFE,0xF7,0xA1,0xFB,0xEE,0xE7,0x01,0x20,0xA0,0x71,0x00,0x20,0xA0,0x72, + 0x10,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0x32,0x05,0x00,0x20,0xD6,0x04,0x00,0x20, + 0x10,0x06,0x00,0x20,0xFF,0xB5,0x86,0xB0,0x00,0x20,0x04,0x90,0x08,0x68,0x02,0x90, + 0x14,0x20,0x01,0x26,0x08,0x56,0x01,0x90,0x15,0x20,0x08,0x56,0x1D,0x46,0xB4,0x46, + 0x05,0x90,0x04,0x98,0x40,0x00,0x29,0x5C,0x40,0x19,0x00,0x91,0x40,0x78,0x03,0x90, + 0x04,0x98,0x40,0x1C,0x80,0x06,0x80,0x0E,0x04,0x90,0x01,0x98,0x41,0x43,0x03,0x98, + 0x08,0x18,0x41,0x00,0x02,0x98,0x41,0x5E,0x10,0x98,0x81,0x42,0x2D,0xDB,0x03,0x24, + 0x03,0x9A,0x00,0x99,0xE0,0x07,0x05,0xD0,0x12,0x19,0x01,0x98,0x92,0x1E,0x82,0x42, + 0x21,0xD2,0x04,0xE0,0x09,0x19,0x05,0x98,0x49,0x1E,0x81,0x42,0x1B,0xD2,0x01,0x98, + 0x06,0x9B,0x48,0x43,0x80,0x18,0x1B,0x5C,0x0F,0x2B,0x14,0xD3,0x02,0x9B,0x47,0x00, + 0xDF,0x5F,0x11,0x9B,0x9F,0x42,0x0E,0xDB,0x06,0x9F,0x08,0x9B,0x3B,0x54,0x60,0x46, + 0x40,0x00,0x29,0x54,0x40,0x19,0x42,0x70,0x0F,0x98,0x04,0xF0,0xAF,0xFB,0x76,0x1C, + 0xB0,0x06,0x80,0x0E,0x84,0x46,0x64,0x1E,0xD2,0xD5,0x04,0x98,0x60,0x45,0xB8,0xD1, + 0x30,0x46,0x0A,0xB0,0xF0,0xBD,0xFF,0xB5,0x8D,0xB0,0xC0,0x31,0x02,0x91,0x48,0x69, + 0x07,0x90,0x0E,0x68,0x00,0x2E,0x06,0xD0,0x40,0x30,0x01,0x7C,0x00,0x29,0x02,0xD0, + 0x00,0x7A,0x00,0x28,0x02,0xD0,0x00,0x20,0x11,0xB0,0xF0,0xBD,0x0D,0x98,0x14,0x21, + 0x41,0x56,0x04,0x91,0x01,0x46,0x15,0x20,0x08,0x56,0x05,0x90,0x08,0x68,0x08,0x90, + 0x04,0x99,0x05,0x98,0x1F,0x22,0x41,0x43,0x30,0x46,0xFE,0xF7,0x35,0xFB,0x02,0x98, + 0x80,0x21,0xC0,0x68,0x09,0x90,0xFE,0xF7,0x36,0xFB,0x09,0x98,0x46,0x60,0x00,0x20, + 0x00,0x90,0x01,0x90,0x02,0x98,0x41,0x69,0x01,0x98,0x80,0x00,0x5F,0x30,0x09,0x18, + 0x88,0x78,0x00,0x28,0x3E,0xD0,0x00,0x98,0x00,0x23,0xC0,0xB2,0x0A,0x78,0x84,0x46, + 0x18,0xE0,0x48,0x78,0x12,0xE0,0x0D,0x9C,0x27,0x46,0x25,0x68,0x14,0x24,0x3C,0x57, + 0x54,0x43,0x27,0x18,0x7F,0x00,0xEF,0x5F,0x02,0x9D,0x6D,0x69,0x6D,0x7D,0xAF,0x42, + 0x03,0xDB,0x37,0x18,0x65,0x46,0xE5,0x55,0x5B,0x1C,0x40,0x1C,0xCC,0x78,0x84,0x42, + 0xE9,0xDA,0x52,0x1C,0x88,0x78,0x90,0x42,0xE3,0xDA,0xFF,0x24,0x22,0x46,0xFF,0x2B, + 0x00,0xDA,0x1A,0x46,0x00,0x98,0xC3,0x00,0x09,0x98,0x18,0x18,0xC2,0x73,0x02,0x7B, + 0x00,0x9B,0x92,0x07,0x92,0x0F,0x9B,0x00,0x1A,0x43,0x02,0x23,0x1A,0x43,0x02,0x73, + 0x84,0x73,0x62,0x46,0x42,0x73,0x08,0x30,0x04,0x22,0xFE,0xF7,0xC5,0xFA,0x00,0x98, + 0x40,0x1C,0x00,0x90,0x01,0x98,0x40,0x1C,0x01,0x90,0x04,0x28,0xB2,0xDB,0x03,0xF0, + 0xA5,0xFC,0x00,0x9C,0x06,0x90,0x64,0x1E,0x6F,0xE0,0x04,0x9D,0x6B,0xE0,0x0E,0x2C, + 0x6B,0xDA,0x04,0x99,0x05,0x98,0x48,0x43,0x40,0x19,0x08,0x99,0x42,0x00,0x8A,0x5E, + 0x07,0x99,0x49,0x7D,0x8A,0x42,0x5E,0xDB,0x31,0x5C,0x0F,0x29,0x5B,0xD3,0x06,0x9A, + 0x05,0x99,0x11,0x70,0x06,0x99,0x6A,0x46,0x4D,0x70,0x06,0x99,0x64,0x1C,0x09,0x88, + 0x91,0x81,0x06,0x99,0x09,0x88,0xD1,0x81,0xE1,0xB2,0x0A,0x91,0x0B,0x91,0x31,0x54, + 0x07,0x98,0x03,0xA9,0x42,0x7D,0x10,0x9B,0x68,0x46,0x0E,0xC0,0x62,0xB2,0x30,0x46, + 0x06,0x9B,0x0D,0x99,0xFF,0xF7,0xF6,0xFE,0x07,0x46,0x07,0x98,0x03,0xA9,0x03,0x7D, + 0x82,0x7D,0x02,0x93,0x01,0x92,0x00,0x96,0xFF,0x23,0x0B,0x9A,0x0D,0x98,0xFF,0xF7, + 0x81,0xFA,0x01,0x46,0x07,0x98,0x42,0x7F,0x8A,0x42,0x1A,0xDB,0x68,0x46,0x00,0x7B, + 0x11,0xE0,0x69,0x46,0x4A,0x7B,0x04,0x9B,0x01,0x46,0x59,0x43,0x06,0xE0,0xB7,0x18, + 0xCB,0x5D,0xA3,0x42,0x01,0xD1,0x1F,0x23,0xCB,0x55,0x52,0x1C,0x6B,0x46,0xDB,0x7B, + 0x93,0x42,0xF4,0xDA,0x40,0x1C,0x69,0x46,0x89,0x7B,0x81,0x42,0xE9,0xDA,0x64,0x1E, + 0x11,0xE0,0x09,0x98,0xE2,0x00,0x10,0x18,0xC7,0x73,0x02,0x7B,0x92,0x07,0x92,0x0F, + 0xA3,0x00,0x1A,0x43,0x02,0x73,0x81,0x73,0x03,0x99,0x81,0x60,0x01,0x21,0x0A,0x43, + 0x02,0x73,0x0A,0x99,0x41,0x73,0x6D,0x1E,0x91,0xD5,0x05,0x98,0x40,0x1E,0x05,0x90, + 0x8B,0xD5,0x09,0x98,0x64,0x1C,0x04,0x80,0x03,0xF0,0x3E,0xFC,0x13,0xE7,0x00,0x00, + 0x10,0x48,0x11,0x49,0x10,0xB5,0x40,0x1A,0x1B,0xD0,0x00,0xF0,0xC9,0xFA,0x09,0x24, + 0x01,0x22,0x0B,0x21,0x24,0x03,0x12,0x03,0x09,0x03,0x20,0x46,0x01,0xF0,0x0A,0xF8, + 0x55,0x21,0x0A,0x4A,0x00,0x20,0x08,0xCC,0x40,0x1C,0x59,0x18,0x80,0xB2,0x90,0x42, + 0xF9,0xD3,0x20,0x68,0x88,0x42,0x04,0xD0,0x01,0x21,0x04,0x20,0x00,0xF0,0x88,0xFF, + 0xFE,0xE7,0x10,0xBD,0x10,0x90,0x00,0x00,0x00,0x90,0x00,0x00,0xFF,0x03,0x00,0x00, + 0x10,0xB5,0x04,0x48,0x80,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x88,0x70, + 0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0x02,0x48,0x41,0x88,0x11,0x22,0x11,0x43, + 0x41,0x80,0x70,0x47,0x00,0x10,0x00,0x40,0x10,0xB5,0x04,0x48,0x40,0x69,0x80,0x47, + 0x02,0x49,0x01,0x20,0x08,0x39,0x48,0x71,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20, + 0xF8,0xB5,0x0D,0x46,0x00,0x26,0x02,0x09,0x38,0x49,0x0F,0x2A,0x28,0xD0,0x58,0x28, + 0x6A,0xD8,0x37,0x4A,0x10,0x5C,0xFF,0x28,0x66,0xD0,0x02,0x07,0x06,0x09,0x12,0x0F, + 0xF0,0x00,0x47,0x18,0x01,0x20,0x90,0x40,0xC4,0xB2,0x38,0x46,0x00,0xF0,0x26,0xFF, + 0x01,0x78,0xA1,0x43,0x01,0x70,0x8C,0x46,0x41,0x78,0xA1,0x43,0x41,0x70,0x82,0x78, + 0xA2,0x43,0x82,0x70,0xC3,0x78,0xA3,0x43,0xC3,0x70,0x04,0x2D,0x0D,0xD0,0x0C,0x2D, + 0x0E,0xD0,0x08,0x2D,0x10,0xD0,0x02,0x2D,0x12,0xD0,0x01,0x2D,0x13,0xD0,0x14,0xE0, + 0x00,0x07,0xFF,0x24,0x40,0x0E,0x47,0x18,0xDF,0xE7,0x21,0x43,0x41,0x70,0x0C,0xE0, + 0x62,0x46,0x22,0x43,0x02,0x70,0xF8,0xE7,0x61,0x46,0x21,0x43,0x01,0x70,0x04,0xE0, + 0x22,0x43,0x82,0x70,0x01,0xE0,0x23,0x43,0xC3,0x70,0x1A,0x49,0x8A,0x5D,0x00,0x2A, + 0x22,0xD0,0x00,0x22,0x17,0x49,0x89,0x5D,0xD1,0x40,0xC9,0x07,0x18,0xD0,0x01,0x21, + 0x91,0x40,0x14,0x4D,0xCB,0xB2,0x00,0x21,0xF4,0x00,0x08,0x35,0x64,0x19,0xA4,0x46, + 0x64,0x46,0xA5,0x5C,0x08,0x24,0xCC,0x40,0x25,0x42,0x02,0xD0,0x44,0x5C,0x1C,0x43, + 0x01,0xE0,0x44,0x5C,0x9C,0x43,0x44,0x54,0x49,0x1C,0xC9,0xB2,0x04,0x29,0xEF,0xD3, + 0x52,0x1C,0xD2,0xB2,0x08,0x2A,0xDD,0xD3,0x01,0x78,0x39,0x70,0x41,0x78,0x79,0x70, + 0x81,0x78,0xB9,0x70,0xC0,0x78,0xF8,0x70,0xF8,0xBD,0x00,0x00,0x40,0x03,0x00,0x40, + 0xBA,0x6D,0x00,0x00,0xFC,0x20,0x00,0x20,0x58,0x28,0x01,0xD9,0xFF,0x20,0x70,0x47, + 0x0B,0x49,0x08,0x5C,0xFF,0x28,0xFA,0xD0,0x01,0x09,0x00,0x07,0xC9,0x00,0x00,0x0F, + 0x08,0x18,0x1E,0x28,0x05,0xD2,0x09,0x28,0x01,0xD2,0x0C,0x30,0x06,0xE0,0x09,0x38, + 0x04,0xE0,0x35,0x28,0x01,0xD2,0x0B,0x38,0x00,0xE0,0x20,0x38,0xC0,0xB2,0x70,0x47, + 0xBA,0x6D,0x00,0x00,0x70,0xB5,0x40,0x07,0x0D,0x4C,0x40,0x0F,0x24,0x5C,0x48,0x07, + 0x0B,0x49,0x40,0x0F,0x08,0x31,0x0D,0x5C,0x04,0x9E,0x00,0x2B,0x0E,0xD0,0x08,0x46, + 0x0A,0x21,0x4C,0x43,0x06,0x49,0x10,0x38,0x80,0x5C,0x09,0x1F,0xC9,0x5C,0x70,0x43, + 0x60,0x43,0x69,0x43,0xFE,0xF7,0x16,0xF9,0x80,0xB2,0x70,0xBD,0x00,0x20,0x70,0xBD, + 0x52,0x6E,0x00,0x00,0xF0,0xB5,0x0D,0x46,0x41,0x06,0xCC,0x0F,0x59,0x08,0x01,0x27, + 0x85,0xB0,0xFF,0x03,0xCF,0x19,0x03,0x91,0x0A,0x99,0x9C,0x46,0x49,0x00,0x02,0x91, + 0x81,0x06,0x89,0x0E,0x8E,0x46,0x89,0x1C,0x01,0x91,0x71,0x46,0x4B,0x1C,0x49,0x1E, + 0x8E,0x46,0x86,0x06,0x69,0x1E,0xB6,0x0E,0x00,0x91,0x97,0x42,0x29,0xD2,0x60,0x46, + 0x17,0x1A,0x01,0x20,0xC0,0x03,0x39,0x1A,0x00,0x29,0x02,0xDC,0x61,0x46,0x89,0x1A, + 0x09,0x18,0x88,0xB2,0x00,0x2C,0x29,0xD0,0x00,0x2E,0x07,0xD0,0x70,0x46,0x03,0xE0, + 0x0A,0x99,0xFE,0xF7,0xDF,0xF8,0x80,0x19,0xC3,0xB2,0x01,0xE0,0x00,0x24,0x27,0xE0, + 0x3F,0x2B,0x26,0xD9,0x3F,0x23,0x24,0xE0,0xA0,0x01,0x18,0x43,0x80,0x21,0x08,0x43, + 0x05,0xB0,0xF0,0xBD,0x00,0x99,0xA0,0x01,0x08,0x43,0x80,0x21,0x08,0x43,0xC0,0xB2, + 0xF6,0xE7,0x01,0x27,0x03,0x99,0xFF,0x03,0x79,0x1A,0x91,0x42,0xF0,0xD9,0xB8,0x1A, + 0x00,0x28,0x00,0xDC,0xD0,0x1B,0x80,0xB2,0x00,0x2C,0x06,0xD0,0x02,0x99,0x81,0x42, + 0xDE,0xD2,0x01,0x99,0xA9,0x42,0xDB,0xD2,0xD2,0xE7,0x00,0x2E,0xCE,0xD1,0x01,0x24, + 0x01,0x23,0xAB,0x42,0xDE,0xD2,0xD7,0xE7,0xFF,0xB5,0x07,0x46,0x83,0xB0,0x44,0x49, + 0x04,0x20,0x04,0xF0,0x99,0xF8,0x43,0x4C,0x01,0x25,0x25,0x80,0x42,0x48,0x61,0x21, + 0x01,0x72,0x60,0x21,0x41,0x72,0x08,0x20,0x00,0xF0,0xAE,0xF8,0x65,0x80,0x3F,0x48, + 0x0F,0x21,0x81,0x70,0x38,0x21,0x01,0x70,0x07,0x21,0xC1,0x70,0xFF,0x20,0xF1,0x30, + 0xE0,0x80,0x11,0x20,0x00,0x02,0x20,0x81,0x10,0x20,0xA0,0x80,0x00,0x24,0x61,0xE0, + 0x04,0x98,0x36,0x4A,0x00,0x5D,0x20,0x32,0x41,0x00,0x89,0x18,0x33,0x4A,0x00,0x91, + 0xC1,0x08,0x08,0x32,0x8A,0x18,0x31,0x49,0x01,0x92,0x60,0x39,0x46,0x18,0x40,0x07, + 0x40,0x0F,0x2E,0x4A,0x07,0x21,0xD1,0x70,0x80,0x21,0x31,0x70,0x01,0x21,0x01,0x9A, + 0x81,0x40,0x11,0x70,0x38,0x5D,0x00,0x21,0x00,0x9A,0x04,0xF0,0xFB,0xF9,0x05,0x46, + 0x38,0x5D,0x80,0x21,0x00,0x9A,0x04,0xF0,0xF5,0xF9,0x25,0x49,0x42,0x1B,0x52,0x18, + 0x49,0x00,0x8A,0x42,0x1A,0xD9,0x21,0x48,0x77,0x21,0xC1,0x70,0xF0,0x20,0x30,0x70, + 0x38,0x5D,0x80,0x21,0x00,0x9A,0x04,0xF0,0xE5,0xF9,0x01,0x21,0xC9,0x03,0x41,0x1A, + 0x8A,0x00,0x89,0x18,0x40,0x1A,0x80,0xB2,0x19,0x49,0x42,0x1B,0x52,0x18,0x49,0x00, + 0x8A,0x42,0x03,0xD8,0x16,0x48,0x40,0x42,0x28,0x18,0x80,0xB2,0x00,0x21,0x31,0x70, + 0x01,0x9A,0x11,0x70,0x41,0x1B,0x00,0x29,0x00,0xDC,0x29,0x1A,0x89,0xB2,0xB4,0x29, + 0x00,0xD2,0x01,0x21,0x06,0x98,0x00,0x28,0x06,0xD0,0x0E,0x48,0x49,0x1C,0xFE,0xF7, + 0x31,0xF8,0x06,0x99,0x62,0x00,0x88,0x52,0x00,0x21,0x01,0x20,0x00,0xF0,0xC0,0xFD, + 0x64,0x1C,0xE4,0xB2,0x05,0x98,0x84,0x42,0x9A,0xD3,0x07,0xB0,0xF0,0xBD,0x00,0x00, + 0xC9,0x1C,0x00,0x00,0x00,0x10,0x00,0x40,0x00,0x03,0x00,0x40,0x60,0x12,0x00,0x40, + 0xAC,0x0D,0x00,0x00,0x50,0x34,0x03,0x00,0xFF,0xB5,0x07,0x46,0x10,0x4C,0x81,0xB0, + 0x11,0x20,0x1D,0x46,0x16,0x46,0x60,0x80,0x04,0x20,0xFF,0xF7,0x65,0xFC,0x0D,0x49, + 0xB8,0x02,0x40,0x18,0x02,0x99,0x09,0x01,0x08,0x43,0x00,0x2E,0x01,0xD1,0x08,0x21, + 0x08,0x43,0x20,0x80,0x00,0x2D,0x06,0xD0,0x01,0x2D,0x06,0xD0,0x00,0x22,0x20,0x21, + 0x04,0x20,0x04,0xF0,0x43,0xFE,0x05,0xB0,0xF0,0xBD,0x00,0x22,0x21,0x21,0xF7,0xE7, + 0x00,0x10,0x00,0x40,0x43,0x03,0x00,0x00,0x70,0xB5,0x00,0x24,0x06,0x46,0xF0,0x25, + 0x20,0x46,0x28,0x43,0x31,0x46,0xFF,0xF7,0x1B,0xFE,0x64,0x1C,0xE4,0xB2,0x08,0x2C, + 0xF6,0xD3,0x70,0xBD,0xF0,0xB5,0x45,0x4E,0x89,0xB0,0x30,0x89,0x44,0x4F,0xC0,0xB2, + 0x08,0x90,0x30,0x68,0x07,0x90,0x3D,0x79,0x0C,0x46,0x00,0x20,0xB0,0x74,0x01,0x46, + 0xC8,0x20,0x01,0xF0,0x43,0xF9,0x00,0x20,0x38,0x71,0x02,0x46,0x01,0x46,0x3C,0x48, + 0x10,0x30,0x00,0xF0,0xA9,0xFD,0x06,0x90,0x39,0x48,0xFF,0x22,0x00,0x21,0x15,0x30, + 0x00,0xF0,0xA2,0xFD,0x05,0x90,0x36,0x48,0xFF,0x22,0x00,0x21,0x14,0x30,0x00,0xF0, + 0x9B,0xFD,0x04,0x90,0x32,0x48,0x00,0x22,0x11,0x46,0x13,0x30,0x00,0xF0,0x94,0xFD, + 0x03,0x90,0x2F,0x48,0x00,0x22,0x11,0x46,0x12,0x30,0x00,0xF0,0x8D,0xFD,0x02,0x90, + 0x2B,0x48,0x00,0x22,0x11,0x46,0x11,0x30,0x00,0xF0,0x86,0xFD,0x01,0x90,0x00,0xF0, + 0xC9,0xF8,0x00,0x2C,0x04,0xD0,0x00,0xF0,0x95,0xF9,0x01,0x20,0x00,0xF0,0x62,0xF9, + 0x0A,0x20,0xFF,0xF7,0xF1,0xFB,0xA0,0x27,0x01,0x22,0x22,0x21,0x0A,0x20,0x04,0xF0, + 0xDD,0xFD,0xB1,0x7C,0x00,0x29,0x30,0xD0,0x00,0x2C,0x02,0xD0,0x00,0x20,0x00,0xF0, + 0x51,0xF9,0x1B,0x48,0x05,0x71,0x1A,0x48,0x01,0x21,0x10,0x30,0x06,0x9A,0x00,0xF0, + 0x63,0xFD,0x17,0x48,0x01,0x21,0x15,0x30,0x05,0x9A,0x00,0xF0,0x5D,0xFD,0x14,0x48, + 0x01,0x21,0x14,0x30,0x04,0x9A,0x00,0xF0,0x57,0xFD,0x11,0x48,0x01,0x21,0x13,0x30, + 0x03,0x9A,0x00,0xF0,0x51,0xFD,0x0E,0x48,0x01,0x21,0x12,0x30,0x02,0x9A,0x00,0xF0, + 0x4B,0xFD,0x0B,0x48,0x01,0x21,0x11,0x30,0x01,0x9A,0x00,0xF0,0x45,0xFD,0x07,0x99, + 0x08,0x98,0x01,0xF0,0xD3,0xF8,0x09,0xB0,0xF0,0xBD,0x80,0x07,0x02,0xD5,0x01,0x20, + 0x00,0xF0,0x20,0xF9,0x03,0x48,0x87,0x80,0xBE,0xE7,0x00,0x00,0x68,0x20,0x00,0x20, + 0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0x0E,0xB5,0xB9,0x20,0x6B,0x46,0x18,0x72, + 0x01,0x22,0x01,0xA9,0x02,0xA8,0x13,0x46,0x00,0x92,0x00,0xF0,0x43,0xF8,0x0E,0xBD, + 0x70,0xB5,0x13,0x4D,0x00,0x20,0x68,0x82,0x07,0x21,0xE9,0x82,0x11,0x4C,0x20,0x80, + 0x33,0x20,0x60,0x80,0x10,0x49,0x01,0x20,0x03,0xF0,0x26,0xFF,0xBF,0x22,0x03,0x21, + 0x0E,0x48,0x00,0xF0,0x11,0xFD,0x0D,0x48,0xBF,0x22,0x03,0x21,0x80,0x1C,0x00,0xF0, + 0x0B,0xFD,0x0A,0x48,0xBF,0x22,0x03,0x21,0x40,0x1C,0x00,0xF0,0x05,0xFD,0xE0,0x8B, + 0x04,0x21,0x08,0x43,0xE0,0x83,0x24,0x20,0x68,0x82,0x03,0x20,0xE8,0x82,0x70,0xBD, + 0x00,0x20,0x00,0x40,0x20,0x11,0x00,0x40,0x4D,0x42,0x00,0x00,0x10,0x03,0x00,0x40, + 0x3E,0xB5,0x00,0x24,0xAB,0x25,0x6B,0x46,0x1D,0x72,0x01,0x22,0x01,0xA9,0x02,0xA8, + 0x13,0x46,0x00,0x92,0x00,0xF0,0x06,0xF8,0x64,0x1C,0xE4,0xB2,0x0A,0x2C,0xF2,0xD3, + 0x3E,0xBD,0x00,0x00,0x30,0xB5,0x0F,0x4D,0x03,0x9C,0xA8,0x62,0xE9,0x62,0x0D,0x48, + 0x40,0x21,0x20,0x30,0x01,0x80,0x82,0x80,0xC3,0x80,0x0B,0x48,0x24,0x21,0x41,0x82, + 0x03,0x21,0xC1,0x82,0x00,0x2C,0x01,0xD0,0x08,0x49,0x00,0xE0,0x08,0x49,0x41,0x82, + 0xC1,0x8A,0xC9,0x07,0xFC,0xD0,0x00,0x20,0x40,0x1C,0xC0,0xB2,0x13,0x28,0xFB,0xD3, + 0x30,0xBD,0x00,0x00,0x00,0x11,0x00,0x40,0x00,0x20,0x00,0x40,0x24,0x30,0x00,0x00, + 0x24,0x10,0x00,0x00,0x00,0xB5,0x00,0x22,0x01,0x21,0x11,0x48,0x00,0xF0,0xB4,0xFC, + 0x0F,0x48,0xFF,0x22,0x01,0x21,0x40,0x1D,0x00,0xF0,0xAE,0xFC,0x0C,0x48,0xFF,0x22, + 0x01,0x21,0x00,0x1D,0x00,0xF0,0xA8,0xFC,0x09,0x48,0x00,0x22,0x01,0x21,0xC0,0x1C, + 0x00,0xF0,0xA2,0xFC,0x06,0x48,0x00,0x22,0x01,0x21,0x80,0x1C,0x00,0xF0,0x9C,0xFC, + 0x03,0x48,0x00,0x22,0x01,0x21,0x40,0x1C,0x00,0xF0,0x96,0xFC,0x00,0xBD,0x00,0x00, + 0x10,0x03,0x00,0x40,0x10,0xB5,0x09,0x4C,0x44,0x21,0x60,0x68,0xFD,0xF7,0xFB,0xFE, + 0xA0,0x69,0xFF,0x22,0x41,0x79,0x60,0x68,0x11,0x30,0xFD,0xF7,0xED,0xFE,0x02,0xF0, + 0xB5,0xF8,0x60,0x61,0x61,0x68,0x00,0x78,0x08,0x74,0x10,0xBD,0x78,0x21,0x00,0x20, + 0xFF,0xB5,0x0D,0x46,0x81,0xB0,0x16,0x46,0x1F,0x46,0x29,0x49,0x02,0x20,0x03,0xF0, + 0x83,0xFE,0x01,0x24,0xA4,0x07,0xA0,0x89,0x00,0x07,0x00,0x0F,0xA0,0x81,0x00,0x2D, + 0x02,0xD1,0xA0,0x89,0xE0,0x21,0x05,0xE0,0xA0,0x89,0x02,0x2D,0x01,0xD1,0x10,0x21, + 0x00,0xE0,0x30,0x21,0x08,0x43,0xA0,0x81,0x1E,0x4D,0xC1,0x20,0x68,0x70,0x30,0x01, + 0x1D,0x49,0x38,0x43,0x88,0x83,0x00,0x22,0x30,0x46,0x0A,0x99,0x00,0xF0,0x94,0xF8, + 0x00,0x22,0x38,0x46,0x0A,0x99,0x00,0xF0,0x8F,0xF8,0x01,0x21,0x08,0x46,0xB0,0x40, + 0xB9,0x40,0x08,0x43,0x06,0x46,0xC2,0xB2,0x02,0x21,0x14,0x48,0x00,0xF0,0x44,0xFC, + 0x12,0x48,0xF2,0xB2,0x02,0x21,0x40,0x1E,0x00,0xF0,0x3E,0xFC,0x60,0x89,0x40,0x21, + 0x08,0x43,0x60,0x81,0x00,0x21,0x69,0x71,0x0B,0x98,0x28,0x70,0x01,0x98,0x00,0x28, + 0x03,0xD1,0x28,0x78,0x80,0x22,0x10,0x43,0x28,0x70,0x09,0x48,0x01,0x84,0x01,0x85, + 0x20,0x30,0xC1,0x71,0x0A,0x99,0x01,0x74,0x0C,0x99,0x41,0x74,0x05,0xB0,0xF0,0xBD, + 0x55,0x47,0x00,0x00,0x00,0x20,0x00,0x40,0x20,0x11,0x00,0x40,0x12,0x03,0x00,0x40, + 0xC8,0x20,0x00,0x20,0x03,0x49,0x00,0x28,0x01,0xD0,0x01,0x20,0x00,0xE0,0x10,0x20, + 0xC8,0x71,0x70,0x47,0x00,0x20,0x00,0x40,0xF0,0xB5,0x11,0x4C,0x06,0x9F,0x08,0x9E, + 0x09,0x9D,0x0F,0xC4,0x10,0x3C,0x20,0x46,0xC6,0x61,0x07,0x99,0x47,0x61,0x81,0x61, + 0x05,0x99,0x01,0x61,0x65,0x84,0x0A,0x98,0x00,0x22,0x28,0x18,0xA0,0x84,0x0C,0x99, + 0xE1,0x62,0x07,0x48,0x0B,0x9C,0x01,0x23,0x20,0x30,0x00,0x2C,0x03,0xD0,0x82,0x72, + 0xC3,0x72,0x0A,0x70,0xF0,0xBD,0x83,0x72,0xC2,0x72,0x0B,0x70,0xF0,0xBD,0x00,0x00, + 0xC8,0x20,0x00,0x20,0x70,0xB5,0x11,0x48,0x81,0x8B,0x80,0x8B,0x09,0x05,0x0D,0x0E, + 0x06,0x07,0x0F,0x4C,0x36,0x0F,0x21,0x7C,0x00,0x22,0x28,0x46,0x00,0xF0,0x1C,0xF8, + 0x21,0x7C,0x00,0x22,0x30,0x46,0x00,0xF0,0x17,0xF8,0x01,0x20,0x04,0x46,0xAC,0x40, + 0xB0,0x40,0x04,0x43,0xE2,0xB2,0x02,0x21,0x06,0x48,0x00,0xF0,0xCD,0xFB,0x05,0x48, + 0xE2,0xB2,0x02,0x21,0x40,0x1E,0x00,0xF0,0xC7,0xFB,0x70,0xBD,0x20,0x11,0x00,0x40, + 0xE8,0x20,0x00,0x20,0x12,0x03,0x00,0x40,0xF7,0xB5,0x07,0x46,0x01,0x20,0xB8,0x40, + 0x81,0xB0,0xC0,0xB2,0x00,0x90,0x02,0x98,0x01,0x21,0x05,0x07,0x06,0x09,0x2D,0x0F, + 0xEA,0x07,0xB9,0x40,0xC9,0xB2,0x24,0x48,0xCC,0x43,0x00,0x2A,0x02,0xD0,0x02,0x21, + 0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0xA6,0xFB,0x1F,0x48,0xA9,0x07, + 0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0x9C,0xFB, + 0x68,0x07,0x04,0xD5,0x18,0x48,0x02,0x21,0x40,0x1C,0x00,0x9A,0x03,0xE0,0x17,0x48, + 0xE2,0xB2,0x03,0x21,0x00,0x1D,0x00,0xF0,0x8F,0xFB,0x15,0x48,0xF1,0x07,0x02,0xD0, + 0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0,0x85,0xFB,0x11,0x48, + 0xB1,0x07,0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2,0x03,0x21,0x00,0xF0, + 0x7B,0xFB,0x0D,0x48,0x71,0x07,0x02,0xD5,0x02,0x21,0x00,0x9A,0x01,0xE0,0xE2,0xB2, + 0x03,0x21,0x00,0xF0,0x71,0xFB,0x03,0x98,0x00,0x28,0x03,0xD0,0x07,0x48,0x07,0x73, + 0x02,0x99,0x41,0x73,0xFF,0xBD,0x00,0x00,0x10,0x03,0x00,0x40,0x12,0x03,0x00,0x40, + 0x13,0x03,0x00,0x40,0x14,0x03,0x00,0x40,0x15,0x03,0x00,0x40,0x68,0x20,0x00,0x20, + 0xFF,0xB5,0x3A,0x4D,0x94,0x46,0x6F,0x68,0x4A,0x1E,0xF8,0x78,0x81,0xB0,0x90,0x42, + 0x01,0xDD,0x01,0x20,0x01,0xE0,0x08,0x1A,0xC0,0xB2,0x35,0x4C,0x01,0x22,0x22,0x80, + 0xAC,0x68,0x34,0x4E,0x62,0x78,0x92,0x01,0x18,0x32,0x32,0x70,0x00,0x2B,0x08,0xD0, + 0x31,0x4A,0x13,0x88,0x31,0x4A,0x93,0x42,0x03,0xD1,0x33,0x78,0x01,0x22,0x13,0x43, + 0x33,0x70,0xA2,0x78,0x00,0x2A,0x06,0xD0,0x33,0x78,0xF7,0x22,0x13,0x40,0x33,0x70, + 0x00,0x23,0x73,0x70,0x01,0xE0,0x10,0x22,0x72,0x70,0x0B,0x02,0x79,0x78,0x0B,0x43, + 0x23,0x49,0xCB,0x80,0x3A,0x78,0x12,0x03,0x02,0x43,0x0A,0x81,0xE0,0x78,0x22,0x79, + 0x00,0x01,0x10,0x43,0xF0,0x70,0x60,0x79,0x00,0x01,0x40,0x1C,0xB0,0x70,0x01,0x98, + 0x88,0x80,0x20,0x7A,0x43,0x21,0x00,0x01,0x08,0x43,0x1D,0x49,0x08,0x72,0xA0,0x79, + 0xE2,0x79,0x00,0x01,0x10,0x43,0x48,0x72,0x60,0x46,0xFF,0xF7,0x3D,0xFD,0xE8,0x68, + 0x01,0x78,0x40,0x68,0x00,0xF0,0x9E,0xFB,0xE8,0x68,0x01,0x78,0xC0,0x68,0x00,0xF0, + 0x75,0xFB,0x01,0x98,0x00,0x90,0x68,0x68,0x43,0x79,0x02,0x79,0xA8,0x68,0x01,0x79, + 0xC0,0x78,0xFF,0xF7,0xE7,0xFB,0xA8,0x83,0x00,0x28,0x02,0xD1,0xFF,0x20,0x2D,0x30, + 0xA8,0x83,0x80,0xB2,0x41,0x08,0x68,0x84,0x41,0x18,0x29,0x84,0x7D,0x21,0xC9,0x00, + 0x40,0x18,0x80,0xB2,0xA8,0x83,0x05,0xB0,0xF0,0xBD,0x00,0x00,0x44,0x21,0x00,0x20, + 0x00,0x10,0x00,0x40,0x60,0x12,0x00,0x40,0xB8,0x6D,0x00,0x00,0xAC,0xCA,0x00,0x00, + 0x00,0x03,0x00,0x40,0x70,0xB5,0x11,0x4C,0x05,0x46,0xE0,0x68,0x41,0x78,0x02,0x78, + 0x01,0x20,0xE0,0x77,0x00,0x20,0x20,0x70,0x60,0x70,0xA0,0x70,0xE0,0x70,0x00,0x29, + 0x00,0xD1,0x01,0x21,0x51,0x43,0x49,0x00,0x60,0x69,0xFD,0xF7,0x34,0xFD,0x04,0x20, + 0x01,0x07,0x48,0x80,0x01,0x21,0x00,0x22,0x08,0x46,0x00,0xF0,0x09,0xFE,0x00,0x2D, + 0x02,0xD0,0x20,0x78,0x00,0x28,0xFC,0xD0,0x70,0xBD,0x00,0x00,0x44,0x21,0x00,0x20, + 0xF0,0xB5,0x05,0xAC,0xE0,0xCC,0x04,0x4C,0xA5,0x61,0x63,0x61,0x62,0x60,0xA1,0x60, + 0xE0,0x60,0xA7,0x77,0x26,0x61,0xF0,0xBD,0x44,0x21,0x00,0x20,0xF0,0xB5,0x6D,0x48, + 0x9D,0xB0,0x41,0x88,0x11,0x22,0x11,0x43,0x41,0x80,0x6B,0x48,0xC1,0x7F,0x00,0x29, + 0x7E,0xD0,0x01,0x46,0x04,0x46,0xE0,0x68,0x28,0x31,0x4E,0x78,0x42,0x78,0x17,0x92, + 0x05,0x78,0x60,0x78,0x62,0x69,0x68,0x43,0x40,0x00,0x10,0x18,0x1C,0x90,0x89,0x68, + 0xA0,0x78,0x32,0x46,0x70,0x43,0x09,0x18,0x19,0xA8,0xFD,0xF7,0xCD,0xFC,0xE0,0x68, + 0x2A,0x46,0x40,0x68,0x01,0xA9,0x00,0xF0,0x2B,0xFB,0x20,0x34,0x60,0x79,0x21,0x79, + 0x88,0x42,0x35,0xD2,0x00,0x20,0x1B,0x90,0x57,0x48,0xC1,0x78,0xC2,0x68,0x80,0x69, + 0x12,0x78,0x51,0x43,0x08,0x18,0x00,0x27,0x18,0x90,0x16,0xE0,0x52,0x48,0x01,0xAA, + 0x41,0x8C,0x00,0x91,0x03,0x8C,0x79,0x00,0x40,0x68,0x52,0x5A,0x41,0x78,0x18,0x98, + 0xC0,0x5D,0xFF,0xF7,0x6F,0xFB,0x18,0x99,0xC9,0x5D,0x81,0x42,0x03,0xD0,0x18,0x99, + 0xC8,0x55,0x01,0x20,0x1B,0x90,0x7F,0x1C,0xFF,0xB2,0xAF,0x42,0xE6,0xD3,0x60,0x79, + 0x40,0x1C,0xC0,0xB2,0x60,0x71,0x1B,0x99,0x00,0x29,0x04,0xD0,0x21,0x79,0x88,0x42, + 0x01,0xD2,0x00,0x22,0x5C,0xE0,0x00,0x21,0x01,0x22,0x08,0x46,0x00,0xF0,0x90,0xFD, + 0x00,0x20,0x60,0x71,0x3C,0x48,0x29,0x46,0x28,0x30,0x03,0x78,0x28,0x38,0x82,0x8B, + 0x01,0xA8,0x00,0xF0,0x49,0xFD,0x01,0xAB,0x9C,0x46,0x33,0x02,0x2B,0x43,0x9E,0x46, + 0x11,0x23,0x36,0x48,0x00,0x93,0x1C,0x99,0x83,0x88,0x19,0xAA,0x10,0x27,0x3B,0x43, + 0x83,0x80,0xC2,0x80,0x63,0x46,0x03,0x81,0x41,0x81,0x81,0x81,0x73,0x46,0x43,0x80, + 0x00,0x9B,0x03,0x80,0x81,0x88,0xC9,0x06,0xFC,0xD5,0x2B,0x4F,0xF8,0x78,0x00,0xE0, + 0x2B,0xE0,0x40,0x1C,0xF8,0x70,0xB8,0x78,0x40,0x1C,0xB8,0x70,0xB8,0x78,0xB0,0x42, + 0x04,0xD3,0x00,0x20,0xB8,0x70,0x78,0x78,0x80,0x19,0x78,0x70,0x79,0x78,0x17,0x98, + 0x81,0x42,0x20,0xD2,0x78,0x78,0x81,0x19,0x17,0x98,0x81,0x42,0x0D,0xD9,0x80,0x1B, + 0x78,0x70,0x78,0x78,0x79,0x69,0x68,0x43,0x40,0x00,0x7A,0x78,0x08,0x18,0x17,0x99, + 0x89,0x1A,0x69,0x43,0x49,0x00,0xFD,0xF7,0x66,0xFC,0xF8,0x78,0x01,0x28,0x06,0xD0, + 0x01,0x22,0x11,0x46,0x00,0x20,0x00,0xF0,0x3B,0xFD,0x1D,0xB0,0xF0,0xBD,0x01,0x22, + 0x01,0x21,0x08,0x46,0xF7,0xE7,0x20,0x79,0x00,0x28,0x18,0xD1,0x04,0x20,0x04,0x07, + 0x60,0x80,0x08,0x20,0xFF,0xF7,0x10,0xFC,0xF8,0x68,0x01,0x78,0x40,0x68,0x00,0xF0, + 0x5B,0xFA,0x0C,0x20,0x60,0x80,0x0A,0x49,0x40,0x20,0x08,0x72,0x09,0x48,0x00,0x21, + 0x01,0x71,0xC2,0x78,0x52,0x06,0x52,0x0E,0xC2,0x70,0x81,0x70,0x61,0x80,0x01,0x20, + 0x38,0x70,0xDA,0xE7,0x00,0x10,0x00,0x40,0x44,0x21,0x00,0x20,0x00,0x11,0x00,0x40, + 0x00,0x03,0x00,0x40,0x60,0x12,0x00,0x40,0xF1,0xB5,0x1B,0x49,0x04,0x20,0x03,0xF0, + 0xCB,0xFB,0x1A,0x48,0x81,0x7F,0x00,0x29,0x2A,0xD0,0x04,0x46,0x00,0x21,0x20,0x34, + 0x61,0x71,0x81,0x68,0x89,0x7A,0x21,0x71,0x01,0x46,0xC5,0x68,0x28,0x31,0x4E,0x78, + 0x6F,0x78,0x31,0x46,0x38,0x46,0xFD,0xF7,0xC5,0xFB,0x00,0x29,0x06,0xD0,0x70,0x1A, + 0xC0,0x19,0x0E,0x4E,0x00,0x06,0x00,0x0E,0x02,0xD0,0x02,0xE0,0x00,0x20,0xF7,0xE7, + 0x01,0x20,0x29,0x78,0x80,0x22,0x41,0x43,0xB0,0x69,0xFD,0xF7,0xFD,0xFB,0x00,0xF0, + 0x55,0xF8,0x01,0x20,0xFF,0xF7,0xB6,0xFE,0x00,0x20,0x60,0x71,0x20,0x71,0xB0,0x77, + 0x00,0x98,0xFF,0xF7,0xAF,0xFE,0xF8,0xBD,0xFD,0x26,0x00,0x00,0x44,0x21,0x00,0x20, + 0x0D,0x49,0x42,0x08,0x48,0x70,0x0A,0x70,0x04,0x2A,0x01,0xD1,0x03,0x22,0x0A,0x70, + 0x04,0x28,0x06,0xD0,0x08,0x28,0x09,0xD0,0x08,0x48,0x48,0x60,0x40,0x1C,0x88,0x60, + 0x70,0x47,0x06,0x48,0x82,0x30,0x48,0x60,0x10,0x30,0xF8,0xE7,0x03,0x48,0x80,0x1C, + 0x48,0x60,0x40,0x30,0xF3,0xE7,0x00,0x00,0x6C,0x21,0x00,0x20,0x62,0x6E,0x00,0x00, + 0xF8,0xB5,0x10,0x4F,0x04,0x46,0x38,0x46,0x00,0xF0,0xF0,0xF8,0x0E,0x4A,0xD1,0x68, + 0x49,0x78,0x00,0x29,0x15,0xD0,0x00,0x21,0x13,0x69,0xE6,0x00,0x72,0x18,0x54,0x00, + 0x1D,0x5D,0x8A,0x00,0x85,0x54,0x64,0x1C,0x1D,0x5D,0x14,0x18,0x65,0x70,0x85,0x5C, + 0xCA,0x00,0xD2,0x19,0x15,0x70,0x64,0x78,0x54,0x70,0x49,0x1C,0xC9,0xB2,0x08,0x29, + 0xEC,0xD3,0xF8,0xBD,0x40,0x03,0x00,0x40,0x44,0x21,0x00,0x20,0xF0,0xB5,0x3C,0x48, + 0x85,0xB0,0x44,0x78,0x28,0x38,0xC0,0x68,0x00,0x26,0x40,0x78,0x01,0x96,0x00,0x90, + 0x69,0xE0,0x31,0x19,0x81,0x42,0x01,0xD9,0x00,0x1B,0xC6,0xB2,0x00,0x27,0x5E,0xE0, + 0x33,0x48,0x41,0x68,0x20,0x46,0x78,0x43,0x08,0x18,0x00,0x25,0x02,0x90,0x19,0xE0, + 0x02,0x98,0x40,0x57,0x01,0x28,0x02,0xD0,0x40,0x1C,0x08,0xD0,0x10,0xE0,0x2C,0x48, + 0x28,0x38,0xC0,0x68,0x01,0x69,0x70,0x19,0x08,0x5C,0x04,0x21,0x06,0xE0,0x28,0x48, + 0x28,0x38,0xC0,0x68,0x01,0x69,0x70,0x19,0x08,0x5C,0x0C,0x21,0xFF,0xF7,0x60,0xF9, + 0x6D,0x1C,0xED,0xB2,0xA5,0x42,0xE3,0xD3,0x01,0x98,0x00,0x25,0xC0,0x00,0x04,0x90, + 0xE8,0x00,0x20,0x49,0x03,0x90,0x40,0x18,0x00,0x22,0x11,0x46,0x00,0xF0,0xFC,0xF8, + 0x1B,0x49,0x28,0x39,0x0A,0x69,0x04,0x99,0x49,0x19,0x49,0x00,0x02,0x91,0x50,0x54, + 0x18,0x49,0x03,0x98,0x49,0x1C,0x40,0x18,0x00,0x22,0x11,0x46,0x00,0xF0,0xEC,0xF8, + 0x13,0x49,0x6D,0x1C,0x28,0x39,0x0A,0x69,0x02,0x99,0xED,0xB2,0x49,0x1C,0x50,0x54, + 0x08,0x2D,0xDD,0xD3,0x00,0x25,0x0A,0xE0,0x0D,0x48,0x28,0x38,0xC0,0x68,0x01,0x69, + 0x70,0x19,0x08,0x5C,0x08,0x21,0xFF,0xF7,0x2B,0xF9,0x6D,0x1C,0xED,0xB2,0xA5,0x42, + 0xF2,0xD3,0x01,0x98,0x40,0x1C,0xC0,0xB2,0x7F,0x1C,0xFF,0xB2,0x01,0x90,0xA7,0x42, + 0x9E,0xD3,0x30,0x19,0xC6,0xB2,0x00,0x98,0x86,0x42,0x92,0xD3,0x05,0xB0,0xF0,0xBD, + 0x6C,0x21,0x00,0x20,0x40,0x03,0x00,0x40,0x02,0x48,0x01,0x78,0x00,0x29,0xFC,0xD0, + 0x70,0x47,0x00,0x00,0x44,0x21,0x00,0x20,0x03,0x46,0xF0,0xB5,0x00,0x20,0x84,0x46, + 0x17,0x48,0x06,0x22,0x44,0x7E,0x01,0x46,0x13,0x31,0x63,0x54,0x00,0x24,0x00,0x25, + 0x29,0x46,0x14,0x4F,0x0E,0xE0,0x63,0x18,0xDB,0xB2,0x93,0x42,0x01,0xD3,0x9B,0x1A, + 0xDB,0xB2,0x46,0x18,0xF6,0x7C,0xFB,0x5C,0x9E,0x42,0x05,0xD1,0x6D,0x1C,0x49,0x1C, + 0xED,0xB2,0xC9,0xB2,0x91,0x42,0xEE,0xD3,0x95,0x42,0x02,0xD1,0x01,0x21,0x8C,0x46, + 0x03,0xE0,0x64,0x1C,0xE4,0xB2,0x94,0x42,0xE1,0xD3,0x41,0x7E,0x52,0x1E,0x91,0x42, + 0x01,0xDA,0x49,0x1C,0x00,0xE0,0x00,0x21,0x41,0x76,0x60,0x46,0xF0,0xBD,0x00,0x00, + 0x68,0x20,0x00,0x20,0x44,0x6E,0x00,0x00,0x01,0x49,0x00,0x20,0x48,0x76,0x70,0x47, + 0x68,0x20,0x00,0x20,0x00,0x22,0x06,0xE0,0x00,0x21,0x49,0x1C,0x89,0xB2,0x42,0x29, + 0xFB,0xD3,0x52,0x1C,0x92,0xB2,0x82,0x42,0xF6,0xD3,0x70,0x47,0x0E,0x4A,0x00,0x21, + 0xC9,0x43,0x82,0x18,0x09,0x2A,0x01,0xD8,0x51,0xB2,0x0C,0xE0,0x0A,0x4A,0x30,0x3A, + 0x80,0x18,0x3B,0x28,0x07,0xD8,0xC0,0xB2,0xC1,0x08,0x40,0x07,0x89,0x00,0x40,0x0F, + 0x08,0x18,0x10,0x30,0x41,0xB2,0x48,0x1C,0x01,0xD0,0x40,0x29,0x01,0xD3,0x00,0x20, + 0x70,0x47,0x02,0x48,0x40,0x18,0x70,0x47,0xF0,0xFC,0xFF,0xBF,0x84,0x20,0x00,0x20, + 0xF0,0xB5,0x00,0x27,0x1C,0x4A,0x1D,0x4D,0xCC,0xB2,0x1D,0x4E,0x03,0x46,0xFD,0xF7, + 0x23,0xFB,0x0C,0x07,0x09,0x0B,0x19,0x1B,0x1D,0x1F,0x21,0x25,0x2B,0x2D,0x2F,0x31, + 0x51,0x81,0x27,0xE0,0x57,0x74,0x25,0xE0,0xE9,0x68,0xEA,0x68,0xE8,0x68,0x0B,0x46, + 0x91,0x42,0x00,0xD8,0x13,0x46,0x83,0x42,0x03,0xD9,0x08,0x46,0x91,0x42,0x00,0xD8, + 0x10,0x46,0xF0,0xBD,0x51,0x60,0x15,0xE0,0x94,0x73,0x13,0xE0,0xD4,0x73,0x11,0xE0, + 0xD0,0x7B,0xF0,0xBD,0x01,0x20,0x80,0x07,0x40,0x88,0xF0,0xBD,0x08,0x03,0x01,0x21, + 0xC9,0x03,0x08,0x43,0xF0,0x83,0x05,0xE0,0xF7,0x83,0x03,0xE0,0x50,0x7C,0xF0,0xBD, + 0xA0,0x20,0xA8,0x80,0x00,0x20,0xF0,0xBD,0x68,0x20,0x00,0x20,0x00,0x02,0x00,0x40, + 0x20,0x11,0x00,0x40,0x01,0x46,0x08,0x78,0x0A,0x78,0x0B,0x78,0x90,0x42,0xFA,0xD1, + 0x98,0x42,0xF8,0xD1,0x70,0x47,0x00,0x00,0x30,0xB5,0x03,0x46,0x0C,0x46,0x15,0x46, + 0xFF,0xF7,0x8C,0xFF,0x00,0x28,0x06,0xD0,0x0D,0x49,0x40,0x1A,0x40,0xB2,0x42,0x1C, + 0x01,0xD0,0x40,0x28,0x01,0xD3,0x00,0x20,0x30,0xBD,0x01,0x2C,0x01,0xD1,0x0D,0x54, + 0x09,0xE0,0x02,0x2C,0x02,0xD1,0x0A,0x5C,0x2A,0x43,0x03,0xE0,0x03,0x2C,0x04,0xD1, + 0x0A,0x5C,0x2A,0x40,0x0A,0x54,0x0A,0x5C,0x1A,0x70,0x08,0x5C,0x30,0xBD,0x00,0x00, + 0x84,0x20,0x00,0x20,0xF0,0xB5,0x21,0x4B,0x06,0x46,0x9D,0x44,0x20,0x4B,0x3B,0x20, + 0x6B,0x44,0x18,0x71,0x00,0x20,0x18,0x72,0x0D,0x46,0x14,0x46,0x58,0x72,0xFF,0xF7, + 0xD7,0xFA,0x2A,0xE0,0x01,0x27,0xBF,0x02,0xBC,0x42,0x00,0xD8,0x27,0x46,0x18,0x4B, + 0x28,0x0C,0x6B,0x44,0x58,0x71,0x28,0x0A,0x98,0x71,0xDD,0x71,0x00,0x22,0x15,0x48, + 0x00,0x92,0x7B,0x08,0x06,0x22,0x01,0xA9,0x68,0x44,0xFF,0xF7,0xD3,0xFA,0x12,0x49, + 0x48,0x07,0xC1,0x80,0x00,0x20,0x01,0xA9,0x82,0x00,0x8A,0x58,0x40,0x1C,0x04,0xC6, + 0x80,0xB2,0xFF,0x28,0xF8,0xD9,0x00,0x20,0x01,0x21,0x89,0x07,0xC8,0x80,0xED,0x19, + 0x08,0x15,0x84,0x42,0x03,0xD9,0x20,0x1A,0x84,0xB2,0x00,0x2C,0xD2,0xD1,0xFF,0xF7, + 0x6B,0xFA,0x04,0x4B,0x08,0x33,0x9D,0x44,0xF0,0xBD,0x00,0x00,0xF4,0xEF,0xFF,0xFF, + 0x00,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0xCA,0xCA,0x00,0x00,0x70,0xB5,0x0D,0x46, + 0x06,0x46,0x00,0x24,0x05,0xE0,0x30,0x5D,0x01,0x21,0xFE,0xF7,0xD9,0xFF,0x64,0x1C, + 0xE4,0xB2,0xAC,0x42,0xF7,0xD3,0x70,0xBD,0xF0,0xB5,0x00,0x22,0x08,0x4E,0x0B,0xE0, + 0x83,0x5C,0xDC,0x08,0xA4,0x19,0x25,0x7A,0x5F,0x07,0x7F,0x0F,0x01,0x23,0xBB,0x40, + 0x9D,0x43,0x25,0x72,0x52,0x1C,0xD2,0xB2,0x8A,0x42,0xF1,0xD3,0xF0,0xBD,0x00,0x00, + 0x60,0x12,0x00,0x40,0xF0,0xB5,0x00,0x22,0x08,0x4E,0x0B,0xE0,0x83,0x5C,0xDC,0x08, + 0xA4,0x19,0x25,0x7A,0x5F,0x07,0x7F,0x0F,0x01,0x23,0xBB,0x40,0x1D,0x43,0x25,0x72, + 0x52,0x1C,0xD2,0xB2,0x8A,0x42,0xF1,0xD3,0xF0,0xBD,0x00,0x00,0x60,0x12,0x00,0x40, + 0x06,0x4B,0xD8,0x80,0x59,0x81,0x98,0x88,0x10,0x21,0x08,0x43,0x98,0x80,0x5A,0x80, + 0x21,0x20,0x18,0x80,0x98,0x88,0xC0,0x06,0xFC,0xD5,0x70,0x47,0x00,0x11,0x00,0x40, + 0x30,0xB5,0x07,0x4B,0x9C,0x88,0x10,0x25,0x2C,0x43,0x9C,0x80,0xD8,0x80,0x19,0x81, + 0x5A,0x80,0x31,0x20,0x18,0x80,0x98,0x88,0xC0,0x06,0xFC,0xD5,0x30,0xBD,0x00,0x00, + 0x00,0x11,0x00,0x40,0x70,0xB5,0x03,0x4C,0x05,0x9E,0x04,0x9D,0xA5,0x61,0x40,0xC4, + 0x0F,0xC4,0x70,0xBD,0x78,0x21,0x00,0x20,0xF7,0xB5,0xDB,0x4D,0x04,0x46,0xA8,0x69, + 0x8A,0xB0,0x00,0x79,0x01,0x90,0x0E,0x46,0xD8,0x49,0x04,0x20,0x2F,0x68,0x03,0xF0, + 0x2B,0xF9,0xA9,0x69,0x08,0x78,0x89,0x78,0x00,0x29,0x00,0xD1,0x30,0x46,0x00,0x23, + 0x1A,0x46,0x0F,0x21,0xFF,0xF7,0xB4,0xFB,0xCF,0x4D,0xC2,0x22,0x28,0x69,0x01,0x78, + 0x38,0x46,0xFD,0xF7,0x71,0xF9,0x28,0x69,0x39,0x46,0x02,0x78,0x40,0x68,0xFF,0xF7, + 0xBF,0xFF,0x68,0x68,0x00,0x78,0x00,0x28,0x04,0xD0,0x28,0x46,0x80,0x69,0x80,0x78, + 0x00,0x28,0x1F,0xD1,0xC4,0x4D,0xA9,0x69,0x88,0x78,0x00,0x28,0x01,0xD0,0x68,0x69, + 0x04,0x78,0x28,0x69,0xC9,0x78,0x03,0x78,0x42,0x68,0x20,0x46,0x00,0xF0,0x82,0xF9, + 0x01,0x46,0x68,0x68,0x0A,0x0A,0x01,0x75,0x42,0x75,0x02,0x46,0x20,0x32,0x11,0x73, + 0x0B,0x0A,0x53,0x73,0xAA,0x69,0x21,0x23,0x9B,0x5C,0x8B,0x42,0x1A,0xD8,0x91,0x78, + 0x00,0x29,0x17,0xD0,0x00,0x20,0x05,0x90,0xB3,0x4F,0x06,0x46,0x00,0x90,0xB8,0x69, + 0xB3,0x4D,0x41,0x79,0x00,0x29,0x04,0xD0,0x78,0x68,0xC0,0x79,0xFD,0xF7,0xEA,0xF8, + 0x00,0x91,0x01,0x99,0x00,0x98,0x48,0x43,0x06,0x90,0x79,0x69,0x08,0x18,0x00,0x24, + 0x08,0x90,0x79,0xE0,0x00,0x21,0xC1,0x73,0x81,0x70,0xC1,0x71,0x04,0x74,0x3B,0xE1, + 0xA5,0x4F,0x08,0x98,0x39,0x69,0x00,0x5D,0x0B,0x78,0x4A,0x68,0xB9,0x69,0xC9,0x78, + 0x00,0xF0,0x48,0xF9,0x62,0x00,0x02,0xA9,0x88,0x52,0x06,0x9B,0x79,0x68,0x1B,0x19, + 0x5B,0x00,0x07,0x93,0x2C,0x33,0xCF,0x18,0xBC,0x46,0x7B,0x78,0x3F,0x78,0x1B,0x02, + 0x3B,0x43,0x67,0x46,0x38,0x70,0x00,0x0A,0x78,0x70,0x02,0xA8,0x80,0x5A,0xC7,0x1A, + 0x00,0x2F,0x00,0xDC,0x1F,0x1A,0xC0,0x19,0x83,0xB2,0x02,0xA8,0x83,0x52,0x07,0x98, + 0x14,0x30,0x08,0x18,0x84,0x46,0x47,0x78,0x00,0x78,0x3F,0x02,0x07,0x43,0xD8,0x1B, + 0x19,0x28,0x07,0xDD,0x58,0x00,0x18,0x18,0x38,0x18,0x80,0x03,0x03,0x0C,0x02,0xA8, + 0x83,0x52,0x06,0xE0,0x78,0x00,0x38,0x18,0xC0,0x18,0x80,0x03,0x02,0xAF,0x00,0x0C, + 0xB8,0x52,0x02,0xAF,0xBB,0x5A,0x60,0x46,0x03,0x70,0x1B,0x0A,0x43,0x70,0xB8,0x5A, + 0xA8,0x42,0x01,0xD2,0x05,0x46,0x05,0x94,0xB0,0x42,0x00,0xD9,0x06,0x46,0x7E,0x48, + 0x80,0x69,0x20,0x30,0x40,0x78,0xA8,0x42,0x1C,0xD9,0x08,0x78,0x00,0x28,0x19,0xD1, + 0x48,0x78,0xA0,0x42,0x16,0xD1,0x8A,0x78,0x00,0x98,0x82,0x42,0x12,0xD1,0x76,0x4A, + 0x50,0x68,0xC0,0x79,0x40,0x1E,0xC8,0x71,0x4C,0x70,0x00,0x98,0x88,0x70,0x68,0x46, + 0x03,0x89,0x90,0x69,0x20,0x30,0x40,0x78,0x0A,0x38,0x83,0x42,0x01,0xDA,0x00,0x20, + 0x48,0x70,0x90,0xE0,0x64,0x1C,0xE4,0xB2,0x01,0x98,0x84,0x42,0x88,0xD3,0x6A,0x49, + 0x00,0x98,0x4C,0x68,0x05,0x9A,0x11,0x30,0x22,0x54,0xA0,0x78,0x06,0x90,0x07,0x90, + 0x60,0x78,0x08,0x90,0x09,0x90,0x00,0x9F,0x89,0x69,0x05,0x91,0x64,0x4D,0x00,0x20, + 0x4B,0x79,0x14,0xE0,0x01,0x46,0x11,0x31,0x61,0x5C,0xFF,0x29,0x0D,0xD0,0x01,0x9A, + 0x42,0x43,0x51,0x18,0x49,0x00,0x14,0x31,0x0A,0x19,0x51,0x78,0x12,0x78,0x09,0x02, + 0x11,0x43,0xA9,0x42,0x01,0xD2,0x0D,0x46,0x07,0x46,0x40,0x1C,0xC0,0xB2,0x83,0x42, + 0xE8,0xD8,0x57,0x48,0x85,0x42,0x04,0xD0,0x38,0x46,0x11,0x30,0x07,0x97,0x20,0x5C, + 0x09,0x90,0x20,0x46,0x08,0x30,0x00,0x90,0xFD,0xF7,0x89,0xF8,0x00,0x28,0x12,0xD1, + 0x05,0x99,0x20,0x31,0xCA,0x78,0x0C,0x99,0x8A,0x42,0x0C,0xD8,0x38,0x46,0xA7,0x73, + 0x11,0x30,0x21,0x5C,0xE1,0x73,0xA7,0x70,0x20,0x5C,0x60,0x70,0x01,0x20,0x00,0x99, + 0xFD,0xF7,0x7E,0xF8,0x3F,0xE0,0x09,0x9A,0x08,0x99,0x91,0x42,0x03,0xD1,0x07,0x9A, + 0x06,0x99,0x91,0x42,0x27,0xD0,0x01,0x9A,0x06,0x99,0x01,0x9B,0x51,0x43,0x08,0x9A, + 0x89,0x18,0x49,0x00,0x14,0x31,0x09,0x19,0x4A,0x78,0x09,0x78,0x12,0x02,0x0A,0x43, + 0x07,0x99,0x59,0x43,0x09,0x9B,0xC9,0x18,0x49,0x00,0x14,0x31,0x61,0x18,0x4B,0x78, + 0x0F,0x78,0x19,0x02,0x39,0x43,0x1E,0x31,0x8A,0x42,0x12,0xD9,0x05,0x99,0x0C,0x9A, + 0x20,0x31,0xCB,0x78,0x93,0x42,0x0C,0xD8,0x89,0x78,0x88,0x42,0x06,0xD3,0x09,0x98, + 0x60,0x70,0x07,0x98,0xA0,0x70,0x01,0x20,0x00,0x99,0x06,0xE0,0x40,0x1C,0x00,0x99, + 0x03,0xE0,0x01,0x28,0x03,0xD9,0x40,0x1E,0x00,0x99,0xFD,0xF7,0x41,0xF8,0x09,0x98, + 0xE0,0x73,0x07,0x98,0xA0,0x73,0x24,0x4C,0xA1,0x69,0x20,0x31,0x48,0x78,0x40,0x00, + 0xB0,0x42,0x0B,0xD2,0x60,0x68,0x1E,0x22,0x02,0x70,0x49,0x78,0x0A,0x23,0x59,0x43, + 0xB1,0x42,0x1A,0xD2,0x02,0x73,0x11,0x0A,0x41,0x73,0x16,0xE0,0x60,0x68,0x42,0x7B, + 0x03,0x7B,0x12,0x02,0x1A,0x43,0x03,0xD0,0x52,0x1E,0x02,0x73,0x12,0x0A,0x42,0x73, + 0x49,0x78,0xB1,0x42,0x09,0xD9,0x01,0x78,0x00,0x29,0x06,0xD0,0x49,0x1E,0x09,0x06, + 0x09,0x0E,0x01,0x70,0x01,0xD1,0xFF,0xF7,0xFD,0xF8,0x60,0x68,0x2A,0x0A,0xC5,0x70, + 0x02,0x71,0x46,0x71,0x32,0x0A,0x82,0x71,0x82,0x78,0x01,0x99,0x63,0x69,0x4A,0x43, + 0x99,0x18,0x42,0x78,0x89,0x5C,0x01,0x74,0x08,0x20,0xFE,0xF7,0xAD,0xFF,0x06,0x4C, + 0x20,0x69,0x01,0x78,0x40,0x68,0xFF,0xF7,0xF7,0xFD,0x60,0x68,0xC1,0x79,0x49,0x1C, + 0xC1,0x71,0x00,0x7C,0x0D,0xB0,0xF0,0xBD,0x78,0x21,0x00,0x20,0xC9,0x1C,0x00,0x00, + 0xFF,0x7F,0x00,0x00,0xFF,0xB5,0x39,0x4A,0x1E,0x46,0x11,0x68,0x83,0xB0,0x9B,0x00, + 0xCD,0x18,0x01,0x91,0x73,0x00,0xD2,0x68,0xCC,0x18,0xD1,0x78,0x43,0x1E,0x99,0x42, + 0x01,0xDD,0x01,0x23,0x01,0xE0,0x41,0x1A,0xCB,0xB2,0x31,0x49,0xCF,0x88,0xFF,0xB2, + 0xCF,0x80,0xCF,0x88,0x00,0x02,0x07,0x43,0xCF,0x80,0x08,0x89,0x00,0x0A,0x00,0x02, + 0x08,0x81,0x08,0x89,0x18,0x43,0x08,0x81,0x28,0x49,0x88,0x69,0x00,0x78,0x00,0x90, + 0x88,0x68,0x53,0x79,0x01,0x79,0x12,0x79,0xC0,0x78,0xFE,0xF7,0x2B,0xFE,0x00,0x90, + 0x00,0x20,0x03,0x46,0x23,0x4A,0x04,0xE0,0x41,0x00,0x6A,0x52,0x40,0x1C,0x63,0x52, + 0xC0,0xB2,0xB0,0x42,0xF8,0xD3,0x00,0x27,0x25,0xE0,0x1C,0x48,0x01,0x23,0xC0,0x68, + 0x1A,0x46,0x41,0x79,0x00,0x79,0xFE,0xF7,0x2F,0xFF,0x32,0x46,0x01,0x99,0x05,0x98, + 0xFF,0xF7,0xCE,0xFD,0x00,0x23,0x31,0x46,0x00,0x9A,0x01,0x98,0x00,0xF0,0x2C,0xF8, + 0x00,0x21,0x0C,0xE0,0x4A,0x00,0x01,0x98,0xAB,0x5E,0x80,0x5A,0x83,0x42,0x00,0xDD, + 0xA8,0x52,0xA3,0x5E,0x83,0x42,0x00,0xDA,0xA0,0x52,0x49,0x1C,0xC9,0xB2,0xB1,0x42, + 0xF0,0xD3,0x7F,0x1C,0xFF,0xB2,0x04,0x98,0x87,0x42,0xD6,0xD3,0x00,0x21,0x08,0x46, + 0x07,0xE0,0x42,0x00,0xA3,0x5A,0xAA,0x5A,0x9A,0x1A,0x51,0x18,0x40,0x1C,0x89,0xB2, + 0xC0,0xB2,0xB0,0x42,0xF5,0xD3,0x88,0x08,0x07,0xB0,0xF0,0xBD,0x78,0x21,0x00,0x20, + 0x00,0x10,0x00,0x40,0xFF,0x7F,0x00,0x00,0xF0,0xB5,0x00,0x24,0x01,0x25,0xED,0x03, + 0xAE,0x1A,0x27,0x46,0x0C,0xE0,0x62,0x00,0x85,0x5A,0xB5,0x42,0x02,0xDD,0xAD,0x1B, + 0x85,0x52,0x00,0xE0,0x87,0x52,0x85,0x5A,0xDD,0x40,0x64,0x1C,0x85,0x52,0xA4,0xB2, + 0x8C,0x42,0xF0,0xD3,0xF0,0xBD,0x00,0x00,0x01,0x22,0x82,0x40,0x00,0xB5,0x06,0x48, + 0xD2,0xB2,0x00,0x29,0x01,0xD0,0x02,0x21,0x02,0xE0,0xD1,0x43,0xCA,0xB2,0x03,0x21, + 0xFF,0xF7,0xCA,0xFC,0x00,0xBD,0x00,0x00,0x10,0x03,0x00,0x40,0x02,0x00,0x00,0xB5, + 0x06,0x48,0x41,0x7B,0x00,0x7B,0x03,0xD0,0xC9,0x07,0xC9,0x17,0x49,0x1C,0x01,0xE0, + 0xC9,0x07,0xC9,0x0F,0xFF,0xF7,0xE0,0xFF,0x00,0xBD,0x00,0x00,0x68,0x20,0x00,0x20, + 0xF8,0xB5,0x21,0x4E,0x0D,0x46,0xF1,0x78,0x14,0x46,0xF3,0x68,0xB7,0x69,0x1A,0x78, + 0x51,0x43,0xC9,0x19,0x00,0x28,0x05,0xD0,0x58,0x68,0xFF,0xF7,0x61,0xFD,0xF0,0x78, + 0xFF,0xF7,0x3E,0xFB,0x00,0x2D,0x0A,0xD0,0x0C,0x20,0x01,0x21,0x89,0x07,0x48,0x80, + 0x70,0x68,0x00,0x23,0x41,0x79,0x00,0x79,0x01,0x22,0xFE,0xF7,0x9D,0xFE,0x00,0x2C, + 0x1E,0xD0,0x11,0x48,0xF4,0x68,0x28,0x30,0x45,0x78,0x60,0x78,0x29,0x46,0x07,0x46, + 0xFC,0xF7,0xA8,0xFE,0x00,0x29,0x14,0xD0,0x68,0x1A,0x40,0x1E,0xF1,0x78,0xC0,0x19, + 0x88,0x42,0x0D,0xDD,0xF0,0x78,0x22,0x78,0x40,0x1C,0xB1,0x69,0x50,0x43,0x41,0x18, + 0x60,0x68,0xFF,0xF7,0x35,0xFD,0xF0,0x78,0x40,0x1C,0xC0,0xB2,0xFF,0xF7,0x10,0xFB, + 0xF8,0xBD,0x00,0x20,0xE9,0xE7,0x00,0x00,0x44,0x21,0x00,0x20,0xF8,0xB5,0x05,0x46, + 0x0E,0x46,0x16,0x49,0x08,0x20,0x02,0xF0,0x77,0xFE,0x15,0x48,0x15,0x4C,0x05,0x81, + 0x20,0x88,0x20,0x27,0x38,0x40,0x88,0x30,0x20,0x80,0x64,0x2D,0x05,0xD2,0x00,0x20, + 0x60,0x81,0x28,0x01,0xE1,0x13,0x08,0x43,0x08,0xE0,0x14,0x21,0x28,0x46,0xFC,0xF7, + 0x71,0xFE,0x01,0x21,0xC9,0x03,0x08,0x43,0x60,0x81,0x0B,0x48,0x20,0x81,0x20,0x88, + 0x08,0x21,0x88,0x43,0x20,0x80,0xAA,0x20,0xA0,0x80,0x20,0x88,0x38,0x43,0x20,0x80, + 0x00,0x2E,0x01,0xD0,0x02,0x48,0x06,0x60,0xF8,0xBD,0x00,0x00,0x15,0x6B,0x00,0x00, + 0x68,0x20,0x00,0x20,0x00,0x02,0x00,0x40,0x40,0x81,0x00,0x00,0x70,0xB5,0x22,0x4A, + 0xCA,0x21,0x11,0x74,0x51,0x74,0x00,0x25,0x49,0x07,0xCD,0x80,0x1E,0x4A,0x20,0x3A, + 0x95,0x72,0x0B,0x89,0x04,0x24,0x23,0x43,0x0B,0x81,0x0B,0x89,0x08,0x24,0x23,0x43, + 0x0B,0x81,0x4B,0x89,0x80,0x24,0x23,0x43,0x4B,0x81,0x00,0x28,0x02,0xD0,0x30,0x20, + 0x10,0x71,0x00,0xE0,0x15,0x71,0x00,0xF0,0x0B,0xFC,0x13,0x4C,0x12,0x4E,0x0F,0x3C, + 0xF6,0x1F,0x00,0x21,0x20,0x46,0xFF,0xF7,0x05,0xFC,0x02,0x46,0x01,0x21,0x20,0x46, + 0xFF,0xF7,0x0A,0xFC,0x64,0x1C,0xB4,0x42,0xF3,0xD9,0x0B,0x4C,0x0A,0x4E,0x20,0x34, + 0x5B,0x36,0x00,0x22,0x01,0x21,0x20,0x46,0xFF,0xF7,0xFE,0xFB,0x64,0x1C,0xB4,0x42, + 0xF7,0xD9,0x06,0x48,0xFF,0x21,0x45,0x74,0x41,0x81,0x85,0x73,0x01,0x21,0xC1,0x73, + 0x01,0x81,0x05,0x60,0x45,0x76,0x70,0xBD,0x20,0x03,0x00,0x40,0x68,0x20,0x00,0x20, + 0xFF,0xB5,0x98,0x78,0x19,0x78,0x95,0xB0,0x40,0x1A,0x40,0x1C,0x1F,0x9F,0x10,0x90, + 0xD8,0x78,0x59,0x78,0x1E,0x9D,0x40,0x1A,0x40,0x1C,0x11,0x90,0x10,0x98,0x1C,0x46, + 0x02,0x28,0x05,0xDC,0x11,0x98,0x02,0x28,0x02,0xDC,0x00,0x20,0x19,0xB0,0xF0,0xBD, + 0x11,0x99,0x10,0x98,0x46,0x18,0x30,0x01,0x81,0x1B,0x18,0x31,0x38,0x46,0xFC,0xF7, + 0x3A,0xFE,0x0C,0x20,0x70,0x43,0xC1,0x19,0x12,0x91,0x10,0x98,0x08,0x71,0x12,0x99, + 0x11,0x98,0x88,0x72,0x12,0x99,0x70,0x1E,0x08,0x74,0x12,0x99,0x88,0x75,0x10,0x98, + 0x0C,0x97,0x80,0x00,0x11,0x99,0xC0,0x19,0x0D,0x90,0x89,0x00,0x40,0x18,0x0E,0x90, + 0xF0,0x00,0xC0,0x19,0x00,0x1F,0x0F,0x90,0x14,0x21,0x15,0x98,0x00,0x22,0x41,0x56, + 0x08,0x91,0x6E,0xE0,0x20,0x78,0x08,0x99,0x80,0x18,0x48,0x43,0x61,0x78,0x40,0x18, + 0x84,0x46,0x00,0x21,0x61,0xE0,0x17,0x98,0x63,0x46,0xC0,0x5C,0x23,0x79,0x9B,0x08, + 0x98,0x42,0x01,0xD0,0x15,0x28,0x54,0xD1,0x16,0x9B,0x66,0x46,0x9B,0x5D,0x00,0x20, + 0x14,0x3B,0x00,0x2B,0x00,0xDD,0x18,0x46,0x93,0x00,0x0C,0x9E,0x01,0x93,0xF3,0x58, + 0x01,0x26,0x36,0x04,0x07,0x46,0x37,0x43,0xDE,0x19,0xBE,0x46,0x0C,0x9F,0x01,0x9B, + 0xFE,0x50,0x8B,0x00,0x0D,0x9E,0x00,0x93,0xF6,0x58,0x0D,0x9F,0x76,0x44,0xFE,0x50, + 0x53,0x18,0x9B,0x00,0x0E,0x9E,0x09,0x93,0x07,0x93,0xF3,0x58,0x77,0x46,0xDE,0x19, + 0x0E,0x9F,0x07,0x9B,0xFE,0x50,0x11,0x9B,0x57,0x1A,0xFB,0x18,0x9B,0x00,0x02,0x93, + 0x0F,0x9E,0x1B,0x1F,0x0B,0x93,0xF3,0x58,0x77,0x46,0xDE,0x19,0x0F,0x9F,0x0B,0x9B, + 0xFE,0x50,0x01,0x9B,0x0C,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0C,0x9E, + 0xF0,0x54,0x00,0x9B,0x0D,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0D,0x9E, + 0xF0,0x54,0x09,0x9B,0x0E,0x9E,0xDB,0x1C,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0E,0x9E, + 0xF0,0x54,0x02,0x9B,0x0F,0x9E,0x5B,0x1E,0xF6,0x5C,0x86,0x42,0x01,0xDA,0x0F,0x9E, + 0xF0,0x54,0x49,0x1C,0x60,0x46,0x40,0x1C,0x84,0x46,0x11,0x98,0x81,0x42,0x9A,0xDB, + 0x52,0x1C,0x10,0x98,0x82,0x42,0x8D,0xDB,0x00,0x27,0x78,0x1E,0x01,0x90,0x02,0x90, + 0xE7,0x81,0x20,0x98,0x19,0x21,0xC0,0x30,0x08,0x90,0x40,0x69,0x3E,0x46,0x00,0x7F, + 0x48,0x43,0x21,0x99,0x40,0x18,0x09,0x90,0x00,0x20,0x07,0xAB,0x07,0x90,0x00,0x93, + 0xB0,0x00,0x0C,0xA9,0x0A,0x90,0x08,0x58,0x72,0xB2,0x20,0x9B,0x12,0x99,0x00,0xF0, + 0xA1,0xF9,0x00,0x28,0x17,0xDD,0x08,0x99,0x49,0x69,0x89,0x68,0xC9,0x06,0x04,0xD5, + 0x00,0x2E,0x02,0xD1,0x07,0x99,0x14,0x39,0x07,0x91,0x07,0x99,0xB9,0x42,0x0A,0xDD, + 0x0A,0x9A,0x0C,0xAB,0x9B,0x58,0x82,0x00,0x92,0x1C,0x9A,0x5C,0x08,0x2A,0x02,0xD2, + 0x0F,0x46,0x01,0x96,0x02,0x90,0xE1,0x89,0x07,0x98,0x81,0x42,0x00,0xDB,0x08,0x46, + 0x76,0x1C,0xE0,0x81,0x04,0x2E,0xCF,0xDB,0x01,0x98,0x40,0x1C,0x08,0xD0,0xE0,0x89, + 0x00,0x28,0x05,0xD0,0xFF,0x22,0x09,0x99,0x24,0x32,0x51,0x1A,0x88,0x42,0x02,0xDA, + 0x01,0x20,0xA0,0x72,0x11,0xE7,0x15,0x98,0x15,0x21,0x41,0x56,0x12,0x91,0x14,0x21, + 0x41,0x56,0x01,0x98,0x07,0x91,0x00,0xB2,0x09,0x90,0x02,0x98,0x00,0xB2,0x0B,0x90, + 0xA1,0x78,0x20,0x78,0x09,0x1A,0x49,0x1C,0x13,0x91,0xE2,0x78,0x61,0x78,0x11,0x91, + 0x52,0x1A,0x52,0x1C,0x0A,0x92,0xAA,0x4A,0x00,0x21,0x22,0x80,0x61,0x80,0x2A,0x80, + 0x69,0x80,0x0F,0x46,0x02,0x91,0x01,0x90,0x56,0xE0,0x11,0x98,0x00,0x26,0x00,0x90, + 0x4B,0xE0,0x00,0x20,0x09,0x99,0xC0,0x43,0x00,0x29,0x06,0xD0,0x01,0x29,0x06,0xD0, + 0x02,0x29,0x06,0xD0,0x03,0x29,0x06,0xD0,0x09,0xE0,0x38,0x46,0x07,0xE0,0x30,0x46, + 0x05,0xE0,0xB8,0x19,0x03,0xE0,0x0A,0x98,0xB9,0x1B,0x08,0x18,0x40,0x1E,0x07,0x9A, + 0x01,0x99,0x00,0x9B,0x51,0x43,0x17,0x9A,0xD2,0x18,0x10,0x92,0x23,0x79,0x8A,0x5C, + 0x9B,0x08,0x9C,0x46,0x9A,0x42,0x01,0xD0,0x15,0x2A,0x22,0xD1,0x0B,0x9B,0x98,0x42, + 0x0E,0xD1,0x02,0x98,0x03,0xAA,0x40,0x00,0x01,0x9B,0x13,0x54,0x80,0x18,0x00,0x9B, + 0x43,0x70,0x02,0x98,0x40,0x1C,0x02,0x90,0x10,0x98,0x15,0x22,0x0A,0x54,0x10,0xE0, + 0x98,0x42,0x09,0xDD,0x62,0x45,0x03,0xD1,0x28,0x79,0x82,0x08,0x10,0x98,0x0A,0x54, + 0x28,0x46,0x00,0x9A,0x01,0x99,0x02,0xE0,0x20,0x46,0x00,0x9A,0x01,0x99,0x02,0xF0, + 0x2D,0xFD,0x00,0x98,0x76,0x1C,0x40,0x1C,0x00,0x90,0x0A,0x98,0x86,0x42,0xB0,0xDB, + 0x01,0x98,0x7F,0x1C,0x40,0x1C,0x01,0x90,0x13,0x98,0x87,0x42,0xA5,0xDB,0x00,0x20, + 0x6A,0xE0,0x01,0x99,0x00,0x23,0x49,0x00,0x03,0x20,0x03,0xAA,0x0A,0x91,0x89,0x18, + 0x09,0x91,0x0A,0x99,0x1F,0x46,0x51,0x5C,0x00,0x91,0x09,0x99,0x49,0x78,0x8C,0x46, + 0x00,0x9E,0x61,0x46,0xC2,0x07,0x05,0xD0,0x09,0x18,0x07,0x9A,0x89,0x1E,0x91,0x42, + 0x18,0xD2,0x04,0xE0,0x36,0x18,0x12,0x9A,0x76,0x1E,0x96,0x42,0x12,0xD2,0x07,0x9A, + 0x56,0x43,0x16,0x9A,0x71,0x18,0x56,0x5C,0x17,0x9A,0x14,0x3E,0x51,0x5C,0x22,0x79, + 0x92,0x08,0x91,0x42,0x01,0xD1,0x9B,0x19,0x04,0xE0,0x2A,0x79,0x92,0x08,0x91,0x42, + 0x00,0xD1,0xBF,0x19,0x40,0x1E,0xDB,0xD5,0x07,0x99,0x00,0x98,0x15,0x26,0x48,0x43, + 0x61,0x46,0x41,0x18,0x16,0x98,0x40,0x5C,0x14,0x38,0x98,0x42,0x03,0xDD,0xB8,0x42, + 0x01,0xDD,0x16,0x26,0x07,0xE0,0x9F,0x42,0x01,0xDA,0x20,0x79,0x02,0xE0,0xBB,0x42, + 0x01,0xDA,0x28,0x79,0x86,0x08,0x20,0x79,0x80,0x08,0xB0,0x42,0x04,0xD0,0x62,0x46, + 0x28,0x46,0x00,0x99,0x02,0xF0,0xCA,0xFC,0x28,0x79,0x80,0x08,0xB0,0x42,0x07,0xD0, + 0x09,0x99,0x03,0xA8,0x4A,0x78,0x0A,0x99,0x41,0x5C,0x20,0x46,0x02,0xF0,0xBE,0xFC, + 0x0A,0x99,0x03,0xA8,0x40,0x5C,0x07,0x99,0x48,0x43,0x09,0x99,0x49,0x78,0x41,0x18, + 0x17,0x98,0x46,0x54,0x01,0x98,0x40,0x1C,0x02,0x99,0x01,0x90,0x88,0x42,0x90,0xDB, + 0x08,0xB2,0x09,0x90,0x08,0x98,0x17,0x99,0x40,0x69,0x1F,0x27,0x03,0x7D,0x82,0x7D, + 0x68,0x46,0x0E,0xC0,0x20,0x79,0xFF,0x23,0x82,0x08,0x21,0x46,0x15,0x98,0xFD,0xF7, + 0x39,0xFC,0x07,0x90,0x08,0x98,0x40,0x69,0x41,0x7F,0x07,0x98,0x81,0x42,0x13,0xDB, + 0x20,0x79,0x14,0x21,0x87,0x08,0x15,0x98,0x2B,0x46,0x41,0x56,0x3A,0x46,0x17,0x98, + 0x00,0xF0,0x3F,0xF9,0x15,0x98,0x14,0x21,0x41,0x56,0x23,0x46,0x1F,0x22,0x17,0x98, + 0x00,0xF0,0x37,0xF9,0x28,0x68,0x20,0x60,0x08,0x98,0x17,0x99,0x40,0x69,0x03,0x7D, + 0x82,0x7D,0x68,0x46,0x0E,0xC0,0x28,0x79,0xFF,0x23,0x82,0x08,0x29,0x46,0x15,0x98, + 0xFD,0xF7,0x10,0xFC,0x00,0x90,0x08,0x98,0x40,0x69,0x41,0x7F,0x00,0x98,0x81,0x42, + 0x22,0xDB,0x28,0x79,0x14,0x21,0x87,0x08,0x15,0x98,0x2B,0x46,0x41,0x56,0x1F,0x22, + 0x17,0x98,0x00,0xF0,0x16,0xF9,0x00,0x26,0x13,0xE0,0x15,0x98,0x14,0x21,0x41,0x56, + 0x70,0x00,0x03,0xAA,0x13,0x5C,0x80,0x18,0x42,0x78,0x59,0x43,0x88,0x18,0x21,0x79, + 0x9C,0x46,0x8B,0x08,0x17,0x99,0x0B,0x54,0x61,0x46,0x20,0x46,0x02,0xF0,0x4E,0xFC, + 0x76,0x1C,0x09,0x98,0x86,0x42,0xE8,0xDB,0x1F,0x2F,0x02,0xD0,0x00,0x20,0xC0,0x43, + 0xBC,0xE5,0x07,0x98,0xA0,0x71,0x21,0x79,0x01,0x20,0x01,0x43,0x21,0x71,0x00,0x99, + 0xA9,0x71,0x29,0x79,0x01,0x43,0x29,0x71,0xE1,0x89,0xA9,0x81,0x00,0x21,0xE1,0x81, + 0xA9,0x89,0xA1,0x81,0x02,0x21,0xA9,0x72,0x61,0x79,0x69,0x71,0xA6,0xE5,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0xFF,0xB5,0x10,0x46,0x06,0x21,0x91,0xB0,0x48,0x43,0x12,0x99, + 0x0E,0x90,0x40,0x18,0x04,0x21,0x0C,0x90,0x41,0x56,0x01,0x20,0x14,0x46,0x02,0x2A, + 0x00,0xDB,0x00,0x20,0x00,0x26,0x08,0x18,0xF6,0x43,0x03,0x28,0x02,0xDC,0x30,0x46, + 0x15,0xB0,0xF0,0xBD,0x1D,0x46,0xC0,0x35,0x01,0x2C,0x04,0xDD,0x68,0x69,0x02,0x7D, + 0x11,0x98,0x00,0xF0,0xE5,0xF8,0x68,0x69,0x3D,0x21,0x00,0x7E,0x48,0x43,0x80,0x30, + 0x01,0x0A,0x02,0x2C,0x02,0xDB,0x2D,0x20,0x41,0x43,0x89,0x11,0x01,0x20,0x80,0x04, + 0x0A,0x91,0xFC,0xF7,0x7D,0xFB,0x00,0x27,0x00,0x26,0x0B,0x90,0xFF,0x43,0x11,0x98, + 0x03,0x97,0x09,0x96,0x00,0x88,0x06,0x96,0x0F,0x96,0x01,0x90,0x05,0x96,0x07,0x97, + 0x01,0x20,0x00,0x90,0x0C,0x99,0x08,0x97,0x04,0x20,0x08,0x56,0x34,0x46,0x04,0x90, + 0x6E,0xE0,0x88,0x00,0x11,0x99,0x00,0x9A,0x41,0x18,0x20,0x39,0x89,0x8B,0x4D,0x42, + 0x04,0x99,0x91,0x42,0x02,0xDD,0x11,0x99,0x08,0x5A,0x45,0x19,0x01,0x98,0x68,0x43, + 0x00,0x28,0x41,0xDA,0x01,0x99,0x10,0x46,0x48,0x43,0x09,0x99,0x69,0x43,0x40,0x1A, + 0x0A,0x99,0x48,0x43,0x01,0x99,0x49,0x1B,0xFC,0xF7,0x4A,0xFB,0x02,0x90,0x03,0x98, + 0x40,0x1C,0x37,0xD0,0x78,0x1C,0x38,0xD0,0x03,0x99,0x02,0x98,0x40,0x1A,0x0F,0x99, + 0x88,0x42,0x23,0xDD,0x0F,0x90,0x0B,0x98,0x03,0x99,0x07,0x91,0x78,0x43,0x02,0x99, + 0x80,0x14,0x08,0x91,0x81,0x00,0x11,0x98,0x42,0x5A,0x00,0x2A,0x27,0xD0,0xA6,0x42, + 0x02,0xDD,0x66,0x40,0x74,0x40,0x66,0x40,0x28,0x21,0x28,0x2A,0x03,0xD9,0xFA,0x21, + 0xFA,0x2A,0x00,0xD2,0x11,0x46,0x8C,0x42,0x00,0xDB,0x0C,0x46,0x30,0x19,0x80,0x00, + 0xF2,0x00,0x80,0x18,0xFC,0xF7,0x1C,0xFB,0x06,0x97,0x05,0x90,0x00,0x27,0xFF,0x43, + 0x02,0x98,0x00,0x26,0x34,0x46,0x03,0x90,0x03,0x98,0x40,0x1C,0x0C,0xD0,0x78,0x1C, + 0x08,0xD0,0x0B,0xE0,0x02,0x98,0x03,0x90,0xF6,0xE7,0x02,0x9F,0xF7,0xE7,0x7D,0x20, + 0xC0,0x00,0xE9,0xE7,0x76,0x1B,0x02,0xE0,0x78,0x1C,0x00,0xD0,0x64,0x19,0x00,0x2D, + 0x02,0xD0,0x00,0x98,0x01,0x95,0x09,0x90,0x00,0x98,0x40,0x1C,0x00,0x90,0x04,0x98, + 0x00,0x99,0x88,0x42,0x8D,0xDA,0x06,0x98,0x0B,0x99,0x40,0x00,0x40,0x1C,0x48,0x43, + 0x12,0x9B,0x0E,0x9A,0x07,0x99,0x99,0x52,0x0C,0x9A,0x08,0x99,0x51,0x80,0x0A,0x9A, + 0x0F,0x99,0x53,0x00,0xC0,0x14,0xD2,0x18,0x8A,0x42,0x00,0xDC,0x11,0x46,0x05,0x9B, + 0x01,0x22,0x4B,0x43,0x92,0x02,0x9C,0x10,0x94,0x42,0x00,0xDA,0x22,0x46,0x1A,0x9C, + 0x0F,0x2B,0x22,0x60,0x02,0xDB,0x0F,0x29,0x00,0xDB,0x39,0xE7,0x00,0x20,0xC0,0x43, + 0x36,0xE7,0xFF,0xB5,0xD1,0xB2,0x96,0x46,0x1C,0x78,0x8C,0x46,0x12,0xE0,0x01,0x9A, + 0x59,0x78,0x62,0x43,0x0A,0xE0,0x55,0x18,0x1F,0x79,0x46,0x5D,0xBF,0x08,0xBE,0x42, + 0x01,0xD0,0x15,0x2E,0x01,0xD1,0x66,0x46,0x46,0x55,0x49,0x1C,0xDD,0x78,0x8D,0x42, + 0xF1,0xDA,0x64,0x1C,0x99,0x78,0xA1,0x42,0xE9,0xDA,0x70,0x46,0x1F,0x28,0x06,0xD0, + 0x18,0x79,0x71,0x46,0x80,0x07,0x80,0x0F,0x89,0x00,0x08,0x43,0x18,0x71,0xFF,0xBD, + 0xFE,0xB5,0x04,0x46,0x00,0x20,0x0E,0x46,0x4B,0x1E,0x49,0x1E,0x84,0x46,0x01,0x91, + 0x0B,0xE0,0x81,0x00,0x0D,0x19,0xE9,0x78,0xED,0x79,0xA9,0x42,0x03,0xD3,0x91,0x42, + 0x01,0xD9,0x84,0x46,0x03,0xE0,0x01,0x99,0x40,0x1C,0x88,0x42,0xF1,0xDB,0x75,0x1E, + 0x0B,0xE0,0xA8,0x00,0x07,0x19,0xF9,0x78,0x20,0x3F,0xFF,0x7F,0xB9,0x42,0x03,0xD3, + 0x91,0x42,0x01,0xD9,0x2B,0x46,0x02,0xE0,0x6D,0x1E,0x00,0x2D,0xF1,0xDC,0xFF,0x20, + 0xF5,0x30,0x00,0x25,0x61,0x46,0x09,0xE0,0x8A,0x00,0x12,0x19,0xD2,0x78,0x82,0x42, + 0x00,0xDA,0x10,0x46,0xAA,0x42,0x00,0xDD,0x15,0x46,0x49,0x1C,0x99,0x42,0xF3,0xDD, + 0x14,0x21,0x14,0x28,0x03,0xDD,0x64,0x21,0x64,0x28,0x00,0xDA,0x01,0x46,0x28,0x1A, + 0x0A,0x22,0x50,0x43,0xFC,0xF7,0x64,0xFA,0x80,0x1C,0x00,0x90,0x0A,0x28,0x1E,0xDA, + 0x81,0x1C,0x01,0x20,0x00,0x27,0x25,0x88,0x00,0x04,0xFC,0xF7,0x59,0xFA,0x03,0x46, + 0x00,0x20,0x12,0xE0,0x01,0x9A,0x39,0x46,0x2F,0x46,0x90,0x42,0x01,0xD1,0x00,0x25, + 0x02,0xE0,0x82,0x00,0x12,0x19,0x95,0x88,0x00,0x9A,0x49,0x19,0x7A,0x43,0x51,0x18, + 0x59,0x43,0x09,0x0C,0x82,0x00,0xA1,0x52,0x40,0x1C,0xB0,0x42,0xEA,0xDB,0xFE,0xBD, + 0x62,0xB6,0x70,0x47,0x01,0x46,0x10,0xB5,0x0A,0x48,0x01,0x29,0x02,0xD1,0x0C,0x22, + 0x09,0xA1,0x08,0xE0,0x02,0x29,0x02,0xD1,0x0C,0x22,0x0B,0xA1,0x03,0xE0,0x03,0x29, + 0x03,0xD1,0x0C,0x22,0x0C,0xA1,0xFC,0xF7,0x3F,0xFA,0x00,0x21,0x04,0x20,0xFE,0xF7, + 0xA7,0xFF,0xFE,0xE7,0x50,0x01,0x00,0x20,0x6D,0x61,0x6C,0x6C,0x6F,0x63,0x20,0x65, + 0x72,0x72,0x0D,0x0A,0x00,0x00,0x00,0x00,0x4F,0x76,0x65,0x72,0x46,0x6C,0x6F,0x77, + 0x21,0x21,0x0D,0x0A,0x00,0x00,0x00,0x00,0x61,0x6C,0x67,0x4E,0x6F,0x4D,0x61,0x74, + 0x63,0x68,0x0D,0x0A,0x00,0x00,0x00,0x00,0xF0,0xB5,0x8F,0xB0,0xF0,0x20,0x6B,0x46, + 0x98,0x70,0x00,0x20,0x18,0x71,0xD9,0x79,0x58,0x71,0x09,0x09,0x09,0x01,0xC9,0xB2, + 0x09,0x07,0x09,0x0F,0xD9,0x71,0x98,0x71,0x1E,0x48,0x05,0x21,0xC0,0x7C,0x18,0x72, + 0x1D,0x48,0xC0,0x78,0xD8,0x70,0x01,0xA8,0x00,0xF0,0xE4,0xFB,0x6B,0x46,0x18,0x80, + 0x18,0x48,0x1A,0x49,0x40,0x38,0x02,0xF0,0x34,0xFD,0x18,0x48,0x00,0x24,0x60,0x30, + 0x0E,0x90,0x1F,0xE0,0x16,0x49,0x15,0x4F,0x0D,0x68,0x66,0x00,0x69,0x7F,0x2A,0x7F, + 0xB8,0x5B,0x09,0x02,0x11,0x43,0x48,0x43,0x0E,0x49,0x40,0x39,0x89,0x88,0xFC,0xF7, + 0xD7,0xF9,0xB8,0x53,0xE9,0x7F,0xF6,0x19,0xAA,0x7F,0xB0,0x8F,0x09,0x02,0x11,0x43, + 0x48,0x43,0x08,0x49,0x40,0x39,0xC9,0x88,0xFC,0xF7,0xCA,0xF9,0xB0,0x87,0x64,0x1C, + 0x0E,0x98,0xE4,0xB2,0x00,0x7E,0xA0,0x42,0xDC,0xD8,0x68,0x46,0x02,0xF0,0x64,0xF9, + 0x0F,0xB0,0xF0,0xBD,0x58,0x06,0x00,0x20,0xB8,0x04,0x00,0x20,0x78,0x1F,0x00,0x20, + 0x10,0x06,0x00,0x20,0xF7,0xB5,0xBC,0xB0,0x15,0x46,0x00,0x29,0x18,0xD0,0x00,0x24, + 0x18,0x20,0x41,0x43,0x0B,0x4E,0x0F,0x46,0x10,0xE0,0x3A,0x46,0x68,0x46,0x3C,0x99, + 0xFC,0xF7,0xBA,0xF9,0x2B,0x46,0x62,0x1C,0x69,0x46,0x70,0x68,0x02,0xF0,0x36,0xFE, + 0xC1,0xB2,0x68,0x46,0x00,0xF0,0x08,0xF8,0x64,0x1C,0xE4,0xB2,0xAC,0x42,0xEC,0xD3, + 0x3F,0xB0,0xF0,0xBD,0x58,0x07,0x00,0x20,0xF3,0xB5,0x95,0xB0,0x00,0x27,0x6B,0x46, + 0x9F,0x82,0xFF,0x20,0x98,0x75,0x61,0x48,0x14,0x90,0x01,0x79,0x3A,0x46,0xFF,0x29, + 0x26,0xD0,0x5F,0x48,0x00,0x6B,0x40,0x5C,0x00,0x09,0x20,0xD0,0x1A,0x76,0x5A,0x76, + 0x9A,0x76,0xDA,0x7E,0x09,0x07,0x12,0x09,0x12,0x01,0xD2,0xB2,0x12,0x07,0x12,0x0F, + 0xDA,0x76,0x1A,0x7F,0x09,0x0F,0x12,0x09,0x12,0x01,0x0A,0x43,0x1A,0x77,0x01,0x28, + 0x01,0xD0,0x02,0x28,0x05,0xD1,0x6B,0x46,0x18,0x7F,0x00,0x07,0x00,0x0F,0x10,0x30, + 0x03,0xE0,0x6B,0x46,0x18,0x7F,0x00,0x07,0x00,0x0F,0x6B,0x46,0x18,0x77,0x01,0x27, + 0x00,0x25,0x2E,0x46,0x7A,0xE0,0x30,0x46,0x18,0x21,0x48,0x43,0x15,0x99,0x6B,0x46, + 0x09,0x5C,0x02,0x91,0x15,0x9A,0x19,0x7C,0x84,0x18,0x09,0x07,0x60,0x78,0x09,0x0F, + 0x80,0x06,0x03,0xD0,0xA0,0x78,0x01,0x28,0x00,0xD0,0x02,0x20,0x00,0x01,0x01,0x43, + 0x6B,0x46,0xC8,0xB2,0x19,0x74,0x02,0x99,0x00,0x09,0x09,0x07,0x00,0x01,0x09,0x0F, + 0x08,0x43,0x18,0x74,0xA2,0x89,0xE0,0x89,0x00,0x90,0x14,0x98,0x00,0x78,0x00,0x28, + 0x02,0xD0,0x22,0x89,0x60,0x89,0x00,0x90,0x36,0x48,0x81,0x88,0x36,0x48,0x00,0x68, + 0x13,0x90,0x43,0x7F,0x00,0x7F,0x1B,0x02,0x03,0x43,0x53,0x43,0x18,0x46,0xFC,0xF7, + 0x27,0xF9,0x80,0xB2,0x01,0x90,0x2F,0x48,0xC1,0x88,0x13,0x98,0xC2,0x7F,0x83,0x7F, + 0x10,0x02,0x00,0x9A,0x18,0x43,0x50,0x43,0xFC,0xF7,0x1A,0xF9,0x82,0xB2,0x02,0x98, + 0x06,0x21,0x48,0x43,0x29,0x49,0xE3,0x78,0x40,0x18,0x41,0x79,0x99,0x42,0x01,0xD2, + 0x49,0x1C,0x02,0xE0,0x99,0x42,0x01,0xD9,0x49,0x1E,0x41,0x71,0x6B,0x46,0x01,0x99, + 0x19,0x73,0xD9,0x7B,0x01,0x9B,0x09,0x09,0x1B,0x05,0x09,0x01,0x1B,0x0F,0x19,0x43, + 0x6B,0x46,0xD9,0x73,0x5A,0x73,0xC9,0xB2,0x12,0x09,0xF0,0x23,0x09,0x07,0x1A,0x40, + 0x09,0x0F,0x11,0x43,0x6B,0x46,0xD9,0x73,0x40,0x79,0x98,0x73,0xB8,0x00,0x38,0x18, + 0x05,0xA9,0x40,0x18,0xA9,0x00,0x69,0x18,0x40,0x18,0x00,0x1D,0x05,0x22,0x03,0xA9, + 0xFC,0xF7,0xFA,0xF8,0x6D,0x1C,0x76,0x1C,0xED,0xB2,0x76,0xB2,0x16,0x98,0x86,0x42, + 0x81,0xDB,0x38,0x01,0x28,0x43,0x6B,0x46,0xD8,0x75,0x16,0x98,0xC0,0x19,0x81,0x00, + 0x41,0x18,0x06,0xA8,0x00,0xF0,0xC6,0xFA,0x6B,0x46,0x98,0x82,0xE8,0x19,0x02,0xD0, + 0x05,0xA8,0x02,0xF0,0x71,0xF8,0x17,0xB0,0xF0,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20, + 0x44,0x04,0x00,0x20,0x18,0x06,0x00,0x20,0x10,0x06,0x00,0x20,0xF2,0x1F,0x00,0x20, + 0xF3,0xB5,0x00,0x24,0x0F,0x46,0x83,0xB0,0x0E,0x46,0x20,0x37,0x34,0xE0,0x54,0x20, + 0x03,0x99,0x60,0x43,0x45,0x18,0x28,0x7C,0x01,0x07,0x2B,0xD0,0x39,0x79,0x00,0x09, + 0x88,0x42,0x27,0xD8,0x56,0x20,0x82,0x5D,0xF9,0x7A,0x28,0x46,0xFC,0xF7,0xBA,0xFE, + 0x28,0x7C,0x00,0x07,0x00,0x0F,0x02,0x28,0x02,0xD2,0x68,0x6B,0x00,0x90,0x14,0xE0, + 0x31,0x46,0x28,0x46,0xFC,0xF7,0x84,0xFD,0x01,0x46,0x01,0x90,0x33,0x46,0x00,0x22, + 0x28,0x46,0xFC,0xF7,0x27,0xFE,0x69,0x46,0x08,0x80,0x33,0x46,0x01,0x22,0x28,0x46, + 0x01,0x99,0xFC,0xF7,0x1F,0xFE,0x69,0x46,0x48,0x80,0x6A,0x46,0x31,0x46,0x28,0x46, + 0x02,0xF0,0x34,0xFE,0x64,0x1C,0xE4,0xB2,0xB0,0x78,0xA0,0x42,0xC7,0xD8,0x00,0x20, + 0x05,0xB0,0xF0,0xBD,0xFF,0x30,0x41,0x30,0x40,0x68,0x02,0x49,0xC1,0x60,0x00,0x20, + 0x70,0x47,0x00,0x00,0x31,0x3F,0x00,0x00,0xFF,0xB5,0x06,0x46,0x08,0x46,0x83,0xB0, + 0x0D,0x46,0x24,0x30,0x01,0x90,0x18,0x30,0x18,0x31,0x02,0x90,0x30,0x38,0x00,0x91, + 0x2F,0x46,0x01,0x21,0x54,0x37,0x81,0x55,0x00,0x24,0x17,0xE0,0x00,0x98,0x00,0x5D, + 0x00,0x28,0x12,0xD1,0x01,0x98,0x71,0x00,0x42,0x5E,0x02,0x98,0x61,0x00,0x40,0x5E, + 0x12,0x18,0x06,0x98,0x70,0x43,0x00,0x19,0x43,0x00,0x05,0x98,0xC0,0x5A,0x10,0x1A, + 0x0A,0xD0,0x7A,0x5E,0x82,0x42,0x00,0xDD,0x78,0x52,0x64,0x1C,0x06,0x98,0x84,0x42, + 0xE4,0xD3,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x00,0x99,0x01,0x20,0x08,0x55,0x28,0x57, + 0x41,0x1C,0x06,0xD0,0x29,0x46,0x06,0x9B,0x05,0x9A,0xFF,0xF7,0xC5,0xFF,0x00,0x28, + 0xEB,0xD0,0x2E,0x55,0x01,0x20,0xED,0xE7,0xF8,0xB5,0x79,0x48,0x2B,0x27,0x07,0x70, + 0x00,0x26,0x78,0x4C,0x46,0x70,0x20,0x68,0xFF,0x30,0x41,0x30,0x40,0x7C,0x01,0xF0, + 0xF7,0xFF,0x00,0x20,0xFF,0xF7,0x2A,0xF9,0x73,0x48,0x21,0x68,0x05,0x6D,0xFF,0x31, + 0x9C,0x22,0xA1,0x31,0x71,0x48,0xFC,0xF7,0x2F,0xF8,0x5C,0x22,0x6F,0x49,0x70,0x48, + 0xFC,0xF7,0x2A,0xF8,0x6E,0x48,0x6F,0x49,0x86,0x72,0x06,0x77,0x30,0x20,0x48,0x70, + 0x08,0x46,0x20,0x30,0x00,0x90,0xA8,0xE0,0x65,0x48,0x00,0x78,0x01,0x46,0x20,0x38, + 0x10,0x28,0x55,0xD8,0x62,0x4C,0x2B,0x29,0x01,0xD0,0xF0,0x21,0x61,0x70,0x03,0x46, + 0xFC,0xF7,0xAA,0xF8,0x0B,0x07,0x0B,0x12,0x17,0x3D,0x40,0x4E,0x45,0x60,0x6C,0x75, + 0x4E,0x00,0x5F,0x49,0x07,0x20,0x88,0x73,0x01,0xE0,0x5D,0x48,0x86,0x73,0xE0,0x78, + 0x29,0x46,0x00,0xF0,0xFB,0xF9,0x2D,0xE0,0x00,0x21,0x0A,0x20,0xFD,0xF7,0xF2,0xFF, + 0x4F,0xE0,0x53,0x48,0xC0,0x78,0x00,0x28,0x0C,0xD1,0x53,0x4C,0x2B,0x46,0x22,0x78, + 0xE1,0x69,0xE0,0x68,0xFD,0xF7,0x18,0xFF,0x20,0x78,0x62,0x78,0x40,0x00,0x43,0x19, + 0xA1,0x69,0x0B,0xE0,0x50,0x4C,0x2B,0x46,0x22,0x78,0xA1,0x69,0xE0,0x68,0xFD,0xF7, + 0x0B,0xFF,0x20,0x78,0x62,0x78,0x40,0x00,0x61,0x69,0x43,0x19,0x20,0x69,0xFD,0xF7, + 0x03,0xFF,0x43,0x49,0x01,0x20,0x88,0x70,0xFC,0x20,0x48,0x70,0x44,0xE0,0x02,0x20, + 0xA0,0x70,0x11,0xE0,0x01,0x20,0xA0,0x70,0xFC,0x20,0x60,0x70,0x3C,0xE0,0x02,0x20, + 0xA0,0x70,0x66,0x70,0x00,0x22,0x27,0x70,0x21,0x21,0x10,0x46,0x02,0xF0,0xE6,0xFD, + 0x37,0x48,0x81,0x78,0x02,0x29,0x2C,0xD1,0x35,0x4C,0x60,0x78,0xFC,0x28,0x40,0xD1, + 0x01,0x20,0xFF,0xF7,0xAB,0xF8,0x05,0x20,0xFE,0xF7,0xF4,0xFC,0x00,0x20,0xFF,0xF7, + 0xA5,0xF8,0x08,0xE0,0x2F,0x48,0x00,0x68,0xFF,0x30,0x61,0x30,0x00,0x7D,0x01,0x21, + 0x0A,0xE0,0x02,0x20,0xA0,0x70,0x27,0x70,0x66,0x70,0x2A,0xE0,0x29,0x48,0x00,0x21, + 0x00,0x68,0xFF,0x30,0x61,0x30,0x00,0x7D,0xFF,0xF7,0x7E,0xF8,0xF1,0xE7,0x78,0x20, + 0xFE,0xF7,0xD8,0xFC,0xFE,0xF7,0x96,0xF8,0x00,0x21,0x01,0x20,0xFE,0xF7,0x00,0xFD, + 0xFA,0xE7,0x40,0x78,0xFC,0x28,0x14,0xD1,0x00,0x98,0x86,0x70,0x01,0x20,0xFF,0xF7, + 0x7D,0xF8,0x1C,0x48,0x00,0x68,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A,0x08,0x02, + 0x10,0x43,0x02,0xF0,0x81,0xFD,0x00,0x20,0xFF,0xF7,0x70,0xF8,0x14,0x48,0x07,0x70, + 0x46,0x70,0x00,0x21,0x01,0x20,0xFE,0xF7,0xE3,0xFC,0x16,0x48,0x00,0x78,0x11,0x28, + 0x00,0xD1,0x51,0xE7,0x0F,0x48,0x9C,0x22,0x01,0x68,0x10,0x48,0x0C,0x46,0xFF,0x31, + 0xA1,0x31,0xFB,0xF7,0x69,0xFF,0x5C,0x22,0x0C,0x49,0x0D,0x48,0xFB,0xF7,0x64,0xFF, + 0x0C,0x48,0x31,0x0A,0x86,0x72,0xC1,0x72,0x00,0x9A,0x01,0x21,0x91,0x71,0x06,0x72, + 0x31,0x0A,0x41,0x72,0xFF,0x21,0x51,0x31,0x08,0x5D,0x01,0xF0,0x11,0xFF,0xF8,0xBD, + 0xC8,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0xAC,0x03,0x00,0x20,0x32,0x05,0x00,0x20, + 0xD6,0x04,0x00,0x20,0x98,0x04,0x00,0x20,0x44,0x04,0x00,0x20,0x01,0x49,0x01,0x20, + 0xC8,0x82,0x70,0x47,0x00,0x20,0x00,0x40,0xFF,0xB5,0x81,0xB0,0x00,0x24,0x33,0xE0, + 0x20,0x46,0x48,0x43,0x01,0x9A,0x40,0x00,0x83,0x18,0x04,0x9A,0x9C,0x46,0x85,0x18, + 0x02,0x20,0x00,0x22,0x18,0x5E,0x9A,0x5E,0x43,0x00,0x93,0x42,0x02,0xDA,0x53,0x00, + 0xD3,0x18,0x00,0xE0,0x53,0x00,0x1B,0x18,0x2B,0x80,0x01,0x23,0x4E,0x1E,0x00,0x96, + 0x0D,0xE0,0x46,0x00,0xB6,0x18,0x02,0x46,0x58,0x00,0x67,0x46,0x86,0x46,0xC7,0x19, + 0x02,0x20,0x38,0x5E,0x37,0x18,0x76,0x46,0xAF,0x53,0x00,0x9E,0x5B,0x1C,0xB3,0x42, + 0xEF,0xDB,0x56,0x00,0x86,0x42,0x02,0xDA,0x46,0x00,0x80,0x19,0x00,0xE0,0x40,0x00, + 0x80,0x18,0x5A,0x00,0xA8,0x52,0x64,0x1C,0x03,0x98,0x84,0x42,0xC8,0xDB,0x00,0x25, + 0x30,0xE0,0x04,0x98,0x6A,0x00,0x14,0x18,0x48,0x00,0x00,0x22,0x20,0x5E,0xA2,0x5E, + 0x43,0x00,0x93,0x42,0x02,0xDA,0x53,0x00,0xD3,0x18,0x00,0xE0,0x53,0x00,0x1B,0x18, + 0x1B,0x11,0x23,0x80,0x03,0x9E,0x0B,0x46,0x76,0x1E,0x4E,0x43,0xB4,0x46,0x0B,0xE0, + 0x46,0x00,0xB2,0x18,0x17,0xB2,0x02,0x46,0x5E,0x18,0x70,0x00,0x20,0x5E,0x3F,0x18, + 0x3F,0x11,0x5B,0x00,0xE7,0x52,0x33,0x46,0x9C,0x45,0xF1,0xDC,0x56,0x00,0x86,0x42, + 0x02,0xDA,0x46,0x00,0x80,0x19,0x00,0xE0,0x40,0x00,0x80,0x18,0x00,0x11,0x5A,0x00, + 0xA0,0x52,0x6D,0x1C,0x8D,0x42,0xCC,0xDB,0x05,0xB0,0xF0,0xBD,0xF0,0xB5,0x03,0x46, + 0xC0,0x30,0x84,0x68,0x40,0x69,0x85,0xB0,0x01,0x27,0x05,0x46,0xFF,0x43,0x40,0x35, + 0x03,0x90,0xEF,0x74,0x03,0x98,0x80,0x68,0x00,0x07,0x02,0xD4,0x38,0x46,0x05,0xB0, + 0xF0,0xBD,0xA8,0x7D,0x02,0x90,0x00,0x20,0x01,0x90,0x00,0x90,0x6A,0x46,0x01,0xA9, + 0x18,0x46,0xFD,0xF7,0x73,0xFA,0x06,0x46,0x01,0x28,0x03,0xDD,0xFF,0x20,0xE8,0x74, + 0xE0,0x70,0x01,0x26,0x31,0x46,0x20,0x46,0x02,0x9A,0x00,0xF0,0x63,0xF8,0x60,0x78, + 0x01,0x28,0x02,0xD0,0x02,0x28,0x11,0xD0,0x25,0xE0,0x01,0x2E,0x0C,0xD1,0x20,0x46, + 0x00,0x9A,0x01,0x99,0x02,0xF0,0x3F,0xFC,0xE2,0x88,0x02,0x99,0x14,0x48,0x51,0x18, + 0x81,0x42,0x00,0xDC,0x08,0x46,0xE0,0x80,0xEF,0x74,0x14,0xE0,0xE0,0x78,0xFF,0x28, + 0x18,0xD0,0x20,0x46,0x03,0x99,0x00,0xF0,0xCF,0xFB,0xE1,0x68,0x07,0x46,0x00,0x29, + 0x07,0xD0,0x00,0x2F,0x05,0xDA,0x20,0x78,0x04,0x28,0x02,0xD3,0x20,0x46,0x88,0x47, + 0x07,0x46,0x00,0x20,0x60,0x70,0x3A,0x46,0x20,0x46,0x03,0x99,0xFD,0xF7,0xF5,0xF9, + 0xE8,0x74,0xB4,0xE7,0x00,0x27,0xFF,0x43,0x00,0x20,0xE0,0x70,0xF1,0xE7,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0x70,0xB5,0x0D,0x46,0x81,0x68,0x16,0x46,0x09,0x07,0x01,0xD4, + 0x00,0x20,0x70,0xBD,0xFF,0x22,0x53,0x21,0x0A,0x54,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x08,0x48,0x20,0x61,0x01,0xF0,0x42,0xF8,0xC0,0x34,0xA0,0x60,0xC8,0x20,0x01,0xF0, + 0x5B,0xF8,0xA4,0x68,0xC8,0x21,0x20,0x46,0xFB,0xF7,0x75,0xFE,0x26,0x61,0xC8,0x20, + 0xE5,0x60,0x70,0xBD,0x3D,0x43,0x00,0x00,0x10,0xB5,0x00,0x22,0x11,0x46,0xFF,0xF7, + 0xD9,0xFF,0x10,0xBD,0x10,0xB5,0x00,0x29,0x06,0xD1,0x84,0x88,0x0C,0x4B,0xA2,0x18, + 0x9A,0x42,0x00,0xDA,0x13,0x46,0x83,0x80,0x42,0x78,0x00,0x2A,0x07,0xD0,0x01,0x2A, + 0x04,0xD1,0x81,0x88,0x05,0x29,0x01,0xD3,0x02,0x21,0x41,0x70,0x10,0xBD,0x01,0x29, + 0xFC,0xD1,0x41,0x70,0x00,0x21,0x01,0x70,0xC1,0x80,0x81,0x80,0x10,0xBD,0x00,0x00, + 0xFF,0xFF,0x00,0x00,0x03,0x46,0x10,0xB5,0x55,0x20,0x00,0x22,0x03,0xE0,0x9C,0x5C, + 0x20,0x18,0x80,0xB2,0x52,0x1C,0x8A,0x42,0xF9,0xDB,0x10,0xBD,0x06,0x48,0x80,0x69, + 0x01,0x79,0x04,0x29,0x03,0xD0,0x03,0x29,0x03,0xD0,0x1B,0x30,0x70,0x47,0x80,0x1D, + 0x70,0x47,0x12,0x30,0x70,0x47,0x00,0x00,0x78,0x21,0x00,0x20,0xF0,0xB5,0x05,0x46, + 0x85,0xB0,0x0C,0x46,0x01,0x20,0xFE,0xF7,0x33,0xFA,0x1C,0x48,0x1C,0x4B,0x1D,0x4E, + 0x1D,0x4F,0x00,0x2D,0x0A,0xD1,0x41,0x6C,0xF0,0x6A,0x01,0x22,0x02,0x92,0x01,0x91, + 0x00,0x90,0x1A,0x46,0x08,0x3A,0x19,0x46,0x30,0x46,0x09,0xE0,0x81,0x6C,0xF8,0x69, + 0x01,0x22,0x02,0x92,0x00,0x90,0x12,0x4A,0x01,0x91,0x13,0x48,0x08,0x3A,0x19,0x46, + 0x23,0x46,0xFE,0xF7,0xE5,0xF8,0x0E,0x48,0x08,0x22,0x08,0x38,0x81,0x78,0x00,0x7A, + 0x00,0x23,0xFE,0xF7,0x35,0xF8,0x03,0x90,0x01,0x20,0xFE,0xF7,0xCD,0xF9,0x00,0x2D, + 0x04,0xD1,0x32,0x78,0x70,0x78,0xF3,0x6A,0x42,0x43,0x01,0xE0,0x3A,0x78,0xFB,0x69, + 0x20,0x46,0x03,0x99,0x01,0xF0,0x16,0xFE,0x05,0xB0,0xF0,0xBD,0x60,0x03,0x00,0x20, + 0xDE,0x04,0x00,0x20,0xAC,0x03,0x00,0x20,0x44,0x04,0x00,0x20,0x04,0x48,0x01,0x7A, + 0xC2,0x79,0x88,0x1A,0x91,0x42,0x00,0xD2,0x08,0x30,0xC0,0xB2,0x70,0x47,0x00,0x00, + 0xB8,0x04,0x00,0x20,0x10,0xB5,0x04,0x48,0x00,0x69,0x80,0x47,0x02,0x49,0x01,0x20, + 0x08,0x39,0x08,0x71,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0x03,0x49,0x02,0x48, + 0xC8,0x60,0xBF,0xF3,0x40,0x8F,0xFE,0xE7,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0, + 0xF7,0xB5,0x8C,0xB0,0xC8,0x69,0x08,0x90,0x08,0x6A,0x09,0x90,0x48,0x6A,0x06,0x90, + 0x0C,0x98,0x15,0x24,0x04,0x57,0x14,0x25,0x45,0x57,0x22,0x46,0x06,0x98,0x6A,0x43, + 0x13,0x18,0x00,0x20,0x03,0x90,0x02,0x46,0x04,0x90,0xC8,0x6A,0x01,0x26,0x86,0x57, + 0x07,0x96,0x02,0x26,0x86,0x57,0x0A,0x96,0x03,0x26,0x86,0x57,0xB0,0x10,0x6E,0x46, + 0x31,0xC6,0x00,0x20,0x6C,0xE0,0x0E,0x98,0x00,0x28,0x00,0xD0,0x01,0x20,0x86,0x46, + 0x60,0xE0,0x00,0x20,0x0B,0x90,0xC5,0x07,0x05,0x9C,0xED,0x0F,0x2C,0x19,0x02,0x25, + 0x05,0x40,0x75,0x44,0xAC,0x46,0x01,0x9D,0xAC,0x42,0x34,0xD2,0x02,0x9D,0xAC,0x45, + 0x31,0xD2,0x65,0x43,0x06,0x9E,0x65,0x44,0x76,0x57,0x32,0x36,0x65,0x2E,0x30,0xD2, + 0x08,0x9E,0x6D,0x00,0x77,0x5F,0x09,0x9E,0x75,0x5F,0x07,0x9E,0x7D,0x1B,0xB5,0x42, + 0x02,0xDC,0x0A,0x9E,0xB5,0x42,0x00,0xDA,0x52,0x1C,0x0E,0x9E,0x00,0x2E,0x1A,0xD1, + 0x40,0x26,0x77,0x5E,0x00,0x2F,0x16,0xDD,0x07,0x9E,0xB5,0x42,0x13,0xDD,0x0C,0x9D, + 0x64,0x00,0x6D,0x68,0x4E,0x6B,0x2D,0x5F,0x34,0x5F,0x2C,0x1B,0x0A,0x2C,0x0A,0xDD, + 0x0C,0x9C,0xCE,0x6C,0xA5,0x68,0x64,0x46,0x64,0x00,0x2D,0x5F,0x34,0x5F,0x2C,0x1B, + 0x0A,0x2C,0x00,0xDD,0x52,0x1E,0x40,0x1C,0x04,0x28,0xBC,0xDB,0x0B,0x98,0x00,0x28, + 0x02,0xD0,0x00,0x20,0x18,0x70,0x11,0xE0,0x00,0x20,0x18,0x56,0x7F,0x24,0x45,0x1C, + 0x7F,0x2D,0x00,0xDA,0x2C,0x46,0x60,0xB2,0x18,0x70,0x03,0x9C,0x64,0x1C,0x03,0x94, + 0x00,0x9C,0xA0,0x42,0x02,0xDB,0x04,0x98,0x40,0x1C,0x04,0x90,0x70,0x46,0x80,0x1C, + 0x86,0x46,0x5B,0x1C,0x04,0x46,0x02,0x98,0x84,0x42,0x9A,0xDB,0x05,0x98,0x80,0x1C, + 0x01,0x9C,0x05,0x90,0xA0,0x42,0x8E,0xDB,0x04,0x9B,0x03,0x99,0x00,0x20,0x99,0x42, + 0x04,0xD1,0x00,0x29,0x02,0xDD,0x02,0x2A,0x00,0xDD,0x01,0x20,0x0F,0xB0,0xF0,0xBD, + 0xF3,0xB5,0x81,0xB0,0x05,0x46,0x00,0x24,0x18,0x20,0x60,0x43,0x42,0x19,0x18,0x32, + 0x50,0x68,0x00,0x28,0x2A,0xD0,0x02,0x98,0x00,0x28,0x04,0xD0,0x10,0x21,0x51,0x5E, + 0x00,0x2C,0x1D,0xD0,0x1F,0xE0,0x00,0x21,0xD6,0x68,0x14,0xE0,0x13,0x68,0x48,0x00, + 0x97,0x68,0x1B,0x5E,0x38,0x5E,0x1B,0x1A,0x70,0x56,0xC7,0x00,0x38,0x1A,0xC0,0x10, + 0xC0,0x18,0x7F,0x23,0xDB,0x43,0x98,0x42,0x03,0xDD,0x7F,0x23,0x7F,0x28,0x00,0xDA, + 0x03,0x46,0x73,0x54,0x49,0x1C,0x10,0x20,0x10,0x5E,0x88,0x42,0xE6,0xDC,0x05,0xE0, + 0x00,0x20,0x28,0x5E,0x41,0x18,0xD0,0x68,0xFB,0xF7,0xED,0xFC,0x64,0x1C,0x05,0x2C, + 0xCA,0xDB,0xFE,0xBD,0xF8,0xB5,0x66,0x4D,0xE8,0x79,0x66,0x4E,0xC1,0x07,0x34,0x46, + 0x20,0x34,0xE0,0x7A,0x00,0x27,0x00,0x29,0x43,0xD0,0x29,0x46,0x4D,0x88,0xC9,0x79, + 0x09,0x06,0x1E,0xD5,0x5E,0x49,0x10,0x22,0xCA,0x71,0x31,0x1F,0x0F,0x80,0x00,0x28, + 0x1C,0xD0,0x70,0x69,0x80,0x47,0x28,0x0A,0x00,0x90,0xB1,0x69,0x88,0x47,0xE0,0x7A, + 0x00,0x28,0x09,0xD0,0x00,0x98,0xFE,0xF7,0x9F,0xF9,0x00,0x28,0x04,0xD0,0x01,0x20, + 0xA0,0x72,0xE7,0x72,0xF1,0x6A,0x08,0x70,0xB1,0x69,0xE8,0xB2,0x88,0x47,0x35,0x85, + 0x04,0xE0,0x50,0x49,0x09,0x1F,0x08,0x88,0x40,0x1C,0x08,0x80,0x4E,0x49,0xA0,0x20, + 0x88,0x80,0x4C,0x48,0xFF,0x22,0x00,0x1F,0x01,0x88,0xF5,0x32,0x91,0x42,0x0F,0xD9, + 0x47,0x49,0x10,0x22,0xCA,0x71,0x07,0x80,0xE0,0x7A,0x00,0x28,0x08,0xD0,0x70,0x69, + 0x80,0x47,0xB1,0x69,0x28,0x0A,0x88,0x47,0xB1,0x69,0xE8,0xB2,0x88,0x47,0x35,0x85, + 0xF8,0xBD,0xA9,0x79,0xCF,0x22,0x11,0x40,0x01,0x29,0x33,0xD0,0x05,0x29,0x1F,0xD0, + 0x09,0x29,0x72,0xD1,0xA7,0x71,0xE7,0x71,0x29,0x78,0x09,0x06,0x08,0xD4,0x00,0x28, + 0x06,0xD0,0x68,0x88,0x31,0x69,0xC0,0x05,0x00,0x0E,0x88,0x47,0x00,0x28,0x64,0xD0, + 0x68,0x88,0xC0,0x07,0x0C,0xD1,0x37,0x84,0xE0,0x7A,0x00,0x28,0x01,0xD0,0x70,0x69, + 0x80,0x47,0xA0,0x7A,0x00,0x28,0x01,0xD0,0x70,0x68,0x80,0x47,0x10,0x20,0x0D,0xE0, + 0xE0,0x7A,0x00,0x28,0x0C,0xD0,0x30,0x8D,0xC0,0xB2,0x55,0x28,0x02,0xD1,0xE0,0x79, + 0x40,0x1C,0xE0,0x71,0xF0,0x69,0x80,0x47,0x68,0x80,0x14,0x20,0xA8,0x71,0xF8,0xBD, + 0xF0,0x68,0xF8,0xE7,0x22,0x49,0x49,0x88,0xA2,0x79,0xCD,0xB2,0x21,0x49,0x02,0x2A, + 0x89,0x68,0x30,0xD2,0x33,0x8C,0x1B,0x02,0x2B,0x43,0x33,0x84,0x00,0x28,0x1E,0xD0, + 0x00,0x2A,0x15,0xD1,0x28,0x46,0xFE,0xF7,0x27,0xF9,0x00,0x28,0x04,0xD0,0x01,0x20, + 0xA0,0x72,0xE7,0x72,0xF1,0x6A,0x08,0x70,0x60,0x7C,0xA8,0x42,0x02,0xD1,0xE7,0x71, + 0x37,0x85,0x05,0xE0,0x30,0x8D,0x00,0x02,0x30,0x85,0x30,0x8D,0x28,0x43,0x30,0x85, + 0xA0,0x79,0x01,0x28,0x01,0xD1,0xFE,0xF7,0x47,0xF9,0xB1,0x69,0x05,0xE0,0x01,0x2A, + 0x05,0xD1,0x30,0x8C,0x00,0x0A,0x88,0x47,0xB1,0x68,0x28,0x46,0x88,0x47,0xA0,0x79, + 0x40,0x1C,0xA0,0x71,0x04,0xE0,0x00,0x28,0x00,0xD0,0xB1,0x69,0x28,0x46,0x88,0x47, + 0x03,0x49,0x10,0x20,0x88,0x71,0xF8,0xBD,0xFF,0xE7,0xAF,0x71,0xFB,0xE7,0x00,0x00, + 0x00,0x20,0x00,0x40,0xC8,0x20,0x00,0x20,0x00,0x02,0x00,0x40,0x10,0xB5,0x04,0x48, + 0x40,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x48,0x70,0x10,0xBD,0x00,0x00, + 0x50,0x20,0x00,0x20,0xF0,0xB5,0x18,0x48,0x89,0xB0,0x04,0x68,0x6B,0x46,0xFF,0x34, + 0x41,0x34,0x60,0x7F,0xE2,0x7F,0x61,0x7E,0x07,0xC3,0xA3,0x7E,0xE2,0x7E,0x21,0x7F, + 0x20,0x7E,0xFD,0xF7,0x0D,0xFD,0x11,0x48,0x11,0x4A,0x01,0x68,0x8E,0x46,0x41,0x68, + 0x8C,0x46,0x81,0x68,0x08,0x91,0xC3,0x68,0x10,0x30,0xF0,0xC8,0x30,0x20,0x05,0x90, + 0x00,0x21,0x09,0x48,0x07,0x92,0x06,0x91,0x00,0x68,0x41,0x7E,0x00,0x7E,0x0A,0x02, + 0x02,0x43,0x68,0x46,0xF0,0xC0,0x04,0x92,0x61,0x46,0x70,0x46,0x08,0x9A,0xFD,0xF7, + 0x5B,0xFD,0x09,0xB0,0xF0,0xBD,0x00,0x00,0x10,0x06,0x00,0x20,0x98,0x6D,0x00,0x00, + 0xC3,0x04,0x00,0x20,0x0A,0x49,0x0B,0x48,0x0A,0x6D,0x02,0x60,0x4A,0x6D,0x42,0x60, + 0x8A,0x6D,0x82,0x60,0x08,0x4A,0xC2,0x60,0x00,0x22,0x02,0x74,0x42,0x74,0x07,0x48, + 0x00,0x68,0x20,0x30,0x02,0x7C,0x4A,0x75,0x40,0x7C,0x08,0x75,0x70,0x47,0x00,0x00, + 0xAC,0x03,0x00,0x20,0x34,0x20,0x00,0x20,0x7A,0x01,0x00,0x20,0x10,0x06,0x00,0x20, + 0x70,0xB5,0x00,0x24,0x18,0x4D,0x19,0x4E,0x08,0xE0,0x00,0x19,0x20,0x30,0x00,0x7D, + 0xFD,0xF7,0x0A,0xFA,0xA9,0x69,0x08,0x55,0x64,0x1C,0xE4,0xB2,0x30,0x68,0x30,0x21, + 0x09,0x5C,0xA1,0x42,0xF1,0xD8,0x00,0x24,0x08,0xE0,0x00,0x19,0x60,0x30,0x00,0x7A, + 0xFD,0xF7,0xFA,0xF9,0xE9,0x69,0x08,0x55,0x64,0x1C,0xE4,0xB2,0x30,0x68,0x31,0x21, + 0x09,0x5C,0xA1,0x42,0xF1,0xD8,0x01,0x46,0x20,0x31,0x4A,0x7C,0x2A,0x70,0x09,0x7C, + 0x69,0x70,0xE9,0x69,0x69,0x60,0xA9,0x69,0xA9,0x60,0x01,0x46,0x68,0x31,0x34,0x30, + 0xE9,0x60,0x28,0x61,0x70,0xBD,0x00,0x00,0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20, + 0x70,0xB5,0x15,0x4C,0x10,0x20,0x20,0x70,0x20,0x20,0x60,0x70,0x00,0x21,0x07,0x20, + 0xFE,0xF7,0xB6,0xF8,0xA0,0x70,0xFF,0x22,0x10,0x48,0x62,0x77,0x01,0x68,0x0D,0x46, + 0xFF,0x31,0x41,0x31,0x08,0x7C,0x20,0x77,0x0D,0x48,0x81,0x78,0x20,0x46,0x20,0x30, + 0x41,0x71,0x01,0x21,0x81,0x71,0x81,0x70,0x02,0x71,0x00,0x21,0x81,0x73,0xC1,0x20, + 0x08,0x49,0x80,0x04,0xFB,0xF7,0x6C,0xFB,0x29,0x46,0x40,0x22,0xA8,0x31,0x06,0x48, + 0xFB,0xF7,0x2A,0xFB,0x70,0xBD,0x00,0x00,0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0xD6,0x04,0x00,0x20,0x4A,0x01,0x00,0x20,0xCE,0x05,0x00,0x20,0x7C,0xB5,0x29,0x4D, + 0x20,0x20,0x68,0x70,0x29,0x4C,0x28,0x48,0x20,0x60,0x9C,0x22,0x28,0x49,0x29,0x48, + 0xFB,0xF7,0x12,0xFB,0x5C,0x22,0x27,0x49,0x27,0x48,0xFB,0xF7,0x0D,0xFB,0x22,0x48, + 0x10,0x30,0xFB,0xF7,0x3C,0xFB,0xC0,0x07,0xC0,0x0F,0xFE,0xF7,0x87,0xFC,0x20,0x68, + 0x01,0x22,0xFF,0x30,0x61,0x30,0x41,0x7D,0x00,0x7D,0xFD,0xF7,0xF5,0xFC,0xFF,0xF7, + 0x19,0xFF,0xFB,0xF7,0xC1,0xFD,0xFF,0xF7,0xA3,0xFF,0xFF,0xF7,0x69,0xFF,0x01,0xF0, + 0x19,0xF9,0x01,0xF0,0x4F,0xF8,0x20,0x68,0xFF,0x30,0x51,0x30,0x41,0x79,0x00,0x79, + 0x09,0x02,0x01,0x43,0x00,0x20,0xFE,0xF7,0x53,0xF8,0x14,0x48,0x12,0x49,0x02,0x6A, + 0x34,0x31,0x01,0x92,0x00,0x91,0x10,0x4A,0x2C,0x39,0x11,0x48,0x0F,0x4B,0xFE,0xF7, + 0x61,0xF9,0x20,0x68,0xFF,0x30,0x81,0x30,0xC0,0x7E,0x00,0x28,0x28,0x7F,0x01,0xD0, + 0x0C,0x49,0x00,0xE0,0x00,0x21,0xFE,0xF7,0x19,0xFC,0xFF,0xF7,0x23,0xFF,0xFB,0xF7, + 0x11,0xFC,0x7C,0xBD,0x98,0x04,0x00,0x20,0x00,0x8C,0x00,0x00,0x10,0x06,0x00,0x20, + 0xA0,0x8D,0x00,0x00,0x32,0x05,0x00,0x20,0xD6,0x04,0x00,0x20,0xAC,0x03,0x00,0x20, + 0x60,0x03,0x00,0x20,0x19,0x61,0x00,0x00,0x70,0xB5,0x09,0x24,0xA4,0x03,0x01,0x21, + 0x05,0x78,0x11,0xE0,0x06,0x22,0x4A,0x43,0x12,0x18,0x83,0x8A,0x96,0x8A,0xD2,0x8A, + 0x9B,0x1B,0xC6,0x8A,0x5B,0x43,0xB2,0x1A,0x52,0x43,0x9A,0x18,0xA2,0x42,0x02,0xDD, + 0x00,0x20,0xC0,0x43,0x70,0xBD,0x49,0x1C,0x8D,0x42,0xEB,0xDC,0x00,0x20,0x70,0xBD, + 0xFF,0xB5,0x83,0xB0,0x6A,0x46,0x10,0x21,0x0C,0x20,0x51,0x5E,0x10,0x5E,0x8E,0x46, + 0x88,0x42,0x02,0xDA,0x02,0x46,0x0B,0x46,0x01,0xE0,0x0A,0x46,0x03,0x46,0x6D,0x46, + 0x18,0x24,0x14,0x21,0x2C,0x5F,0x69,0x5E,0xA4,0x46,0xA1,0x42,0x02,0xDA,0x0C,0x46, + 0x65,0x46,0x00,0xE0,0x0D,0x46,0xA3,0x42,0x46,0xDB,0x95,0x42,0x44,0xDB,0x6C,0x46, + 0x0E,0x22,0x12,0x23,0xA2,0x5E,0xE3,0x5E,0x00,0x93,0x9A,0x42,0x02,0xDA,0x17,0x46, + 0x1E,0x46,0x01,0xE0,0x1F,0x46,0x16,0x46,0x16,0x23,0x25,0x46,0xE3,0x5E,0x1A,0x24, + 0x2C,0x5F,0x01,0x94,0xA3,0x42,0x02,0xDA,0x1C,0x46,0x01,0x9D,0x00,0xE0,0x1D,0x46, + 0xA6,0x42,0x29,0xDB,0xBD,0x42,0x27,0xDB,0x01,0x9C,0xD6,0x1A,0xE7,0x1A,0x64,0x46, + 0x64,0x1A,0x45,0x1A,0x66,0x43,0x7D,0x43,0x02,0x94,0xAD,0x1B,0x74,0x46,0x66,0x1A, + 0x00,0x9C,0x7E,0x43,0xE7,0x1A,0x02,0x9C,0x67,0x43,0xF4,0x1B,0x65,0x40,0x00,0x2D, + 0x12,0xDC,0x0C,0x1A,0x00,0x99,0x9D,0x1A,0x73,0x46,0x89,0x1A,0x1B,0x1A,0x4C,0x43, + 0x5D,0x43,0x64,0x1B,0x65,0x46,0x28,0x1A,0x48,0x43,0x01,0x99,0x89,0x1A,0x59,0x43, + 0x40,0x1A,0x44,0x40,0x00,0x2C,0x02,0xDD,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x01,0x20, + 0xFB,0xE7,0x00,0x00,0xF0,0xB5,0x14,0x4A,0x14,0x4F,0x12,0x68,0x11,0x4D,0x13,0x46, + 0x20,0x33,0x1C,0x7C,0x5E,0x7C,0x23,0x46,0x7F,0x78,0xA0,0x32,0xA9,0x6A,0x28,0x6A, + 0x73,0x43,0x14,0x7D,0xFF,0x43,0xBF,0x07,0x03,0xD1,0xD4,0x7D,0xA9,0x6C,0x28,0x6C, + 0x33,0x46,0x00,0x22,0x0A,0xE0,0x0D,0x88,0x06,0x88,0xAD,0x1B,0xA5,0x42,0x01,0xDD, + 0x01,0x20,0xF0,0xBD,0x89,0x1C,0x80,0x1C,0x52,0x1C,0x92,0xB2,0x9A,0x42,0xF2,0xD3, + 0x00,0x20,0xF0,0xBD,0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20,0xF6,0x04,0x00,0x20, + 0xF0,0xB5,0x6F,0x48,0x8F,0xB0,0x00,0x6D,0x08,0x90,0x6E,0x48,0x00,0x68,0x20,0x30, + 0x41,0x7C,0x07,0x91,0x00,0x7C,0x06,0x90,0x00,0x20,0x05,0x90,0x04,0x90,0x06,0x46, + 0x03,0x90,0x69,0x48,0x0D,0x90,0xC0,0x7B,0x0E,0x90,0xA8,0xE0,0x00,0x25,0xA0,0xE0, + 0x70,0x43,0x40,0x19,0x41,0x00,0x0C,0x90,0x08,0x98,0x44,0x5E,0x13,0x20,0xC0,0x43, + 0x84,0x42,0x03,0xDA,0x04,0x98,0x00,0x19,0x04,0x90,0x04,0xE0,0x14,0x2C,0x02,0xDD, + 0x05,0x98,0x00,0x19,0x05,0x90,0x03,0x98,0x00,0x28,0x7E,0xD1,0x0E,0x98,0x32,0x28, + 0x7B,0xD2,0x1E,0x2C,0x79,0xDD,0x00,0x20,0x02,0x90,0x00,0x2E,0x7F,0xD0,0x06,0x98, + 0x40,0x1E,0x0B,0x90,0x86,0x42,0x7A,0xDA,0x00,0x2D,0x78,0xD0,0x07,0x98,0x40,0x1E, + 0x0A,0x90,0x85,0x42,0x73,0xDA,0x07,0x9A,0x70,0x1E,0x50,0x43,0x40,0x19,0x08,0x9A, + 0x40,0x00,0x82,0x18,0x13,0x46,0x20,0x3B,0x1E,0x27,0xDF,0x5F,0xA7,0x42,0x66,0xDA, + 0x08,0x9B,0x18,0x5E,0xA0,0x42,0x62,0xDA,0x02,0x20,0x10,0x5E,0xA0,0x42,0x5E,0xDA, + 0xC9,0x18,0x08,0x46,0x20,0x38,0x1E,0x22,0x82,0x5E,0xA2,0x42,0x57,0xDA,0x07,0x9A, + 0x70,0x1C,0x50,0x43,0x40,0x19,0x40,0x00,0xC2,0x18,0x13,0x46,0x20,0x3B,0x1E,0x27, + 0xDF,0x5F,0xA7,0x42,0x4B,0xDC,0x08,0x9B,0x18,0x5E,0xA0,0x42,0x47,0xDC,0x02,0x20, + 0x10,0x5E,0xA0,0x42,0x43,0xDC,0x02,0x20,0x08,0x5E,0xA0,0x42,0x3F,0xDC,0x37,0xA0, + 0x00,0x68,0x01,0x27,0x09,0x90,0x01,0x90,0x00,0x20,0x00,0x90,0x03,0x21,0xFB,0xF7, + 0x59,0xF9,0x01,0xAA,0x10,0x5C,0x51,0x5C,0x78,0x43,0x79,0x43,0x80,0x19,0x49,0x19, + 0x40,0xB2,0x49,0xB2,0x00,0x28,0x15,0xDB,0x0B,0x9A,0x90,0x42,0x12,0xDC,0x00,0x29, + 0x10,0xDB,0x0A,0x9A,0x91,0x42,0x0D,0xDC,0x07,0x9A,0x50,0x43,0x40,0x18,0x0C,0x99, + 0x00,0xB2,0x81,0x42,0x06,0xD0,0x08,0x99,0x40,0x00,0x08,0x5A,0x02,0x99,0x40,0x18, + 0x00,0xB2,0x02,0x90,0x00,0x98,0x40,0x1C,0xC0,0xB2,0x00,0x90,0x09,0x28,0xD5,0xD3, + 0x7F,0x1C,0xFF,0xB2,0x02,0x2F,0x03,0xD8,0x00,0xE0,0x08,0xE0,0x09,0x98,0xCA,0xE7, + 0x02,0x98,0x00,0x19,0x00,0xB2,0x0A,0x28,0x01,0xDA,0x01,0x20,0x03,0x90,0x6D,0x1C, + 0xED,0xB2,0x07,0x98,0x85,0x42,0x00,0xD2,0x5A,0xE7,0x76,0x1C,0xF6,0xB2,0x06,0x98, + 0x86,0x42,0x00,0xD2,0x52,0xE7,0x04,0x99,0x05,0x98,0x40,0x18,0x10,0x49,0x88,0x42, + 0x07,0xDA,0x0D,0x98,0x00,0x21,0xC1,0x73,0x0D,0x98,0x01,0x21,0x81,0x71,0x0F,0xB0, + 0xF0,0xBD,0x03,0x98,0x00,0x28,0x03,0xD0,0x0D,0x98,0x64,0x21,0xC1,0x73,0xF6,0xE7, + 0x0E,0x98,0x00,0x28,0xF3,0xD0,0x0D,0x99,0x40,0x1E,0xC8,0x73,0xEF,0xE7,0x00,0x00, + 0xAC,0x03,0x00,0x20,0x10,0x06,0x00,0x20,0xB8,0x04,0x00,0x20,0xFF,0x00,0x01,0x00, + 0x78,0xEC,0xFF,0xFF,0x10,0xB5,0xFF,0xF7,0xF9,0xFD,0x0B,0x4C,0x20,0x78,0x10,0x28, + 0x04,0xD0,0x11,0x28,0xFA,0xD1,0xFF,0xF7,0xC7,0xF8,0xF7,0xE7,0x00,0xF0,0x02,0xFD, + 0x00,0xF0,0x52,0xFB,0x00,0xF0,0x76,0xFD,0x00,0xF0,0x4E,0xFC,0x00,0xF0,0x5C,0xFB, + 0x00,0xF0,0x1C,0xFD,0xEA,0xE7,0x00,0x00,0x98,0x04,0x00,0x20,0x03,0x68,0x0B,0x60, + 0x01,0x68,0xD2,0x1C,0x89,0x18,0x89,0x08,0x89,0x00,0x01,0x60,0x70,0x47,0xF3,0xB5, + 0x81,0xB0,0x02,0x98,0x00,0x27,0x40,0x1E,0x00,0x90,0x29,0xE0,0x54,0x20,0x01,0x99, + 0x78,0x43,0x46,0x18,0x30,0x7C,0x01,0x07,0x09,0x0F,0x01,0x29,0x1E,0xD9,0x00,0x09, + 0x1C,0xD1,0x7D,0x1C,0x17,0xE0,0x54,0x20,0x01,0x99,0x68,0x43,0x44,0x18,0x20,0x7C, + 0x01,0x07,0x09,0x0F,0x01,0x29,0x0D,0xD9,0x00,0x09,0x0B,0xD1,0x23,0x68,0x62,0x6A, + 0x31,0x68,0x70,0x6A,0xFF,0xF7,0x34,0xFE,0x00,0x28,0x03,0xD0,0x30,0x68,0x21,0x68, + 0x31,0x60,0x20,0x60,0x6D,0x1C,0x02,0x98,0x85,0x42,0xE4,0xD3,0x00,0x98,0x7F,0x1C, + 0x87,0x42,0xD3,0xD3,0xFE,0xBD,0x00,0x00,0x10,0xB5,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x54,0x22,0x20,0x46,0xC0,0x30,0x41,0x69,0x00,0x69,0x89,0x78,0x51,0x43,0xFB,0xF7, + 0xDA,0xF8,0x02,0x48,0xA0,0x60,0x00,0x20,0x10,0xBD,0x00,0x00,0x81,0x4F,0x00,0x00, + 0xF7,0xB5,0x90,0xB0,0x10,0x98,0x0C,0x25,0xC0,0x30,0x01,0x69,0x07,0x91,0x44,0x69, + 0xFF,0x22,0xA0,0x78,0x06,0x90,0x0A,0x21,0x03,0xA8,0xFB,0xF7,0xBD,0xF8,0x00,0x20, + 0x02,0x90,0x0D,0xE0,0x54,0x21,0x07,0x9A,0x41,0x43,0x89,0x18,0x09,0x7C,0x09,0x07, + 0x05,0xD0,0x02,0x9A,0x03,0xA9,0x88,0x54,0x02,0x99,0x49,0x1C,0x02,0x91,0x40,0x1C, + 0x06,0x99,0x88,0x42,0xEE,0xDB,0x02,0x99,0x12,0x98,0x88,0x42,0x00,0xDC,0x08,0x46, + 0x46,0x00,0x46,0x43,0x77,0x19,0x0A,0x90,0x00,0xF0,0x68,0xFA,0x08,0x90,0x38,0x46, + 0x00,0xF0,0x82,0xFA,0x39,0x46,0x08,0x98,0xFB,0xF7,0x9D,0xF8,0x08,0x98,0xFF,0x22, + 0x30,0x18,0x29,0x46,0x09,0x90,0xFB,0xF7,0x8F,0xF8,0x12,0x99,0x02,0x98,0x48,0x43, + 0x0F,0x90,0x00,0x28,0x77,0xD0,0x08,0x46,0x02,0x99,0x88,0x42,0x00,0xDC,0x08,0x46, + 0xC0,0xB2,0x0B,0x90,0x70,0x20,0x00,0x5B,0x40,0x34,0x00,0x90,0xA0,0x7D,0x00,0x27, + 0x0E,0x90,0x85,0xE0,0x00,0x26,0x7E,0xE0,0x02,0x98,0x5F,0x4D,0x87,0x42,0x73,0xDA, + 0x12,0x98,0x86,0x42,0x70,0xDA,0x03,0xA8,0xC0,0x5D,0x54,0x21,0x48,0x43,0x07,0x99, + 0x44,0x18,0x11,0x98,0x31,0x01,0x08,0x18,0x00,0x68,0x01,0x90,0x69,0x46,0x06,0x20, + 0x08,0x5E,0x0C,0x90,0x04,0x20,0x08,0x5E,0x23,0x46,0x0D,0x90,0x40,0x33,0x01,0x93, + 0x02,0x21,0x00,0x20,0x59,0x5E,0x18,0x5E,0x0C,0x9B,0x0D,0x9A,0x00,0xF0,0x03,0xFD, + 0x05,0x46,0x02,0x20,0x20,0x5E,0x01,0x9B,0x84,0x46,0x02,0x21,0x00,0x20,0x00,0x22, + 0x59,0x5E,0x18,0x5E,0xA2,0x5E,0x63,0x46,0x00,0xF0,0xF5,0xFC,0x01,0x90,0x02,0x21, + 0x00,0x20,0x61,0x5E,0x20,0x5E,0x0C,0x9B,0x0D,0x9A,0x00,0xF0,0xEC,0xFC,0x00,0x99, + 0x8D,0x42,0x39,0xDB,0x88,0x42,0x37,0xDB,0x62,0x7C,0x01,0x21,0xD2,0x09,0x07,0xD1, + 0x22,0x7C,0x0E,0x9B,0x12,0x07,0x12,0x0F,0x5A,0x43,0x32,0x2A,0x00,0xDB,0x00,0x21, + 0x01,0x9A,0x00,0x2A,0x26,0xD0,0x00,0x29,0x24,0xD1,0x01,0x99,0x2A,0x11,0x8A,0x42, + 0x12,0xDC,0x40,0x43,0x49,0x43,0x41,0x1A,0x28,0x46,0x68,0x43,0x08,0x1A,0x01,0x99, + 0xC0,0x01,0x69,0x43,0xFA,0xF7,0xE4,0xFF,0x80,0x38,0x00,0x28,0x04,0xDD,0x80,0x28, + 0x03,0xDB,0x80,0x20,0x01,0xE0,0x1F,0xE0,0x00,0x20,0x01,0x9A,0x00,0x99,0x80,0x11, + 0x89,0x18,0x41,0x43,0x00,0x98,0x08,0x18,0x0E,0x99,0x10,0x29,0x00,0xDD,0x40,0x00, + 0x85,0x42,0x01,0xDD,0x24,0x4D,0x6D,0x1E,0x0B,0x98,0x78,0x43,0x80,0x19,0x41,0x00, + 0x08,0x98,0x76,0x1C,0x45,0x52,0x0B,0x98,0x86,0x42,0x00,0xDA,0x7C,0xE7,0x7F,0x1C, + 0x0B,0x98,0x87,0x42,0x00,0xDA,0x75,0xE7,0x0F,0x98,0x01,0x28,0x0E,0xD0,0x00,0x28, + 0x09,0xD0,0x00,0x23,0xDB,0x43,0x12,0x9A,0x01,0x93,0x00,0x92,0x08,0xA8,0x07,0xC8, + 0x02,0x9B,0x00,0xF0,0x2B,0xF8,0x00,0x20,0x03,0xAA,0x11,0xE0,0x08,0x98,0x01,0x88, + 0x11,0x48,0x40,0x1E,0x81,0x42,0xF6,0xD2,0x09,0x99,0x00,0x20,0x08,0x70,0xF2,0xE7, + 0x09,0x99,0x09,0x5C,0xFF,0x29,0x02,0xD0,0x53,0x5C,0x09,0x99,0x0B,0x54,0x40,0x1C, + 0x12,0x99,0x88,0x42,0xF4,0xDB,0x0A,0x46,0x09,0x9B,0x11,0x99,0x10,0x98,0x00,0xF0, + 0xAD,0xF8,0x08,0x98,0x00,0xF0,0xC8,0xF9,0x06,0x99,0x07,0x98,0xFF,0xF7,0xA7,0xFE, + 0x06,0x98,0x13,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0x7F,0x00,0x00,0xFF,0xB5,0x81,0xB0, + 0x04,0x46,0x15,0x46,0x00,0xF0,0x7A,0xF9,0x06,0x46,0xB4,0x20,0x00,0xF0,0x94,0xF9, + 0x00,0x20,0x2A,0x46,0x6A,0x43,0x0C,0xE0,0x41,0x00,0x67,0x5A,0x17,0x4B,0x9F,0x42, + 0x01,0xD3,0x5B,0x1C,0x63,0x52,0x15,0x4B,0x67,0x5A,0x5B,0x1C,0xDB,0x1B,0x63,0x52, + 0x40,0x1C,0x82,0x42,0xF0,0xD8,0x2A,0x46,0x21,0x46,0x30,0x46,0x01,0xF0,0x2E,0xF9, + 0xFF,0x22,0x0A,0x99,0x02,0x98,0xFA,0xF7,0x8F,0xFF,0x00,0x23,0x0D,0xE0,0xF0,0x5C, + 0x04,0x99,0x88,0x42,0x08,0xD2,0xF1,0x56,0x69,0x43,0xC9,0x18,0x49,0x00,0x61,0x5A, + 0x00,0x29,0x01,0xD0,0x02,0x99,0xC8,0x54,0x5B,0x1C,0x0A,0x98,0x83,0x42,0xEE,0xD3, + 0x30,0x46,0x00,0xF0,0x81,0xF9,0x05,0xB0,0xF0,0xBD,0x00,0x00,0xFE,0x7F,0x00,0x00, + 0xF8,0xB5,0x8E,0x46,0x01,0x68,0x00,0x91,0x24,0x21,0x6C,0x46,0x00,0x22,0x41,0x5E, + 0xA2,0x5E,0x02,0x23,0x8A,0x1A,0x26,0x21,0x41,0x5E,0xE3,0x5E,0xC9,0x1A,0x16,0x23, + 0xC3,0x5E,0x9B,0x18,0x18,0x22,0x82,0x5E,0x54,0x18,0x19,0x46,0x22,0x46,0x59,0x43, + 0x62,0x43,0x8F,0x18,0x41,0x7C,0x00,0x91,0xCD,0x09,0x71,0x46,0x40,0x31,0x46,0x7D, + 0x8C,0x46,0x71,0x46,0x42,0x8B,0x76,0x43,0x20,0x31,0xBE,0x42,0x15,0xDD,0x00,0x2D, + 0x07,0xD1,0x67,0x46,0xBF,0x7D,0x18,0x4E,0xBA,0x18,0xB2,0x42,0x00,0xDC,0x16,0x46, + 0x32,0x46,0x89,0x78,0x0A,0x26,0x71,0x43,0x91,0x42,0x03,0xDA,0x01,0x25,0x00,0x23, + 0x1C,0x46,0x1A,0x46,0x00,0x21,0x01,0x77,0x13,0xE0,0xB6,0x00,0xBE,0x42,0x01,0xDA, + 0xCE,0x79,0x01,0xE0,0x06,0x7F,0x76,0x1C,0x06,0x77,0xC9,0x79,0xF6,0xB2,0x8E,0x42, + 0x07,0xD1,0x00,0x25,0x61,0x46,0x49,0x7D,0x2A,0x46,0x2B,0x46,0x2C,0x46,0x41,0x75, + 0xE8,0xE7,0x00,0x99,0x49,0x06,0x49,0x0E,0xED,0x01,0x29,0x43,0x41,0x74,0x42,0x83, + 0xC3,0x82,0x04,0x83,0xF8,0xBD,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xB5,0x85,0xB0, + 0xC0,0x30,0x03,0x90,0x04,0x69,0x40,0x69,0x00,0x90,0x80,0x78,0x01,0x90,0x00,0x20, + 0x84,0x46,0x01,0x46,0x02,0x90,0x3F,0xE0,0x08,0x98,0x47,0x5C,0xFF,0x2F,0x40,0xD0, + 0x54,0x20,0x78,0x43,0x00,0x19,0x42,0x7B,0x0E,0x01,0x53,0x00,0xD5,0x18,0x06,0x9B, + 0xF3,0x18,0x5E,0x7B,0xAA,0x19,0x92,0x08,0x04,0x92,0xC5,0x7A,0x6E,0x00,0xAD,0x19, + 0xDE,0x7A,0xAA,0x19,0x45,0x6A,0x85,0x62,0x05,0x68,0x92,0x08,0x45,0x62,0x96,0x46, + 0x45,0x7B,0x85,0x74,0x1A,0x46,0x1B,0x68,0x96,0x68,0x55,0x68,0xD2,0x68,0x68,0xC0, + 0x0C,0x38,0xC2,0x60,0x04,0x9A,0x42,0x73,0x72,0x46,0xC2,0x72,0x02,0x7C,0x12,0x07, + 0x12,0x0F,0x02,0x74,0x0A,0x2A,0x06,0xD2,0x04,0x23,0xDA,0x41,0x9B,0x06,0xD2,0x18, + 0x1C,0x23,0xDA,0x41,0x02,0x74,0x01,0x20,0xB8,0x40,0x62,0x46,0x10,0x43,0x84,0x46, + 0x02,0x98,0x40,0x1C,0x02,0x90,0x49,0x1C,0x07,0x98,0x81,0x42,0xBC,0xD3,0x00,0x21, + 0x68,0xE0,0x01,0x98,0xC2,0xB2,0x00,0x20,0x07,0xE0,0x54,0x23,0x43,0x43,0x1B,0x19, + 0x1B,0x7C,0x1B,0x07,0x03,0xD0,0x40,0x1C,0xC0,0xB2,0x90,0x42,0xF5,0xD3,0xFF,0x23, + 0x90,0x42,0x00,0xD2,0x03,0x46,0x9E,0x46,0xFF,0x2B,0xE4,0xD0,0x18,0x46,0x54,0x22, + 0x50,0x43,0x00,0x19,0x42,0x7C,0x80,0x23,0x1A,0x43,0x42,0x74,0x04,0x92,0x00,0x9A, + 0x40,0x32,0x12,0x7D,0x42,0x75,0x00,0x9A,0x20,0x32,0x93,0x7A,0xD2,0x7A,0x9A,0x18, + 0x52,0x08,0x02,0x75,0x06,0x9A,0x0B,0x01,0x9A,0x18,0x13,0x46,0xE8,0xCB,0xE8,0xC0, + 0x10,0x38,0x15,0x68,0x45,0x62,0x55,0x7B,0x85,0x74,0x15,0x68,0x05,0x62,0x0C,0xCA, + 0x43,0x64,0x02,0x64,0x02,0x7C,0x73,0x46,0x12,0x09,0x12,0x01,0x52,0x1C,0x02,0x74, + 0x04,0x9A,0x5B,0x06,0xD2,0x09,0xD2,0x01,0x5B,0x0E,0x1A,0x43,0x42,0x74,0x72,0x46, + 0x01,0x20,0x90,0x40,0x62,0x46,0x10,0x43,0x84,0x46,0xAC,0xE7,0x01,0x20,0x88,0x40, + 0x62,0x46,0x10,0x42,0x15,0xD1,0x54,0x20,0x48,0x43,0x00,0x19,0x02,0x7C,0x13,0x07, + 0x0F,0xD0,0x13,0x07,0x12,0x09,0x52,0x1C,0x1B,0x0F,0x12,0x01,0x13,0x43,0x03,0x74, + 0x42,0x7C,0xD2,0x09,0x05,0xD1,0x43,0x6A,0x83,0x62,0x03,0x68,0x43,0x62,0x02,0x6C, + 0x02,0x60,0x49,0x1C,0x01,0x98,0x81,0x42,0xE0,0xDB,0x00,0x25,0x13,0xE0,0x54,0x20, + 0x68,0x43,0x00,0x19,0x01,0x7C,0x09,0x07,0x09,0x0F,0x01,0x29,0x0A,0xD9,0x03,0x99, + 0x49,0x69,0x89,0x68,0x09,0x06,0x02,0xD5,0x02,0x99,0x01,0x29,0x08,0xD0,0x00,0x99, + 0xFF,0xF7,0xCE,0xFE,0x6D,0x1C,0x01,0x98,0x85,0x42,0xE8,0xDB,0x09,0xB0,0xF0,0xBD, + 0x41,0x7C,0x49,0x06,0x49,0x0E,0x41,0x74,0xF4,0xE7,0x00,0x00,0x09,0x48,0x01,0x21, + 0x00,0x68,0xC1,0x70,0x82,0x78,0x91,0x00,0x09,0x18,0x09,0x1D,0x00,0x2A,0x04,0xD0, + 0x0A,0x1F,0x13,0x88,0x52,0x88,0x9A,0x18,0x0A,0x80,0x09,0x88,0x40,0x30,0x08,0x18, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x02,0x48,0x00,0x21,0x00,0x68,0xC1,0x70, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x10,0xB5,0x0D,0x49,0x00,0x22,0x09,0x68, + 0x00,0x28,0xCA,0x70,0x0B,0xD0,0x0B,0x4A,0xC0,0x1C,0x10,0x40,0x8A,0x78,0x0B,0x88, + 0x92,0x00,0x52,0x18,0x94,0x88,0x1B,0x1B,0x9B,0xB2,0x98,0x42,0x01,0xD9,0x00,0x20, + 0x10,0xBD,0xD0,0x80,0x88,0x78,0x40,0x1C,0x88,0x70,0x01,0x20,0x10,0xBD,0x00,0x00, + 0x94,0x21,0x00,0x20,0xFC,0xFF,0x00,0x00,0x30,0xB5,0x08,0x49,0x09,0x68,0x8B,0x78, + 0x0C,0x46,0x9A,0x00,0x52,0x18,0x15,0x88,0x40,0x34,0x2C,0x19,0x84,0x42,0x03,0xD1, + 0x5B,0x1E,0x8B,0x70,0x50,0x88,0x30,0xBD,0x00,0x20,0x30,0xBD,0x94,0x21,0x00,0x20, + 0x04,0x4A,0x40,0x39,0x10,0x60,0x01,0x80,0x00,0x21,0x81,0x70,0xC1,0x70,0x81,0x80, + 0x70,0x47,0x00,0x00,0x94,0x21,0x00,0x20,0x10,0xB5,0xFA,0xF7,0x69,0xFE,0x00,0x28, + 0x05,0xDA,0xFC,0xF7,0xC1,0xF9,0x03,0x48,0x01,0x21,0x81,0x71,0x10,0xBD,0x00,0xF0, + 0xF4,0xFD,0x10,0xBD,0xB8,0x04,0x00,0x20,0xF8,0xB5,0x75,0x4F,0x24,0x20,0x78,0x70, + 0xFD,0xF7,0x9A,0xFA,0x3C,0x46,0x20,0x34,0x60,0x7B,0x00,0x25,0x40,0x06,0x00,0x28, + 0x10,0xD0,0x01,0xE0,0x00,0xF0,0x7E,0xFA,0xFE,0xF7,0xD8,0xFF,0x00,0x28,0xF9,0xD1, + 0x60,0x7B,0xC1,0x09,0x40,0x06,0x40,0x0E,0xFC,0xF7,0x84,0xFD,0x65,0x73,0x01,0x20, + 0xA0,0x71,0xF8,0xBD,0x78,0x7A,0x67,0x4E,0x01,0x02,0x30,0x68,0x3A,0x7A,0xFF,0x30, + 0x11,0x43,0x41,0x30,0x42,0x7B,0x03,0x7B,0x10,0x02,0x18,0x43,0x81,0x42,0x12,0xD9, + 0xFF,0xF7,0x48,0xFB,0x00,0x28,0x0E,0xD0,0x30,0x68,0xFF,0x30,0x41,0x30,0x41,0x7B, + 0x02,0x7B,0x09,0x02,0x11,0x43,0x0A,0x39,0x39,0x72,0x09,0x0A,0x79,0x72,0x00,0x7C, + 0x00,0xF0,0x26,0xFD,0x1E,0xE0,0x00,0x21,0x02,0x20,0xFD,0xF7,0xD1,0xFA,0x39,0x1D, + 0xFA,0xF7,0x9E,0xFD,0x78,0x7E,0x39,0x7E,0x00,0x02,0x08,0x43,0x30,0x68,0x16,0xD0, + 0xFF,0x30,0x41,0x30,0x00,0x7C,0x00,0xF0,0x13,0xFD,0x01,0x22,0x21,0x21,0x08,0x20, + 0x01,0xF0,0x74,0xFB,0x78,0x7E,0x39,0x7E,0x00,0x02,0x08,0x43,0x40,0x1E,0x38,0x76, + 0x00,0x0A,0x78,0x76,0x00,0x21,0x01,0x20,0xFD,0xF7,0xB2,0xFA,0xF8,0xBD,0xFF,0x21, + 0x9C,0x31,0x09,0x5C,0x00,0x29,0x18,0xD0,0xA1,0x7B,0x00,0x29,0x15,0xD1,0x79,0x7A, + 0x3A,0x7A,0x09,0x02,0x11,0x43,0x01,0xD0,0x3D,0x75,0x0D,0xE0,0x16,0x21,0x79,0x56, + 0x05,0x29,0x02,0xDD,0x39,0x7D,0x49,0x1C,0x05,0xE0,0x4A,0x1D,0x05,0xDA,0x39,0x7D, + 0x00,0x29,0x01,0xD0,0x49,0x1E,0x39,0x75,0xBD,0x75,0xB9,0x7F,0x3D,0x46,0x00,0x29, + 0x0C,0xD1,0x61,0x78,0x00,0x29,0x09,0xD0,0x01,0x46,0xFF,0x31,0x41,0x31,0xCA,0x7B, + 0x8B,0x7B,0x11,0x02,0x19,0x43,0x29,0x72,0x09,0x0A,0x69,0x72,0x69,0x7A,0x2A,0x7A, + 0x09,0x02,0x11,0x43,0x04,0xD1,0xFF,0x30,0x41,0x30,0x00,0x7C,0x00,0xF0,0xC8,0xFC, + 0x68,0x7A,0x29,0x7A,0x02,0x02,0x30,0x68,0x0A,0x43,0xFF,0x30,0x41,0x30,0x41,0x7B, + 0x03,0x7B,0x09,0x02,0x19,0x43,0x8A,0x42,0x02,0xD1,0x40,0x7C,0x00,0xF0,0xB8,0xFC, + 0x30,0x68,0xFF,0x30,0x81,0x30,0xC0,0x7E,0x00,0x28,0x08,0xD0,0xA0,0x7B,0x00,0x28, + 0x05,0xD1,0x28,0x7D,0x00,0x28,0x02,0xD0,0x08,0x20,0xFC,0xF7,0x1D,0xF9,0xE8,0x7F, + 0x21,0x24,0x00,0x28,0x06,0xD1,0x30,0x68,0xFF,0x30,0x41,0x30,0x80,0x7D,0x00,0x28, + 0x00,0xD0,0x22,0x24,0x22,0x2C,0x02,0xD1,0x01,0x20,0xFC,0xF7,0x7B,0xFE,0x02,0x20, + 0xFC,0xF7,0x0A,0xF9,0x01,0x22,0x21,0x46,0x0A,0x20,0x01,0xF0,0xF7,0xFA,0x06,0x46, + 0x22,0x2C,0x02,0xD1,0x00,0x20,0xFC,0xF7,0x6D,0xFE,0x30,0x07,0x04,0xD4,0x01,0x22, + 0x21,0x21,0x08,0x20,0x01,0xF0,0xEA,0xFA,0xE8,0x7F,0x40,0x1E,0xFE,0x28,0x00,0xD2, + 0xE8,0x77,0x00,0x21,0x01,0x20,0xFD,0xF7,0x2B,0xFA,0x00,0xF0,0x07,0xFD,0xF8,0xBD, + 0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0xF0,0xB5,0xBD,0xB0,0x00,0x20,0x4D,0x49, + 0x00,0x90,0x0A,0x79,0xCB,0x78,0x11,0x02,0x4B,0x4A,0x01,0x20,0x12,0x7E,0x19,0x43, + 0x91,0x42,0x00,0xD8,0x00,0x20,0x49,0x4C,0x49,0x4E,0x20,0x82,0x23,0x21,0x71,0x70, + 0x30,0x1D,0xFA,0xF7,0xD4,0xFC,0x47,0x4A,0x11,0x68,0x88,0x42,0x04,0xD9,0x41,0x1A, + 0xC9,0x02,0x01,0x23,0xDB,0x03,0x03,0xE0,0x41,0x1A,0xC9,0x02,0x0F,0x23,0xDB,0x02, + 0xC9,0x18,0x09,0x0C,0x61,0x82,0x10,0x60,0x68,0x46,0xFA,0xF7,0xBB,0xFD,0x3D,0x48, + 0x71,0x7F,0x00,0x1D,0x08,0x22,0xF0,0x29,0x81,0x68,0x01,0xD1,0x11,0x43,0x00,0xE0, + 0x91,0x43,0x81,0x60,0x38,0x48,0x01,0xA9,0x40,0x68,0x00,0xF0,0xCE,0xFF,0x04,0x1E, + 0x00,0xDA,0x00,0x24,0x32,0x4D,0xFF,0x21,0x20,0x35,0xE8,0x78,0x9B,0x31,0x00,0x09, + 0x00,0x01,0xC0,0xB2,0x20,0x43,0xE8,0x70,0x30,0x48,0x00,0x68,0x09,0x5C,0x02,0x29, + 0x11,0xD1,0x71,0x7C,0x00,0x29,0x0C,0xD1,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A, + 0x08,0x02,0x10,0x43,0x01,0xF0,0x60,0xFA,0x28,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7, + 0x4D,0xFD,0x00,0x20,0xF0,0x70,0x70,0x7F,0xFF,0x28,0x0A,0xD1,0x30,0x7C,0x00,0x28, + 0x17,0xD1,0x30,0x7D,0xE1,0xB2,0x02,0x07,0x12,0x0F,0x01,0xA8,0xFE,0xF7,0x82,0xFA, + 0x0F,0xE0,0xF0,0x28,0x11,0xD1,0x1B,0x4F,0x13,0x20,0x44,0x37,0x38,0x56,0x80,0x1C, + 0x07,0xD0,0x01,0x20,0xE8,0x70,0xF8,0x7C,0xFE,0xF7,0x1E,0xFA,0xFE,0x20,0xF8,0x74, + 0x03,0xE0,0xE1,0xB2,0x01,0xA8,0xFE,0xF7,0x8F,0xFA,0x6B,0x46,0x18,0x78,0x00,0x28, + 0x08,0xD1,0xB0,0x7E,0x00,0x28,0x05,0xD1,0x30,0x7C,0x00,0x28,0x02,0xD1,0x28,0x79, + 0xFF,0x28,0x01,0xD0,0x00,0x20,0x07,0xE0,0x70,0x7A,0x31,0x7A,0x00,0x02,0x08,0x43, + 0x0B,0x49,0x88,0x42,0x03,0xD2,0x40,0x1C,0x30,0x72,0x00,0x0A,0x70,0x72,0x3D,0xB0, + 0xF0,0xBD,0x00,0x00,0x60,0x03,0x00,0x20,0x16,0x05,0x00,0x20,0x60,0x1F,0x00,0x20, + 0x98,0x04,0x00,0x20,0x14,0x06,0x00,0x20,0x58,0x07,0x00,0x20,0x10,0x06,0x00,0x20, + 0xFF,0x7F,0x00,0x00,0x70,0xB5,0x0F,0x4D,0x21,0x20,0x68,0x70,0x0E,0x48,0x2C,0x46, + 0x80,0x78,0x20,0x34,0x60,0x71,0xA0,0x79,0x00,0x28,0x0F,0xD0,0xFA,0xF7,0x20,0xFD, + 0x00,0x20,0xA0,0x71,0x01,0x20,0x00,0xF0,0x8D,0xFC,0x00,0x21,0x02,0x20,0xFD,0xF7, + 0x5F,0xF9,0x29,0x1D,0xFA,0xF7,0x2C,0xFC,0x00,0xF0,0x6C,0xFC,0x00,0x20,0x00,0xF0, + 0x81,0xFC,0x70,0xBD,0x98,0x04,0x00,0x20,0xD6,0x04,0x00,0x20,0x70,0xB5,0x25,0x4D, + 0x26,0x20,0x68,0x70,0x28,0x7C,0x2C,0x46,0x20,0x34,0x00,0x28,0x10,0xD0,0x36,0x21, + 0x21,0x48,0xFA,0xF7,0x00,0xFC,0xFE,0xF7,0x19,0xFE,0x00,0x28,0x01,0xD0,0x00,0xF0, + 0xB9,0xF8,0x00,0xF0,0x0D,0xFB,0x00,0x28,0x1A,0xD0,0xFF,0x20,0x60,0x72,0x17,0xE0, + 0xFE,0xF7,0x0C,0xFE,0x00,0x28,0x13,0xD0,0x18,0x48,0x00,0x68,0xFF,0x30,0x81,0x30, + 0xC0,0x7E,0x00,0x28,0x02,0xD0,0xA0,0x7B,0x00,0x28,0x09,0xD0,0x00,0xF0,0xA2,0xF8, + 0x00,0xF0,0x05,0xFC,0x00,0x28,0x03,0xD0,0x00,0xF0,0xF2,0xFA,0x00,0xF0,0xFC,0xFB, + 0xFB,0xF7,0xFA,0xFF,0x00,0xF0,0x2E,0xFC,0x0A,0x48,0x0C,0x30,0xFA,0xF7,0xDF,0xFB, + 0x00,0x68,0x0B,0x49,0x88,0x42,0x02,0xD0,0x02,0x20,0xFE,0xF7,0x53,0xF9,0xE8,0x7A, + 0xA9,0x7A,0x00,0x02,0x08,0x43,0xFF,0x28,0x03,0xD2,0x40,0x1C,0xA8,0x72,0x00,0x0A, + 0xE8,0x72,0x70,0xBD,0x98,0x04,0x00,0x20,0x7A,0x01,0x00,0x20,0x10,0x06,0x00,0x20, + 0x5A,0xA5,0xAC,0xCA,0x01,0x48,0x00,0x68,0xC0,0x7E,0x70,0x47,0x10,0x06,0x00,0x20, + 0xFF,0xB5,0xFF,0x31,0x41,0x31,0x4D,0x68,0x00,0x21,0x81,0xB0,0x07,0x46,0x1E,0x46, + 0x0C,0x46,0xE0,0x00,0x40,0x19,0x82,0x8A,0x92,0x0B,0xB2,0x42,0x05,0xD1,0x83,0x69, + 0x29,0x46,0x38,0x46,0x03,0x9A,0x98,0x47,0x01,0x46,0x64,0x1C,0x15,0x2C,0xF0,0xDB, + 0x08,0x46,0x05,0xB0,0xF0,0xBD,0x00,0x00,0x10,0xB5,0x04,0x46,0x08,0x4B,0x4B,0x22, + 0x02,0x21,0x00,0xF0,0x19,0xF8,0xFF,0x34,0x41,0x34,0x64,0x68,0xFF,0xF7,0x4E,0xFD, + 0xC0,0x34,0xE0,0x60,0x80,0x20,0xFF,0xF7,0x67,0xFD,0x00,0x20,0x10,0xBD,0x00,0x00, + 0xE1,0x5A,0x00,0x00,0x10,0xB5,0x03,0x4B,0x3C,0x22,0x02,0x21,0x00,0xF0,0x04,0xF8, + 0x00,0x20,0x10,0xBD,0xF5,0x5A,0x00,0x00,0x30,0xB5,0xFF,0x30,0x41,0x30,0x44,0x68, + 0x00,0x20,0xC5,0x00,0x2D,0x19,0xAD,0x69,0x00,0x2D,0x05,0xD0,0x15,0x28,0x02,0xD0, + 0x40,0x1C,0x15,0x28,0xF5,0xDB,0x30,0xBD,0xC0,0x00,0x00,0x19,0x84,0x8A,0x89,0x03, + 0xA4,0x04,0xA4,0x0C,0x0C,0x43,0xA1,0x0B,0x89,0x03,0x92,0x04,0x92,0x0C,0x11,0x43, + 0x81,0x82,0x83,0x61,0x30,0xBD,0x10,0xB5,0x84,0x1A,0x00,0x2C,0x00,0xDC,0x14,0x1A, + 0xC8,0x1A,0xA2,0xB2,0x00,0x28,0x00,0xDC,0x58,0x1A,0x80,0xB2,0x52,0x43,0x41,0x00, + 0x91,0x42,0x01,0xD3,0x80,0xB2,0x10,0xBD,0x40,0x43,0x80,0x18,0x00,0xF0,0x62,0xFD, + 0x10,0xBD,0x00,0x00,0x70,0xB5,0x0B,0x4C,0x36,0x20,0xE5,0x79,0x0A,0x49,0x68,0x43, + 0x41,0x18,0x36,0x22,0x09,0x48,0xFA,0xF7,0x0F,0xFB,0x60,0x7A,0xFF,0x28,0x00,0xD0, + 0x65,0x72,0x6D,0x1C,0x08,0x2D,0x02,0xD3,0x00,0x20,0xE0,0x71,0x70,0xBD,0xE5,0x71, + 0x70,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0xB0,0x01,0x00,0x20,0x7A,0x01,0x00,0x20, + 0x10,0xB5,0xD4,0x23,0x5B,0x58,0x5B,0x7D,0x5B,0x08,0xFB,0xF7,0xBC,0xFF,0x00,0x20, + 0x10,0xBD,0x00,0x00,0xF8,0xB5,0xC0,0x31,0x49,0x69,0x00,0x91,0x00,0x27,0x15,0x21, + 0x14,0x23,0x41,0x56,0xC3,0x56,0x3C,0x46,0x59,0x43,0x27,0x23,0xBC,0x46,0x3E,0x46, + 0x3D,0x46,0xDB,0x43,0x02,0x68,0x0C,0xE0,0x00,0x20,0x10,0x5E,0x28,0x28,0x02,0xDD, + 0xC7,0x19,0x76,0x1C,0x03,0xE0,0x98,0x42,0x01,0xDA,0x04,0x19,0x6D,0x1C,0x49,0x1E, + 0x92,0x1C,0x00,0x29,0xF0,0xD1,0x00,0x2D,0x04,0xDD,0x29,0x46,0x20,0x46,0xFA,0xF7, + 0xB7,0xFA,0x84,0x46,0x12,0x48,0x84,0x42,0x05,0xDA,0x00,0x2C,0x00,0xDC,0x64,0x42, + 0x64,0x37,0xBC,0x42,0x0C,0xDC,0x4F,0x20,0xC0,0x43,0x84,0x45,0x01,0xDA,0x00,0x2E, + 0x06,0xD0,0x14,0x2D,0x0F,0xDD,0x84,0x45,0x0D,0xDA,0x0A,0x36,0xAE,0x42,0x0A,0xDA, + 0x00,0x98,0xFF,0x21,0x40,0x30,0x42,0x7C,0x53,0x1C,0xFF,0x2B,0x00,0xD2,0x51,0x1C, + 0x41,0x74,0x00,0x20,0xF8,0xBD,0x00,0x98,0x00,0x21,0x40,0x30,0xF8,0xE7,0x00,0x00, + 0x0C,0xFE,0xFF,0xFF,0x70,0x47,0x70,0x47,0xA5,0x20,0x70,0x47,0x00,0x20,0x70,0x47, + 0x70,0x47,0x00,0x00,0xF8,0xB5,0x5B,0x4E,0x5B,0x4B,0xF2,0x78,0xB0,0x78,0x1B,0x68, + 0x11,0x02,0x41,0x18,0x5C,0x7E,0x8D,0xB2,0x1B,0x7E,0x71,0x89,0x24,0x02,0x1C,0x43, + 0x0B,0x1B,0xDC,0xB2,0x73,0x78,0x00,0x2B,0x09,0xD0,0x0B,0x0A,0x33,0x71,0x71,0x71, + 0xB0,0x71,0xF2,0x71,0x30,0x1D,0xF0,0x60,0x00,0x1D,0x70,0x61,0x58,0xE0,0x4D,0x49, + 0x00,0x2C,0x49,0x69,0x6C,0xD1,0x4D,0x4F,0x31,0x61,0x39,0x46,0x20,0x31,0x03,0x46, + 0xFA,0xF7,0x0A,0xFB,0x0D,0x08,0x0F,0x11,0x16,0x1F,0x2B,0x2E,0x30,0x32,0x34,0x5E, + 0x5E,0x50,0x5E,0x00,0x00,0x2A,0x01,0xD1,0x10,0x20,0x00,0xE0,0x11,0x20,0x38,0x70, + 0xF8,0xBD,0x3A,0x74,0x1A,0xE0,0x01,0x20,0x88,0x70,0x00,0x20,0xF8,0x70,0xF8,0xBD, + 0x00,0x21,0x08,0x46,0xFC,0xF7,0xC4,0xFF,0x00,0x21,0x01,0x20,0xFD,0xF7,0x9E,0xFB, + 0xFE,0xE7,0x00,0x2A,0x05,0xD1,0x01,0x20,0xB8,0x77,0xF8,0x77,0x00,0x20,0x48,0x70, + 0xF8,0xBD,0x00,0x20,0xB8,0x77,0xF8,0x77,0xF8,0xBD,0x4A,0x70,0x7A,0x74,0xF8,0xBD, + 0x8A,0x72,0xF8,0xBD,0xFA,0x77,0xF8,0xBD,0x0A,0x70,0xF8,0xBD,0x00,0x2A,0x01,0xD1, + 0x00,0x21,0x00,0xE0,0x01,0x21,0x05,0x20,0xFC,0xF7,0xA2,0xFF,0x70,0x78,0x00,0x28, + 0xF3,0xD1,0x00,0x2C,0xF1,0xD0,0x71,0x69,0xF0,0x68,0x09,0x1A,0xA9,0x42,0x43,0xDD, + 0x00,0x28,0x01,0xD0,0x40,0x19,0xF0,0x60,0x30,0x69,0x00,0x28,0xE5,0xD0,0x40,0x19, + 0x30,0x61,0xF8,0xBD,0x00,0x2A,0x01,0xD1,0xFF,0x20,0x04,0xE0,0x01,0x2A,0x01,0xD1, + 0xF0,0x20,0x00,0xE0,0x00,0x20,0x78,0x77,0x00,0x20,0x08,0x72,0xC8,0x71,0xF8,0xBD, + 0x01,0x46,0x20,0x39,0x10,0x29,0xFA,0xD8,0x19,0x49,0x08,0x70,0xCA,0x70,0xF8,0xBD, + 0x10,0x2C,0x0E,0xD2,0x31,0x61,0x13,0x49,0xA0,0x00,0x18,0x31,0x08,0x58,0x11,0x4A, + 0x61,0x00,0x58,0x32,0xF0,0x60,0x51,0x5A,0x41,0x18,0x71,0x61,0x02,0x2C,0xCA,0xD8, + 0x10,0xE0,0x2F,0x2C,0xC7,0xD2,0x0B,0x49,0xA0,0x00,0x78,0x31,0x40,0x18,0x09,0x4A, + 0x40,0x38,0x61,0x00,0xF4,0x32,0x00,0x68,0x89,0x18,0x20,0x39,0xF0,0x60,0x09,0x88, + 0x40,0x18,0x70,0x61,0x30,0x61,0xB6,0xE7,0x00,0x20,0xF0,0x60,0x30,0x61,0x70,0x61, + 0xF8,0xBD,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x06,0x00,0x20,0x98,0x04,0x00,0x20, + 0xC8,0x04,0x00,0x20,0xF8,0xB5,0x45,0x48,0x43,0x49,0x41,0x60,0x44,0x49,0x81,0x60, + 0x44,0x49,0x04,0x27,0x0C,0x68,0x44,0x49,0xC4,0x60,0x01,0x61,0x43,0x49,0x41,0x61, + 0x43,0x49,0x81,0x61,0x43,0x49,0xC1,0x61,0x43,0x49,0x01,0x62,0x43,0x49,0x41,0x62, + 0x9C,0x21,0x40,0x30,0x41,0x80,0x40,0x21,0x81,0x80,0xFF,0x21,0xFD,0x31,0xC1,0x80, + 0x30,0x21,0x01,0x81,0x47,0x81,0x48,0x21,0x81,0x81,0x36,0x21,0xC1,0x81,0x44,0x21, + 0x01,0x82,0x0A,0x21,0x41,0x82,0x20,0x46,0x20,0x30,0x06,0x7C,0x43,0x7C,0x32,0x48, + 0x35,0x46,0x5D,0x43,0x0C,0x30,0x00,0x93,0xFA,0xF7,0xD9,0xF9,0x2B,0x49,0x34,0x4A, + 0x60,0x31,0x08,0x60,0x08,0x46,0x7C,0x30,0x07,0x80,0x53,0x6A,0x4B,0x60,0x6B,0x00, + 0x43,0x80,0x17,0x6D,0x8F,0x60,0x83,0x80,0x97,0x6A,0xCF,0x60,0xC3,0x80,0xD3,0x6A, + 0x0B,0x61,0x05,0x81,0x53,0x6B,0x4B,0x61,0x73,0x00,0x43,0x81,0x55,0x6D,0x8D,0x61, + 0x83,0x81,0x95,0x6B,0xCD,0x61,0xC3,0x81,0xD3,0x6B,0x0B,0x62,0x06,0x82,0x53,0x6C, + 0x4B,0x62,0x00,0x9B,0x5B,0x00,0x43,0x82,0x95,0x6D,0x8D,0x62,0x83,0x82,0x95,0x6C, + 0xCD,0x62,0xC3,0x82,0xD2,0x6C,0x0A,0x63,0x00,0x9B,0x03,0x83,0xFF,0x22,0x7D,0x32, + 0x23,0x46,0x15,0x5D,0x80,0x33,0x9A,0x7D,0x5B,0x7D,0x00,0x2D,0x01,0xD0,0x5A,0x43, + 0x00,0xE0,0xD2,0x18,0x17,0x4B,0x5D,0x6A,0x4D,0x63,0x55,0x00,0x45,0x83,0x1E,0x6A, + 0x8E,0x63,0x85,0x83,0x9E,0x6A,0xCE,0x63,0xC5,0x83,0xDD,0x69,0x0D,0x64,0x02,0x84, + 0xDA,0x6A,0x4A,0x64,0xE2,0x7E,0x42,0x84,0x01,0x22,0x52,0x07,0x8A,0x64,0x03,0x21, + 0x49,0x03,0x81,0x84,0xF8,0xBD,0x00,0x00,0x32,0x05,0x00,0x20,0x18,0x00,0x00,0x20, + 0xCE,0x05,0x00,0x20,0x10,0x06,0x00,0x20,0x98,0x04,0x00,0x20,0xC8,0x04,0x00,0x20, + 0x32,0x01,0x00,0x20,0x7A,0x01,0x00,0x20,0x60,0x03,0x00,0x20,0xCD,0x04,0x00,0x20, + 0xAC,0x03,0x00,0x20,0x44,0x04,0x00,0x20,0x10,0xB5,0x19,0x4A,0x11,0x89,0x00,0x29, + 0x01,0xD1,0x10,0x70,0x23,0xE0,0x01,0x29,0x10,0xD1,0x11,0x78,0x09,0x02,0x01,0x43, + 0x14,0x48,0x00,0x68,0x43,0x7E,0x04,0x7E,0x18,0x02,0x20,0x43,0x2F,0x30,0x81,0x42, + 0x02,0xD1,0x01,0x20,0x50,0x70,0x12,0xE0,0x51,0x81,0x10,0xE0,0x04,0x29,0x04,0xD2, + 0x53,0x78,0x00,0x2B,0x08,0xD1,0x50,0x54,0x06,0xE0,0x53,0x69,0x11,0x69,0x99,0x42, + 0x02,0xD2,0x08,0x70,0x49,0x1C,0x11,0x61,0x10,0x89,0xFF,0x28,0x07,0xD2,0x10,0x89, + 0x40,0x1C,0x80,0xB2,0x10,0x81,0x04,0x28,0x01,0xD1,0xFF,0xF7,0x6B,0xFE,0x10,0xBD, + 0x00,0x00,0x00,0x20,0x10,0x06,0x00,0x20,0x10,0xB5,0x0E,0x49,0xA5,0x24,0x4A,0x69, + 0xC8,0x68,0x90,0x42,0x02,0xD2,0x04,0x78,0x40,0x1C,0xC8,0x60,0x0A,0x48,0x40,0x7C, + 0x00,0x28,0x0D,0xD1,0x09,0x48,0x00,0x68,0xFF,0x30,0x81,0x30,0x80,0x7E,0x02,0x28, + 0x06,0xD1,0xC9,0x68,0x06,0x48,0x81,0x42,0x02,0xD1,0x00,0x20,0xFD,0xF7,0xD6,0xF9, + 0x20,0x46,0x10,0xBD,0x00,0x00,0x00,0x20,0x98,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0x7D,0x01,0x00,0x20,0x10,0xB5,0x1F,0x2A,0x06,0xD2,0x04,0x4C,0x93,0x00,0xE0,0x50, + 0x50,0x00,0x22,0x46,0x7C,0x32,0x11,0x52,0x10,0xBD,0x00,0x00,0x78,0x00,0x00,0x20, + 0x02,0x49,0x00,0x20,0x08,0x81,0x48,0x70,0x70,0x47,0x00,0x00,0x00,0x00,0x00,0x20, + 0xF8,0xB5,0x27,0x4C,0x00,0x25,0x27,0x4E,0xA5,0x70,0x30,0x68,0x23,0x46,0xFF,0x30, + 0x81,0x30,0x81,0x7E,0x01,0x27,0x20,0x7B,0x20,0x3B,0x01,0x29,0x02,0xD0,0x5A,0x7C, + 0x00,0x2A,0x19,0xD0,0x39,0x46,0x1F,0x46,0xD9,0x70,0x00,0x28,0x02,0xD1,0x01,0x20, + 0xFD,0xF7,0x9C,0xF9,0x30,0x68,0xFF,0x30,0x91,0x30,0x41,0x7A,0x02,0x7A,0x08,0x02, + 0x10,0x43,0x00,0xF0,0xA1,0xFE,0x05,0x46,0x20,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7, + 0x8D,0xF9,0x00,0x20,0xF8,0x70,0x21,0xE0,0x02,0x29,0x12,0xD1,0xD9,0x78,0x1E,0x46, + 0x00,0x29,0x06,0xD0,0x00,0x28,0x0A,0xD1,0xFD,0xF7,0x80,0xF9,0x01,0x20,0xFC,0xF7, + 0xC9,0xFD,0x20,0x7B,0x00,0x28,0x02,0xD1,0x01,0x20,0xFD,0xF7,0x77,0xF9,0xF7,0x70, + 0x0C,0xE0,0x00,0x28,0x02,0xD1,0x01,0x20,0xFD,0xF7,0x70,0xF9,0x01,0x20,0xFC,0xF7, + 0xB9,0xFD,0x20,0x7B,0x00,0x28,0x01,0xD1,0xFD,0xF7,0x68,0xF9,0x28,0x46,0xF8,0xBD, + 0xB8,0x04,0x00,0x20,0x10,0x06,0x00,0x20,0x10,0xB5,0x13,0x4C,0x01,0x46,0x20,0x7A, + 0x36,0x22,0x50,0x43,0x11,0x4A,0x80,0x18,0x36,0x22,0xFA,0xF7,0x65,0xF8,0x21,0x7A, + 0xE0,0x79,0x0B,0x46,0x49,0x1C,0x00,0x22,0x81,0x42,0x0B,0xD1,0x41,0x1C,0x20,0x72, + 0x08,0x29,0x00,0xD2,0x42,0x1C,0x08,0x49,0xE2,0x71,0x20,0x39,0x88,0x7D,0x40,0x1E, + 0x88,0x75,0x10,0xBD,0x07,0x2B,0x05,0xD1,0x00,0x28,0x01,0xD1,0x01,0x20,0xE0,0x71, + 0x22,0x72,0x10,0xBD,0x21,0x72,0x10,0xBD,0xB8,0x04,0x00,0x20,0xB0,0x01,0x00,0x20, + 0x10,0xB5,0x04,0x49,0x0A,0x7F,0x82,0x42,0x03,0xD0,0x08,0x77,0x00,0x21,0xFD,0xF7, + 0x85,0xF9,0x10,0xBD,0x98,0x04,0x00,0x20,0xF8,0xB5,0x2A,0x4D,0x00,0x26,0x2F,0x46, + 0x08,0x3F,0x0C,0x46,0x08,0x28,0x37,0xD0,0x0F,0xDC,0x01,0x28,0x1E,0xD0,0x02,0x28, + 0x27,0xD0,0x04,0x28,0x19,0xD1,0xFA,0xF7,0x7F,0xF8,0xAC,0x60,0xBE,0x70,0x03,0x21, + 0x04,0x20,0xFA,0xF7,0x91,0xF8,0x04,0x20,0x0D,0xE0,0x10,0x28,0x2F,0xD0,0x20,0x28, + 0x0B,0xD1,0x01,0x20,0xFA,0xF7,0x70,0xF8,0x6C,0x61,0x7E,0x71,0x00,0x21,0x01,0x20, + 0xFA,0xF7,0x82,0xF8,0x01,0x20,0xFA,0xF7,0x73,0xF8,0xF8,0xBD,0x02,0x20,0xFA,0xF7, + 0x63,0xF8,0x2C,0x60,0x3E,0x70,0x01,0x21,0x02,0x20,0xFA,0xF7,0x75,0xF8,0x02,0x20, + 0xF1,0xE7,0x03,0x20,0xFA,0xF7,0x58,0xF8,0x6C,0x60,0x7E,0x70,0x00,0x21,0x03,0x20, + 0xFA,0xF7,0x6A,0xF8,0x03,0x20,0xE6,0xE7,0x05,0x20,0xFA,0xF7,0x4D,0xF8,0xEC,0x60, + 0xFE,0x70,0x02,0x21,0x05,0x20,0xFA,0xF7,0x5F,0xF8,0x05,0x20,0xDB,0xE7,0x06,0x20, + 0xFA,0xF7,0x42,0xF8,0x2C,0x61,0x3E,0x71,0x02,0x21,0x06,0x20,0xFA,0xF7,0x54,0xF8, + 0x06,0x20,0xD0,0xE7,0x50,0x20,0x00,0x20,0x70,0xB5,0x12,0x4D,0x28,0x7C,0x00,0x28, + 0x0E,0xD1,0x2C,0x46,0x20,0x34,0xA0,0x7B,0x00,0x28,0x09,0xD1,0xFE,0xF7,0x16,0xFA, + 0xE1,0x78,0x00,0x29,0x05,0xD0,0x00,0x28,0x05,0xD1,0xA8,0x7D,0x40,0x1C,0xA8,0x75, + 0x70,0xBD,0x00,0x28,0xFC,0xD0,0xFF,0xF7,0xAD,0xFC,0x00,0xF0,0x10,0xF8,0x00,0x28, + 0xF6,0xD0,0xFF,0xF7,0xFD,0xFE,0x00,0x28,0x01,0xD0,0xFF,0x20,0x60,0x72,0x00,0xF0, + 0x03,0xF8,0x70,0xBD,0x98,0x04,0x00,0x20,0x70,0x47,0x70,0x47,0x70,0x47,0x01,0x20, + 0x70,0x47,0x70,0x47,0xF0,0xB5,0x96,0x46,0x9C,0x46,0x00,0x24,0x13,0xE0,0x65,0x00, + 0x42,0x5B,0x7D,0x23,0xDB,0x00,0xD2,0x1A,0x96,0xB2,0x46,0x53,0x62,0x46,0x17,0x5D, + 0xCB,0x1A,0xBA,0x06,0x92,0x0E,0x5A,0x43,0x7B,0x06,0x01,0xD5,0xB2,0x1A,0x00,0xE0, + 0xB2,0x18,0x42,0x53,0x64,0x1C,0x74,0x45,0xE9,0xD3,0xF0,0xBD,0x10,0xB5,0x04,0x78, + 0xCB,0xB2,0x8C,0x42,0x00,0xDD,0x03,0x70,0x84,0x78,0x8C,0x42,0x00,0xDA,0x83,0x70, + 0x43,0x78,0xD1,0xB2,0x93,0x42,0x00,0xDD,0x41,0x70,0xC3,0x78,0x93,0x42,0x00,0xDA, + 0xC1,0x70,0x10,0xBD,0x70,0xB5,0x0A,0x4C,0x65,0x78,0x26,0x78,0x28,0x46,0x70,0x43, + 0x42,0x00,0x21,0x6A,0x20,0x6D,0xF9,0xF7,0x77,0xFF,0x6A,0x00,0x21,0x6B,0x60,0x6D, + 0xF9,0xF7,0x72,0xFF,0x72,0x00,0x21,0x6C,0xA0,0x6D,0xF9,0xF7,0x6D,0xFF,0x70,0xBD, + 0xAC,0x03,0x00,0x20,0xF0,0xB5,0x2B,0x4C,0x06,0x46,0x27,0x46,0x20,0x3F,0x38,0x46, + 0x61,0x7D,0x08,0x30,0x85,0xB0,0x28,0x4D,0x03,0x90,0x00,0x29,0x28,0xD0,0x28,0x46, + 0x20,0x38,0x01,0x7F,0x25,0x48,0x00,0x68,0xFF,0x30,0x41,0x30,0x00,0x7C,0x81,0x42, + 0x1E,0xD1,0x00,0x2E,0x02,0xD0,0xFC,0xF7,0x75,0xF8,0x19,0xE0,0x20,0x48,0x21,0x4B, + 0x41,0x6C,0xD8,0x6A,0x00,0x22,0x02,0x92,0x01,0x91,0x00,0x90,0x19,0x4A,0x1B,0x6A, + 0x20,0x3A,0x1C,0x48,0x03,0x99,0xFC,0xF7,0x43,0xFA,0x17,0x48,0x21,0x7D,0x20,0x38, + 0x42,0x7D,0xB8,0x78,0xFC,0xF7,0xC8,0xFD,0xA1,0x7D,0x00,0x29,0x00,0xD0,0x68,0x71, + 0x12,0x48,0x00,0x68,0x80,0x30,0x00,0x7D,0xFC,0xF7,0x62,0xFB,0x10,0x48,0x11,0x4B, + 0x41,0x6C,0xD8,0x6A,0x6A,0x46,0x43,0xC2,0x0A,0x4A,0x1B,0x6A,0x20,0x3A,0x0D,0x48, + 0x03,0x99,0xFC,0xF7,0x25,0xFA,0x69,0x79,0x38,0x7A,0x08,0x22,0x00,0x23,0xFC,0xF7, + 0x77,0xF9,0x00,0x20,0xFC,0xF7,0x10,0xFB,0x00,0x2E,0x01,0xD0,0xFC,0xF7,0x0C,0xFC, + 0x05,0xB0,0xF0,0xBD,0xF6,0x04,0x00,0x20,0xB8,0x04,0x00,0x20,0x10,0x06,0x00,0x20, + 0x60,0x03,0x00,0x20,0xAC,0x03,0x00,0x20,0x70,0xB5,0x48,0x79,0x0C,0x46,0xFF,0x28, + 0x17,0xD1,0xD0,0x78,0x00,0x09,0x0F,0xD0,0x0D,0x46,0x40,0x35,0x00,0x21,0x69,0x5E, + 0xA0,0x6B,0x4A,0x00,0x21,0x6B,0xF9,0xF7,0xF7,0xFE,0x18,0x20,0x28,0x5E,0xA1,0x6C, + 0x42,0x00,0x20,0x6D,0xF9,0xF7,0xF0,0xFE,0x00,0x20,0x60,0x71,0x20,0x72,0x64,0x20, + 0xE0,0x71,0x70,0xBD,0x70,0xB5,0x04,0x46,0xD0,0x78,0x0D,0x46,0x00,0x09,0x33,0xD0, + 0x90,0x68,0xC0,0x07,0x22,0x48,0x20,0x56,0x0C,0xD0,0x42,0x00,0x61,0x68,0xA8,0x6B, + 0xF9,0xF7,0xDA,0xFE,0x14,0x20,0x20,0x56,0xA1,0x68,0x42,0x00,0x28,0x6D,0xF9,0xF7, + 0xD3,0xFE,0x21,0xE0,0x42,0x00,0x61,0x68,0x28,0x69,0xF9,0xF7,0xCD,0xFE,0x14,0x20, + 0x20,0x56,0xA1,0x68,0x42,0x00,0x68,0x69,0xF9,0xF7,0xC6,0xFE,0x15,0x20,0x20,0x56, + 0xA9,0x6B,0x42,0x00,0x60,0x68,0xF9,0xF7,0xBF,0xFE,0x14,0x20,0x20,0x56,0x29,0x6D, + 0x42,0x00,0xA0,0x68,0xF9,0xF7,0xB8,0xFE,0x29,0x69,0xA8,0x6B,0xA9,0x63,0x28,0x61, + 0x69,0x69,0x28,0x6D,0x29,0x65,0x68,0x61,0x00,0x24,0x03,0xE0,0x01,0x2C,0x0B,0xD0, + 0x02,0x2C,0x09,0xD0,0x18,0x20,0x60,0x43,0x40,0x19,0x28,0x21,0x41,0x5E,0x4A,0x00, + 0x81,0x69,0x00,0x6A,0xF9,0xF7,0xA0,0xFE,0x64,0x1C,0x05,0x2C,0xEE,0xDB,0x70,0xBD, + 0x15,0x00,0x00,0x00,0xF7,0xB5,0x00,0x20,0x82,0xB0,0x1F,0x4E,0x07,0x46,0x05,0x46, + 0x01,0x90,0x03,0x98,0x80,0x28,0x03,0xD1,0x01,0x21,0x02,0x98,0xFB,0xF7,0x98,0xFC, + 0x00,0x20,0x69,0x46,0x01,0xE0,0x08,0x88,0x40,0x1C,0x08,0x80,0x08,0x88,0x26,0x28, + 0xF9,0xD3,0x04,0x20,0xFB,0xF7,0xB0,0xFA,0x14,0x49,0x03,0x98,0x08,0x43,0x14,0x49, + 0x08,0x80,0x00,0x22,0x20,0x21,0x04,0x20,0x00,0xF0,0x98,0xFC,0x04,0x98,0x04,0x88, + 0x01,0x98,0x00,0x19,0x01,0x90,0x03,0x98,0x80,0x28,0x03,0xD1,0x08,0x21,0x02,0x98, + 0xFB,0xF7,0x76,0xFC,0xA7,0x42,0x00,0xD2,0x27,0x46,0xA6,0x42,0x00,0xD9,0x26,0x46, + 0x6D,0x1C,0xAD,0xB2,0x06,0x2D,0xCC,0xD3,0x01,0x98,0xB9,0x19,0x40,0x1A,0x80,0x03, + 0x00,0x0C,0x05,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0xFF,0x00,0x00,0x63,0x04,0x00,0x00, + 0x00,0x10,0x00,0x40,0x10,0xB5,0x04,0x48,0xC0,0x68,0x80,0x47,0x02,0x49,0x01,0x20, + 0x08,0x39,0xC8,0x70,0x10,0xBD,0x00,0x00,0x50,0x20,0x00,0x20,0xF7,0xB5,0x84,0xB0, + 0x04,0x98,0x04,0x9E,0x0C,0x30,0x01,0x90,0x04,0x98,0x04,0x9F,0x18,0x30,0x04,0x9D, + 0x14,0x46,0x02,0x90,0x24,0x36,0x3C,0x37,0x54,0x35,0xFF,0x22,0x0C,0x21,0x04,0x98, + 0xF9,0xF7,0x52,0xFE,0x30,0x21,0x30,0x46,0xF9,0xF7,0x55,0xFE,0x00,0x21,0x15,0xE0, + 0x0A,0x46,0x62,0x43,0x00,0x20,0x96,0x46,0x4A,0x00,0x94,0x46,0x0B,0xE0,0x72,0x46, + 0x13,0x18,0x05,0x9A,0x5B,0x00,0xD2,0x5A,0x63,0x46,0xF3,0x5E,0x93,0x42,0x01,0xDA, + 0x63,0x46,0xF2,0x52,0x40,0x1C,0xA0,0x42,0xF1,0xD3,0x49,0x1C,0xA1,0x42,0xE7,0xD3, + 0x00,0x20,0x44,0xE0,0x00,0x20,0x03,0xE0,0x42,0x00,0x23,0x49,0xA9,0x52,0x40,0x1C, + 0xA0,0x42,0xF9,0xD3,0x60,0x00,0x03,0x90,0x34,0xE0,0x18,0x21,0x01,0x98,0xF9,0xF7, + 0x2A,0xFE,0x23,0x46,0x05,0x9A,0x04,0x99,0x00,0x98,0xFD,0xF7,0x75,0xFD,0x00,0x28, + 0x2B,0xD1,0x19,0x49,0x09,0xE0,0x02,0x9A,0x12,0x5C,0x00,0x2A,0x04,0xD1,0x42,0x00, + 0xAA,0x5E,0x8A,0x42,0x00,0xDA,0x11,0x46,0x40,0x1C,0xA0,0x42,0xF3,0xD3,0x00,0x20, + 0x15,0xE0,0x01,0x9A,0x12,0x5C,0x00,0x2A,0x03,0xD0,0x42,0x00,0xB3,0x5A,0x5B,0x1A, + 0xB3,0x52,0x02,0x9A,0x12,0x5C,0x00,0x2A,0x04,0xD0,0x42,0x00,0xBB,0x5A,0x5B,0x18, + 0xBB,0x52,0x03,0xE0,0x42,0x00,0xAB,0x5A,0x5B,0x1A,0xAB,0x52,0x40,0x1C,0xA0,0x42, + 0xE7,0xD3,0x03,0x98,0x40,0x1E,0x03,0x90,0xC7,0xD2,0x00,0x98,0x40,0x1C,0x00,0x90, + 0xA0,0x42,0xB7,0xD3,0x07,0xB0,0xF0,0xBD,0xFF,0x7F,0x00,0x00,0x10,0xB5,0x04,0x48, + 0x00,0x68,0x80,0x47,0x02,0x49,0x01,0x20,0x08,0x39,0x08,0x70,0x10,0xBD,0x00,0x00, + 0x50,0x20,0x00,0x20,0x00,0x21,0x82,0x0F,0x00,0xD1,0x80,0x00,0x01,0x22,0xD2,0x03, + 0x53,0x00,0x98,0x42,0x00,0xD2,0x80,0x22,0x11,0x43,0x0B,0x46,0x4B,0x43,0x83,0x42, + 0x00,0xD9,0x51,0x40,0x52,0x08,0xF7,0xD1,0x80,0x0F,0x01,0xD1,0x49,0x1C,0x49,0x08, + 0x88,0xB2,0x70,0x47,0xF3,0xB5,0xFF,0x20,0x45,0x30,0x83,0xB0,0x40,0x58,0x0D,0x46, + 0x00,0x90,0x01,0x68,0x00,0x29,0x08,0xD0,0x14,0x22,0x03,0x99,0x00,0x24,0x8A,0x56, + 0x2E,0x46,0x20,0x36,0x01,0x92,0x02,0x90,0x1B,0xE0,0x00,0x20,0x05,0xB0,0xF0,0xBD, + 0x02,0x98,0x54,0x22,0xC0,0x30,0x01,0x69,0x20,0x46,0x50,0x43,0x02,0x46,0x10,0x32, + 0x8A,0x5C,0x13,0x09,0x0C,0xD0,0x13,0x07,0xF7,0x78,0x1B,0x0F,0xBB,0x42,0x03,0xD9, + 0x33,0x79,0x12,0x09,0x9A,0x42,0x03,0xD9,0x08,0x18,0x54,0x21,0xF9,0xF7,0x9B,0xFD, + 0x64,0x1C,0xA8,0x78,0xA0,0x42,0xE3,0xD8,0x79,0x20,0x40,0x5D,0xFF,0x28,0x05,0xD0, + 0x01,0x23,0x00,0x22,0x29,0x46,0x03,0x98,0xFF,0xF7,0xDA,0xF9,0x00,0x98,0x29,0x46, + 0x02,0x68,0x03,0x98,0x90,0x47,0xAC,0x7C,0x20,0x2C,0xCF,0xD0,0xE9,0x78,0x09,0x09, + 0xCC,0xD0,0x00,0x21,0x07,0xE0,0x03,0x9A,0x4B,0x00,0x92,0x68,0xD5,0x5E,0x65,0x43, + 0x6D,0x11,0xD5,0x52,0x49,0x1C,0x01,0x9A,0x91,0x42,0xF4,0xDB,0xBE,0xE7,0xF3,0xB5, + 0x08,0x46,0xFF,0x30,0x85,0xB0,0x41,0x30,0x02,0x90,0x45,0x68,0x01,0x91,0x8C,0x78, + 0x0E,0x46,0xA4,0x1C,0xFE,0xF7,0x2A,0xFF,0x24,0x01,0x00,0x90,0x20,0x46,0xFE,0xF7, + 0x43,0xFF,0x21,0x46,0x00,0x98,0xF9,0xF7,0x5E,0xFD,0x01,0x9C,0x00,0x20,0x40,0x34, + 0x20,0x72,0x02,0x23,0x31,0x46,0x00,0x9A,0x05,0x98,0xFF,0xF7,0xA1,0xF9,0x20,0x7A, + 0x00,0x27,0x00,0x28,0x0C,0xD1,0x20,0x7C,0x00,0x28,0x09,0xD0,0x6B,0x68,0x00,0x2B, + 0x06,0xD0,0x29,0x46,0x00,0x9A,0x05,0x98,0x98,0x47,0x07,0x1E,0x00,0xDD,0x27,0x72, + 0x60,0x7B,0x0A,0x28,0x01,0xD3,0x01,0x20,0xA0,0x74,0xA0,0x7F,0x00,0x28,0x01,0xD0, + 0x00,0x20,0x20,0x72,0x03,0x23,0x31,0x46,0x00,0x9A,0x05,0x98,0xFF,0xF7,0x80,0xF9, + 0x05,0x98,0x40,0x8A,0xA0,0x75,0xAB,0x68,0x00,0x2B,0x03,0xD0,0x22,0x7A,0x28,0x46, + 0x00,0x99,0x98,0x47,0xEA,0x68,0x00,0x2A,0x03,0xD0,0xD0,0x20,0x40,0x59,0x01,0x99, + 0x90,0x47,0x28,0x46,0xC0,0x30,0x03,0x90,0x01,0x69,0x01,0x98,0xF9,0xF7,0x06,0xFF, + 0x01,0x99,0x00,0x26,0x20,0x31,0x8C,0x46,0x01,0x99,0x30,0x46,0x8B,0x78,0x0D,0xE0, + 0x03,0x99,0x54,0x22,0x09,0x69,0x42,0x43,0x10,0x32,0x89,0x5C,0x62,0x46,0x09,0x07, + 0xD2,0x78,0x09,0x0F,0x91,0x42,0x00,0xD9,0x76,0x1C,0x40,0x1C,0x83,0x42,0xEF,0xDC, + 0x66,0x72,0x00,0x98,0xFE,0xF7,0x00,0xFF,0x29,0x69,0x00,0x29,0x02,0xD0,0x02,0x98, + 0x40,0x68,0x88,0x47,0x00,0x2F,0x02,0xDA,0x38,0x46,0x07,0xB0,0xF0,0xBD,0x30,0x46, + 0xFB,0xE7,0x70,0xB5,0xFF,0x30,0x41,0x30,0x40,0x68,0x0C,0x46,0xC0,0x30,0x85,0x68, + 0x00,0x20,0x60,0x34,0x20,0x76,0x0C,0xE0,0x06,0x22,0x42,0x43,0x52,0x19,0x96,0x8A, + 0x43,0x00,0xCE,0x52,0xD2,0x8A,0x5B,0x18,0x9A,0x87,0x22,0x7E,0x52,0x1C,0x22,0x76, + 0x40,0x1C,0x2A,0x78,0x82,0x42,0xEF,0xDC,0x70,0xBD,0xF0,0xB5,0xC0,0x30,0x00,0x27, + 0x46,0x69,0x04,0x69,0x85,0xB0,0x0D,0x46,0x38,0x46,0x6A,0xE0,0x20,0x7C,0x01,0x07, + 0x30,0x46,0x20,0x30,0x03,0x90,0xC0,0x78,0x09,0x0F,0x81,0x42,0x01,0xD8,0x54,0x34, + 0x5D,0xE0,0x60,0x7C,0x01,0xAB,0x40,0x06,0x40,0x0E,0x28,0x70,0x00,0x93,0x20,0x46, + 0x33,0x46,0x01,0x22,0x21,0x46,0x20,0x30,0xF9,0xF7,0xC4,0xFE,0x01,0x98,0xE8,0x60, + 0x01,0xAB,0x00,0x93,0x33,0x46,0x00,0x22,0x21,0x46,0x20,0x46,0xF9,0xF7,0xBA,0xFE, + 0x01,0x98,0xA8,0x60,0x60,0x68,0x68,0x61,0x20,0x7C,0x01,0x09,0x03,0x98,0x00,0x79, + 0x81,0x42,0x68,0x78,0x03,0xD8,0x80,0x09,0x80,0x01,0x40,0x1C,0x01,0xE0,0x80,0x09, + 0x80,0x01,0x68,0x70,0xE0,0x7C,0xFF,0x28,0x01,0xD2,0x40,0x1C,0xE0,0x74,0xA8,0x70, + 0x20,0x7C,0x00,0x09,0x68,0x78,0x12,0xD0,0x40,0x06,0x40,0x0E,0x68,0x70,0x61,0x7B, + 0xE9,0x80,0xE1,0x7A,0xE9,0x70,0xBF,0x21,0x08,0x40,0x21,0x7B,0x89,0x07,0xC9,0x0F, + 0x89,0x01,0x08,0x43,0x68,0x70,0x20,0x7C,0x00,0x09,0x03,0xD0,0x11,0xE0,0x80,0x21, + 0x08,0x43,0xEB,0xE7,0x01,0xAB,0x00,0x93,0x20,0x46,0x33,0x46,0x02,0x22,0x21,0x46, + 0x40,0x30,0xF9,0xF7,0x7F,0xFE,0x01,0x98,0x28,0x61,0x60,0x7A,0x68,0x71,0x20,0x7A, + 0x28,0x71,0xB0,0x78,0x7F,0x1C,0x18,0x35,0x54,0x34,0xB8,0x42,0x05,0xD0,0x02,0x98, + 0x40,0x1C,0x02,0x90,0xB1,0x78,0x81,0x42,0x90,0xDC,0x38,0x46,0x05,0xB0,0xF0,0xBD, + 0xFF,0xB5,0x06,0x46,0xFF,0x30,0x37,0x46,0x21,0x30,0xFF,0x37,0xC1,0x8B,0x41,0x37, + 0x83,0xB0,0x38,0x68,0xFE,0xF7,0x64,0xFE,0xF0,0x1D,0x03,0x21,0xF9,0x30,0x01,0x75, + 0x41,0x75,0x31,0x46,0x4E,0x4A,0x0C,0x31,0x3C,0x23,0x00,0x20,0x0C,0x5C,0xFF,0x2C, + 0x01,0xD1,0x14,0x5C,0x0C,0x54,0x40,0x1C,0x98,0x42,0xF7,0xDB,0x34,0x46,0x48,0x34, + 0x2A,0x21,0x20,0x46,0xF9,0xF7,0x37,0xFC,0xB0,0x88,0xF1,0x88,0x40,0x43,0x49,0x43, + 0x40,0x18,0xFF,0xF7,0x4F,0xFE,0x35,0x46,0x20,0x35,0x69,0x79,0x48,0x43,0x64,0x21, + 0xF9,0xF7,0xD8,0xFB,0x20,0x85,0x68,0x78,0x64,0x21,0xC0,0x01,0xF9,0xF7,0xD2,0xFB, + 0x20,0x73,0xA8,0x79,0x64,0x21,0xC0,0x01,0xF9,0xF7,0xCC,0xFB,0x60,0x73,0x01,0x20, + 0xA0,0x72,0x0A,0x20,0x20,0x72,0xFE,0x20,0xE0,0x72,0x64,0x21,0x7B,0x20,0x81,0x55, + 0xFE,0xF7,0xD4,0xFD,0xD8,0x21,0x45,0x18,0x04,0x46,0x78,0x60,0xF9,0xF7,0x0B,0xFC, + 0x21,0x46,0xC0,0x31,0x0D,0x61,0xB0,0x78,0x54,0x22,0x50,0x43,0xC0,0x1C,0x87,0x08, + 0x4E,0x61,0xBC,0x20,0x06,0x99,0x01,0x51,0x30,0x46,0xBF,0x00,0xFF,0x30,0xD8,0x37, + 0x17,0x30,0x06,0x22,0x27,0xA1,0xF9,0xF7,0xCF,0xFB,0x35,0x46,0xFF,0x35,0x1C,0x35, + 0x28,0x78,0x00,0x28,0x01,0xD1,0x2D,0x20,0x28,0x70,0x6D,0x1C,0x38,0x46,0xFE,0xF7, + 0xCB,0xFD,0x00,0x20,0x07,0x46,0x00,0x90,0x17,0xE0,0xF8,0x00,0x04,0x99,0x01,0x90, + 0x09,0x58,0x00,0x29,0x10,0xD0,0x30,0x46,0x88,0x47,0x04,0x99,0x01,0x98,0x00,0x9A, + 0x41,0x18,0x48,0x68,0x00,0x78,0x90,0x42,0x02,0xD0,0x00,0x90,0x28,0x70,0x6D,0x1C, + 0x48,0x68,0x40,0x78,0x28,0x70,0x6D,0x1C,0x7F,0x1C,0x05,0x98,0x87,0x42,0xE4,0xDB, + 0x00,0x20,0x28,0x70,0x02,0x46,0x51,0x1C,0xD0,0x00,0x03,0x19,0x10,0xE0,0xC8,0x00, + 0x00,0x19,0x9D,0x8A,0x86,0x8A,0xB5,0x42,0x09,0xD9,0x9E,0x69,0x5D,0x69,0xB4,0x46, + 0x87,0x69,0x46,0x69,0x9F,0x61,0x5E,0x61,0x66,0x46,0x86,0x61,0x45,0x61,0x49,0x1C, + 0x15,0x29,0xEC,0xDB,0x52,0x1C,0x15,0x2A,0xE5,0xDB,0x07,0xB0,0xF0,0xBD,0x00,0x00, + 0x08,0x6F,0x00,0x00,0x31,0x33,0x30,0x39,0x31,0x00,0x00,0x00,0xFF,0xB5,0xC0,0x30, + 0x8F,0xB0,0x47,0x69,0x04,0x69,0x12,0x98,0x0D,0x46,0x41,0x00,0x89,0x1C,0x01,0x26, + 0x0C,0x91,0x36,0x03,0x49,0x43,0x30,0x46,0xF9,0xF7,0x5A,0xFB,0x0D,0x90,0x12,0x99, + 0x30,0x46,0x49,0x1C,0xF9,0xF7,0x54,0xFB,0x0E,0x90,0x00,0x20,0x06,0x46,0x0B,0x90, + 0x79,0xE0,0x20,0x7C,0x39,0x46,0x20,0x31,0x00,0x07,0xCA,0x78,0x00,0x0F,0x90,0x42, + 0x01,0xD8,0x54,0x34,0x6E,0xE0,0x22,0x6A,0x03,0x92,0xE2,0x6A,0x04,0x92,0x22,0x6B, + 0x05,0x92,0x22,0x68,0x06,0x92,0x62,0x6A,0x07,0x92,0xA0,0x6A,0x08,0x90,0x06,0x98, + 0x90,0x42,0x0D,0xD0,0x04,0x9A,0x03,0x98,0x90,0x42,0x09,0xD0,0x68,0x78,0x80,0x06, + 0x06,0xD0,0x20,0x7C,0x02,0x07,0xC8,0x78,0x12,0x0F,0x80,0x1C,0x82,0x42,0x04,0xD2, + 0x20,0x6A,0x09,0x90,0x20,0x68,0x0A,0x90,0x2E,0xE0,0x11,0x98,0x00,0x90,0x00,0x20, + 0x01,0x90,0x0E,0x98,0x02,0x90,0x20,0x7C,0x02,0x07,0xC8,0x78,0x12,0x0F,0x80,0x1C, + 0x82,0x42,0x08,0xD9,0x11,0x99,0x12,0x98,0x40,0x1A,0x40,0x1C,0x00,0x90,0x0C,0x98, + 0x01,0x90,0x0D,0x98,0x02,0x90,0x00,0x22,0x69,0x46,0x03,0xA8,0xFA,0xF7,0x54,0xF9, + 0x69,0x46,0x88,0x84,0x01,0x22,0x03,0xA8,0xFA,0xF7,0x4E,0xF9,0x69,0x46,0xC8,0x84, + 0x00,0x22,0x06,0xA8,0xFA,0xF7,0x48,0xF9,0x69,0x46,0x08,0x85,0x01,0x22,0x06,0xA8, + 0xFA,0xF7,0x42,0xF9,0x69,0x46,0x48,0x85,0x09,0xAB,0x00,0x93,0x3B,0x46,0x01,0x22, + 0x21,0x46,0x09,0xA8,0xF9,0xF7,0x36,0xFD,0x0A,0xAB,0x00,0x93,0x3B,0x46,0x00,0x22, + 0x21,0x46,0x0A,0xA8,0xF9,0xF7,0x2E,0xFD,0x09,0x98,0xE8,0x60,0x0A,0x98,0xA8,0x60, + 0x68,0x78,0x54,0x34,0x80,0x09,0x80,0x01,0x40,0x1C,0x68,0x70,0x0B,0x98,0x40,0x1C, + 0x18,0x35,0x0B,0x90,0x76,0x1C,0xB8,0x78,0xB0,0x42,0x82,0xDC,0x0B,0x98,0x13,0xB0, + 0xF0,0xBD,0x00,0x00,0x30,0xB4,0x10,0x4B,0x58,0x88,0x58,0x80,0xEF,0xF3,0x08,0x82, + 0x0E,0x49,0x48,0x68,0x82,0x42,0x01,0xD8,0x0D,0x4A,0x02,0x60,0x0B,0x48,0x8A,0x7B, + 0x40,0x7C,0x00,0x2A,0x04,0xD1,0x0A,0x89,0x4C,0x89,0x42,0x43,0xA2,0x42,0x01,0xD2, + 0xA0,0x22,0x9A,0x80,0x40,0x1C,0x48,0x74,0x08,0x68,0x00,0x28,0x01,0xD0,0x30,0xBC, + 0x00,0x47,0x30,0xBC,0x70,0x47,0x00,0x00,0x00,0x02,0x00,0x40,0x68,0x20,0x00,0x20, + 0x78,0x56,0x34,0x12,0xFF,0xB5,0x83,0xB0,0x06,0x46,0x68,0x46,0x12,0x25,0x45,0x5F, + 0x14,0x24,0x18,0x22,0xAC,0x46,0x04,0x5F,0x82,0x5E,0x10,0x23,0x1A,0x21,0x16,0x25, + 0xC3,0x5E,0x41,0x5E,0x45,0x5F,0x94,0x42,0x08,0xD1,0x8D,0x42,0x00,0xD0,0x23,0x46, + 0x33,0x80,0x60,0x46,0x70,0x80,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x48,0x1B,0x12,0x1B, + 0x61,0x46,0xE7,0x1A,0x69,0x1A,0x47,0x43,0x51,0x43,0x79,0x1A,0x00,0x91,0x01,0x46, + 0x02,0x92,0x01,0x90,0x51,0x43,0x01,0x27,0x40,0x43,0x52,0x43,0x7F,0x04,0xB8,0x42, + 0x06,0xDC,0xBA,0x42,0x04,0xDC,0xB9,0x42,0x02,0xDC,0x7F,0x42,0xB9,0x42,0x04,0xDA, + 0xC0,0x1C,0xD2,0x1C,0x80,0x10,0x92,0x10,0x89,0x10,0x67,0x46,0x7F,0x1B,0x4F,0x43, + 0x21,0x46,0x41,0x43,0x7F,0x18,0x81,0x18,0x53,0x43,0x48,0x10,0x18,0x18,0x38,0x18, + 0xF9,0xF7,0x5E,0xFA,0x07,0x46,0x01,0x98,0x39,0x1B,0x48,0x43,0x02,0x99,0xF9,0xF7, + 0x57,0xFA,0x40,0x19,0x37,0x80,0x70,0x80,0x00,0x98,0xC5,0xE7,0xC3,0x6A,0x03,0x63, + 0x03,0x6A,0xC3,0x62,0x12,0x68,0x42,0x63,0x41,0x7C,0xC9,0x09,0x01,0xD0,0x83,0x63, + 0x70,0x47,0x02,0x62,0x70,0x47,0xF7,0xB5,0x04,0x46,0x00,0x78,0x00,0x27,0x00,0x28, + 0x10,0xD0,0x06,0x21,0x48,0x43,0x00,0x19,0x10,0x23,0x0E,0x22,0xC3,0x5E,0x82,0x5E, + 0x02,0x98,0x01,0xB2,0x01,0x98,0x00,0xB2,0xFE,0xF7,0x15,0xFF,0x07,0x46,0x20,0x78, + 0x1E,0x28,0x03,0xD2,0x20,0x78,0x40,0x1C,0x20,0x70,0x2C,0xE0,0xE0,0x8B,0xA1,0x8C, + 0x01,0x26,0x42,0x18,0x02,0x25,0x06,0x20,0x68,0x43,0x01,0x19,0x08,0x8B,0xC9,0x8B, + 0x40,0x18,0x90,0x42,0x01,0xDA,0x02,0x46,0x2E,0x46,0x6D,0x1C,0x1D,0x2D,0xF2,0xDB, + 0x06,0x20,0x70,0x43,0x05,0x19,0x1C,0x23,0x1A,0x22,0x10,0x21,0x0E,0x20,0xEB,0x5E, + 0xAA,0x5E,0x69,0x5E,0x28,0x5E,0xFE,0xF7,0xEE,0xFE,0xE8,0x83,0x09,0xE0,0x06,0x20, + 0x70,0x43,0x00,0x19,0x01,0x46,0x1A,0x31,0x14,0x30,0x06,0x22,0xF9,0xF7,0x14,0xFA, + 0x76,0x1C,0x1D,0x2E,0xF3,0xDB,0x21,0x78,0x06,0x22,0x51,0x43,0x09,0x19,0x01,0x98, + 0xC8,0x81,0x21,0x78,0x02,0x98,0x51,0x43,0x09,0x19,0x08,0x82,0x20,0x78,0x50,0x43, + 0x00,0x19,0x47,0x82,0x00,0x20,0xFE,0xBD,0x70,0xB5,0x64,0x21,0x48,0x43,0x06,0x46, + 0x00,0x24,0x0D,0x4D,0x0C,0xE0,0xFF,0xF7,0x44,0xFA,0xA8,0x78,0x00,0x28,0x10,0xD1, + 0x01,0x20,0xFB,0xF7,0x2F,0xFF,0x00,0x21,0x0B,0x20,0xFB,0xF7,0x59,0xFF,0x64,0x1C, + 0xB4,0x42,0xF0,0xD3,0xA8,0x78,0x00,0x28,0x03,0xD1,0x01,0x20,0xA8,0x70,0x00,0x20, + 0x70,0xBD,0x01,0x20,0x70,0xBD,0x00,0x00,0xB8,0x04,0x00,0x20,0xF0,0xB5,0x00,0x24, + 0x1B,0x4F,0x1C,0x4E,0x04,0x25,0x3B,0x78,0x00,0x2B,0x01,0xD0,0x01,0x23,0x1C,0x43, + 0x7B,0x79,0x00,0x2B,0x01,0xD0,0x20,0x23,0x1C,0x43,0x7B,0x78,0x00,0x2B,0x01,0xD0, + 0x02,0x23,0x1C,0x43,0xFB,0x78,0x00,0x2B,0x01,0xD0,0x08,0x23,0x1C,0x43,0xBB,0x78, + 0x00,0x2B,0x00,0xD0,0x2C,0x43,0x3B,0x79,0x00,0x2B,0x01,0xD0,0x10,0x23,0x1C,0x43, + 0x23,0x46,0x03,0x42,0x0D,0xD1,0x20,0x29,0xDD,0xD0,0x22,0x29,0x02,0xD1,0x33,0x69, + 0x2B,0x43,0x33,0x61,0x30,0xBF,0x22,0x29,0xD5,0xD1,0x33,0x69,0xAB,0x43,0x33,0x61, + 0xD1,0xE7,0x00,0x2A,0x01,0xD0,0xFA,0xF7,0xD7,0xFD,0x20,0x46,0xF0,0xBD,0x00,0x00, + 0x48,0x20,0x00,0x20,0x00,0xED,0x00,0xE0,0x00,0x00,0x00,0x00,0x41,0x5F,0x00,0x00, + 0x69,0x5E,0x00,0x00,0xD9,0x5E,0x00,0x00,0x9D,0x5B,0x00,0x00,0xA1,0x5B,0x00,0x00, + 0x97,0x5B,0x00,0x00,0x99,0x5B,0x00,0x00,0xAC,0xCA,0xFF,0xFF,0x32,0x33,0x34,0x35, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0xFF,0xFF,0xFF,0xFF,0xFF,0x75,0x51,0x52, + 0x53,0x54,0x55,0x56,0x57,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x03,0x04,0x05,0x06,0x07,0xFF,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x89,0x09,0x00,0x00,0x47,0x6F,0x00,0x00,0xF9,0x16,0x00,0x00, + 0x4A,0x6F,0x00,0x00,0x59,0x4F,0x00,0x00,0x44,0x6F,0x00,0x00,0xB5,0x3F,0x00,0x00, + 0x50,0x6F,0x00,0x00,0x25,0x5A,0x00,0x00,0x53,0x6F,0x00,0x00,0x49,0x44,0x00,0x00, + 0x4D,0x6F,0x00,0x00,0x48,0x59,0x4E,0x43,0x53,0x54,0x01,0x02,0x04,0x08,0x00,0x04, + 0x02,0x01,0x03,0x06,0x0C,0x12,0x18,0x1E,0x24,0x2A,0x06,0x0C,0x12,0x18,0x1E,0x24, + 0x30,0x3C,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0x01, + 0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0xFF,0xFF,0x01,0x01,0x01, + 0xFF,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF,0xFF, + 0xFF,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01, + 0x01,0x01,0xFF,0xFF,0x82,0x00,0x00,0x82,0x00,0x00,0x02,0x82,0x01,0x81,0x01,0x01, + 0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x81,0x81,0x01,0x01,0x01, + 0x81,0x81,0x01,0x01,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x02,0x02,0x02,0x00,0x00, + 0x00,0x02,0x00,0x02,0x81,0x81,0x81,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02, + 0x02,0x02,0x82,0x02,0xFF,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF,0x01, + 0x01,0x01,0x01,0xFF,0x81,0x01,0x01,0x01,0x01,0x81,0x01,0x01,0x01,0x01,0x81,0x01, + 0x01,0x01,0x01,0x81,0x3B,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14,0x05,0x0A,0x20,0x28, + 0x28,0x28,0x19,0x1E,0x2A,0x11,0x64,0x64,0x0A,0x08,0x0F,0x5A,0x28,0x64,0x64,0x01, + 0x01,0x05,0x32,0x01,0x28,0x14,0x46,0x28,0x32,0x96,0x03,0x5A,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4D,0x30,0x00,0x42,0x31,0x00,0x43,0x31,0x00,0x47,0x31,0x00, + 0x46,0x32,0x00,0x70,0x34,0x00,0x00,0x00,0x68,0x6F,0x00,0x00,0x00,0x00,0x00,0x20, + 0x98,0x21,0x00,0x00,0x32,0x02,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0xA8,0x9F,0xB0, + 0x0C,0x22,0xCA,0xCA,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x2A,0xCB,0xCB, + 0x00,0x00,0x00,0x00,0xA5,0xA5,0xCA,0xCA,0x00,0xD0,0x05,0x00,0x00,0x05,0x20,0x03, + 0x00,0x01,0x01,0x01,0x20,0x10,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x12,0x1E,0x00,0x00,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x02, + 0x03,0x04,0x05,0x06,0x07,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,0x22,0x21,0x20,0x1F,0x1E,0x1D,0x1C,0x1B, + 0x1A,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x0D,0x0C,0x0B,0x0A,0x09,0x43,0x42,0x41, + 0x40,0x3F,0x3E,0x3D,0x3C,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x31,0x39,0x40,0x00,0x00,0x00,0x00,0x00,0x2B,0x00,0x00,0x00,0x0A,0x1E,0x1E,0x14, + 0x05,0x0A,0x20,0x1E,0x3C,0x14,0x19,0x1E,0x2D,0x33,0x32,0x32,0x06,0x08,0x0F,0x5A, + 0x28,0x1E,0x64,0x01,0x01,0x0A,0x01,0x05,0x28,0x0A,0x4D,0x14,0x32,0x96,0x03,0x5A, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x80, + 0x0C,0x3C,0x08,0x00,0x90,0x01,0x00,0x00,0x00,0x58,0x02,0x03,0x02,0x31,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x01,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x4D,0x00,0x11,0x01,0x11,0x00,0x00,0x64,0x00,0x02,0x01,0x01,0x30,0x00,0x00, + 0x1E,0x50,0xB0,0x28,0x03,0x03,0x28,0x14,0x50,0xB0,0x28,0x03,0x03,0x32,0x14,0x28, + 0xD8,0x28,0x03,0x03,0x32,0x00,0x00,0x00,0xF4,0x01,0x01,0x00,0x00,0x00,0x00,0x00, + 0x01,0x20,0x0F,0x08,0x02,0x02,0x00,0x00,0x20,0x01,0x00,0x03,0x05,0x01,0x06,0x07, + 0x03,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x03,0x04,0x01,0x03,0x06,0x00, + 0x03,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0xC8,0x00,0x00,0x01,0x20,0x01,0x03,0x50, + 0x28,0x32,0xC8,0x00,0x08,0x01,0x01,0x10,0x04,0x03,0x11,0x1C,0x2D,0x36,0x14,0x23, + 0x30,0x38,0x18,0x28,0x33,0x3C,0x0F,0x13,0x21,0x0F,0x17,0x28,0x0F,0x1C,0x30,0x0F, + 0x13,0x0F,0x17,0x0F,0x1C,0xC8,0x06,0x08,0x78,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0x1A,0xCE,0x59, + 0x00,0x00,0x04,0x03,0x68,0x65,0x6C,0x6C,0x6F,0x20,0x68,0x79,0x6E,0x21,0x21,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xA3,0xF9,0xE8, + 0x3A,0xCE,0xCE,0xE6, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst7xx_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst7xx_fw.h new file mode 100644 index 000000000000..fba39507880d --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst7xx_fw.h @@ -0,0 +1,984 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst7xx_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { +0x00, 0x00, 0x00, 0x3c, 0x0b, 0x04, +0x02, 0x05, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x35, 0xee, 0x41, 0x04, 0x40, 0x00, 0x00, 0x00, 0x02, +0x34, 0xaf, 0xee, 0x30, 0xe7, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0x00, 0x00, +0x00, 0x02, 0x0a, 0xe2, 0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, +0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, +0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, +0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, +0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, +0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, +0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, +0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, +0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, +0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, +0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, +0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, +0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, +0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, +0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, +0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x00, 0x74, 0x73, 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, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, +0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, +0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, +0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, +0xf3, 0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, +0xa4, 0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, +0xf0, 0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, +0xfc, 0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, +0xce, 0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, +0xf0, 0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, +0x22, 0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xc2, 0xd5, 0xec, 0x30, 0xe7, 0x09, 0xb2, +0xd5, 0xe4, 0xc3, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0xee, 0x30, 0xe7, 0x15, 0xb2, 0xd5, 0xe4, 0xc3, +0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x12, 0x01, 0x84, 0xc3, 0xe4, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x80, +0x03, 0x12, 0x01, 0x84, 0x30, 0xd5, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0xc5, +0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xe0, 0x38, 0xf0, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, +0xe0, 0x22, 0x50, 0x06, 0x87, 0xf0, 0x09, 0xe7, 0x19, 0x22, 0xbb, 0xfe, 0x07, 0xe3, 0xf5, 0xf0, +0x09, 0xe3, 0x19, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xf5, 0xf0, 0x74, 0x01, 0x93, 0x22, +0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, +0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, +0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, +0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, +0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, +0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, +0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, +0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, +0xf0, 0x08, 0xf2, 0x22, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xed, 0x39, 0xfd, 0xec, 0x38, 0xfc, +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, 0xef, 0x4b, +0xff, 0xee, 0x4a, 0xfe, 0xed, 0x49, 0xfd, 0xec, 0x48, 0xfc, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, +0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xec, 0x64, 0x80, 0xc8, 0x64, 0x80, 0x98, 0x45, 0xf0, +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, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x08, 0xe6, 0xfe, +0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, +0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0x22, 0xd0, 0x83, 0xd0, +0x82, 0xe4, 0x93, 0xf6, 0x08, 0x74, 0x01, 0x93, 0xf6, 0x08, 0x74, 0x02, 0x93, 0xf6, 0x08, 0x74, +0x03, 0x93, 0xf6, 0x74, 0x04, 0x73, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, +0x83, 0x22, 0xfa, 0xe6, 0xfb, 0x08, 0x08, 0xe6, 0xf9, 0x25, 0xf0, 0xf6, 0x18, 0xe6, 0xca, 0x3a, +0xf6, 0x22, 0xec, 0x8e, 0xf0, 0xa4, 0xcc, 0xc5, 0xf0, 0xcc, 0xcd, 0xf8, 0xef, 0xa4, 0xce, 0xc5, +0xf0, 0x2d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe8, 0xa4, 0x2e, 0xc8, 0xc5, 0xf0, 0x3d, 0xfd, 0xe4, 0x3c, +0xfc, 0xef, 0xa4, 0xff, 0xe5, 0xf0, 0x28, 0xfe, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0xef, +0x4e, 0x60, 0x12, 0xef, 0x60, 0x01, 0x0e, 0xed, 0xbb, 0x01, 0x0b, 0x89, 0x82, 0x8a, 0x83, 0xf0, +0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x22, 0x89, 0xf0, 0x50, 0x07, 0xf7, 0x09, 0xdf, 0xfc, 0xa9, 0xf0, +0x22, 0xbb, 0xfe, 0xfc, 0xf3, 0x09, 0xdf, 0xfc, 0xa9, 0xf0, 0x22, 0x78, 0xff, 0xe4, 0xf6, 0xd8, +0xfd, 0x90, 0x00, 0x00, 0x7f, 0x00, 0x7e, 0x06, 0xe4, 0xf0, 0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x75, +0x81, 0x9a, 0x75, 0xa0, 0x00, 0x02, 0x05, 0x63, 0x02, 0x2f, 0xf7, 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, 0x00, 0x09, 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, 0xc2, 0xd5, 0xe8, 0x30, 0xe7, 0x0f, 0xb2, 0xd5, +0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0xec, 0x30, 0xe7, +0x17, 0xb2, 0xd5, 0x12, 0x05, 0xde, 0x12, 0x03, 0x6c, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, +0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0x80, 0x03, 0x12, 0x03, 0x6c, 0x30, 0xd5, 0x0d, 0xe4, 0xc3, +0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0xe4, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x22, 0x00, 0x21, 0x22, 0x20, +0x23, 0x30, 0x34, 0x33, 0x32, 0x32, 0x31, 0x54, 0x46, 0x65, 0x34, 0x32, 0x32, 0x33, 0x46, 0x33, +0x30, 0x32, 0x30, 0x24, 0x01, 0x00, 0x01, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x01, +0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x76, +0xa7, 0x18, 0xa1, 0x23, 0x63, 0x45, 0x07, 0x65, 0xaa, 0x56, 0xa1, 0x78, 0x00, 0x21, 0x00, 0x00, +0x00, 0x00, 0xaa, 0x21, 0xaa, 0x43, 0xaa, 0x56, 0xa7, 0x81, 0x00, 0x21, 0xaa, 0x67, 0xaa, 0x23, +0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x87, 0xaa, 0x32, 0xa1, 0x87, 0x06, 0x71, +0xaa, 0x87, 0xaa, 0x23, 0xaa, 0x87, 0xaa, 0x32, 0x00, 0x00, 0xaa, 0x87, 0xaa, 0x23, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xaa, 0x65, 0xaa, 0x87, 0xa6, 0x51, 0x06, 0x47, 0x00, 0x45, 0xa1, 0x28, +0xaa, 0x76, 0xa8, 0x12, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x34, 0xaa, 0x56, 0xa1, 0x78, 0x00, 0x21, +0x00, 0x00, 0xaa, 0x67, 0xaa, 0x23, 0xaa, 0xa1, 0xaa, 0x87, 0xaa, 0x32, 0xaa, 0x67, 0xaa, 0x23, +0xaa, 0x87, 0xaa, 0x32, 0xaa, 0xa1, 0xaa, 0x21, 0xaa, 0x56, 0xa7, 0x81, 0xaa, 0x21, 0x00, 0x00, +0xaa, 0x34, 0xaa, 0x65, 0xaa, 0x87, 0x46, 0x51, 0x03, 0x47, 0xaa, 0xa8, 0xaa, 0x21, 0xaa, 0x43, +0xaa, 0x56, 0xa7, 0x81, 0xaa, 0x34, 0xa5, 0x76, 0xa7, 0x18, 0xa1, 0x23, 0xa3, 0x45, 0xa4, 0x23, +0xa8, 0x21, 0xa6, 0x87, 0xa4, 0x32, 0x21, 0x78, 0xa5, 0x76, 0xa1, 0x23, 0x63, 0x45, 0x07, 0x65, +0x00, 0x00, 0x01, 0xe0, 0x01, 0xe0, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, +0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x02, 0xd0, +0xff, 0x06, 0x02, 0xd0, 0xff, 0x06, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, +0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x04, 0xb5, +0x00, 0xf0, 0x04, 0xb5, 0x00, 0xf0, 0x11, 0x16, 0x24, 0x50, 0x01, 0xb1, 0x46, 0x45, 0x44, 0x43, +0x42, 0x41, 0x40, 0x67, 0x66, 0x64, 0x63, 0x62, 0x61, 0x60, 0x84, 0x83, 0x72, 0x71, 0x70, 0x57, +0x56, 0x55, 0x54, 0x53, 0x73, 0x74, 0x75, 0x76, 0x77, 0x80, 0x81, 0x82, 0x40, 0x47, 0x51, 0x50, +0x00, 0x00, 0x00, 0x00, 0x80, 0x28, 0x10, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x21, 0x23, 0x28, +0x02, 0xbc, 0x22, 0x23, 0x28, 0x02, 0xbc, 0x23, 0x22, 0x28, 0x02, 0xbc, 0x00, 0x00, 0x85, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0xe0, 0x03, 0xc0, 0x03, 0xe8, 0x03, 0x84, 0x03, 0x84, +0x19, 0x03, 0x7b, 0x04, 0x04, 0x08, 0x08, 0x0c, 0xac, 0x11, 0x50, 0x15, 0xf4, 0x1a, 0x98, 0x1f, +0x3c, 0x25, 0x09, 0x26, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, +0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x32, 0x04, 0x12, 0x0f, 0x1c, 0xe5, 0x32, 0xb4, 0x01, 0x03, +0x12, 0x0e, 0x7f, 0x12, 0x08, 0x18, 0xd5, 0x32, 0xef, 0x12, 0x0f, 0x1c, 0x78, 0x87, 0x7c, 0x02, +0x11, 0x70, 0x78, 0xb5, 0x7c, 0x01, 0x11, 0x70, 0x78, 0xdb, 0x7c, 0x02, 0x11, 0x70, 0x7f, 0x2a, +0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x5a, 0xf1, 0x36, 0xe4, 0x90, 0x04, 0x53, 0xf0, 0xa3, 0x04, 0xf0, +0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x04, 0xf0, 0x75, 0x1c, 0x09, 0x90, 0xff, 0x4a, 0x74, 0x09, 0xf0, +0x90, 0xff, 0x50, 0x74, 0x0f, 0xd1, 0xfa, 0x90, 0xff, 0x40, 0x74, 0x18, 0x91, 0xfe, 0x78, 0x8e, +0xe6, 0x90, 0xff, 0x42, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x10, 0xf0, 0x11, 0x7f, 0xf1, 0x08, 0x43, +0xad, 0x04, 0x11, 0x69, 0x90, 0xff, 0x43, 0xe0, 0x30, 0xe4, 0xf9, 0x91, 0xff, 0x78, 0x8d, 0xe6, +0x90, 0xff, 0x48, 0xf0, 0x11, 0x7f, 0x53, 0xad, 0xfb, 0x90, 0xff, 0x40, 0x74, 0x19, 0xf0, 0x22, +0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x01, 0x79, 0x61, 0x7e, 0x00, 0x7f, 0x54, 0x02, 0x00, 0xf4, 0x7b, +0x03, 0xc2, 0xaf, 0xd1, 0xe3, 0x71, 0xc9, 0x7d, 0x06, 0x11, 0xb7, 0xd2, 0xaf, 0x78, 0x8f, 0xe6, +0xfd, 0xeb, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x55, 0xb1, 0x66, 0xed, 0xf0, 0xd1, 0xe3, 0xe0, 0x24, +0x37, 0xd1, 0xdb, 0xe0, 0xfd, 0xeb, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x54, 0xb1, 0x66, 0xed, 0xf0, +0xaf, 0x03, 0x1b, 0xef, 0x70, 0xcb, 0x22, 0xef, 0x54, 0x07, 0x90, 0x07, 0xdd, 0x93, 0xfe, 0xf4, +0xfc, 0xef, 0x54, 0xf0, 0xff, 0x75, 0xa0, 0xff, 0x64, 0x10, 0x70, 0x11, 0x78, 0x12, 0xed, 0x30, +0xe2, 0x05, 0xe2, 0x4e, 0xf2, 0x80, 0x03, 0xe2, 0x5c, 0xf2, 0x18, 0x80, 0x0d, 0xef, 0x13, 0x13, +0x54, 0x3f, 0x24, 0x11, 0xf8, 0xbd, 0x02, 0x02, 0xe4, 0xfd, 0xed, 0x30, 0xe1, 0x05, 0xe2, 0x4e, +0xf2, 0x80, 0x03, 0xe2, 0x5c, 0xf2, 0x18, 0xed, 0x30, 0xe0, 0x05, 0xe2, 0x4e, 0xf2, 0x80, 0x03, +0xe2, 0x5c, 0xf2, 0xe4, 0xf5, 0xa0, 0x22, 0x78, 0x23, 0x7c, 0x00, 0x7a, 0x07, 0x79, 0xb5, 0x7f, +0x28, 0x12, 0x3a, 0x25, 0xe4, 0xf5, 0x4b, 0x90, 0x03, 0xc6, 0xe0, 0xff, 0x90, 0x03, 0xc5, 0xe0, +0xfe, 0x6f, 0xfd, 0x90, 0x03, 0xc7, 0xe0, 0x6d, 0xfb, 0xee, 0xb4, 0xac, 0x08, 0xa3, 0xe0, 0xb5, +0x03, 0x03, 0x75, 0x4b, 0x01, 0xe5, 0x4b, 0x60, 0x02, 0x80, 0x02, 0x7f, 0x40, 0x90, 0xff, 0x42, +0xef, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x40, 0x91, 0xfe, 0xe4, 0x90, 0xff, 0x4a, 0xf0, 0x90, 0xff, +0x50, 0x74, 0x0f, 0xf0, 0x43, 0xad, 0x04, 0x7f, 0x24, 0x7a, 0x00, 0x79, 0x23, 0x12, 0x39, 0x8b, +0x7f, 0x48, 0x7a, 0x00, 0x79, 0xdf, 0x12, 0x34, 0xa6, 0xe4, 0xfb, 0xe4, 0xfa, 0xe4, 0x90, 0xff, +0x54, 0xf0, 0x90, 0xff, 0x55, 0x74, 0xfa, 0xf0, 0x91, 0xf2, 0xb1, 0x30, 0xc3, 0x94, 0xe0, 0xec, +0x94, 0x1f, 0x40, 0x44, 0x90, 0xff, 0x50, 0xe0, 0x30, 0xe7, 0x06, 0xae, 0x07, 0x1f, 0xee, 0x70, +0xf3, 0x74, 0x23, 0x2a, 0xf8, 0xe6, 0x90, 0xff, 0x54, 0xf0, 0xe5, 0x4b, 0x60, 0x07, 0x90, 0x03, +0xc7, 0xe0, 0xff, 0x80, 0x02, 0x7f, 0x40, 0x90, 0xff, 0x55, 0xef, 0xf0, 0xc2, 0xaf, 0xb1, 0x70, +0x2a, 0x71, 0xd9, 0x7d, 0x06, 0xb1, 0x1e, 0xb1, 0x70, 0x2a, 0x71, 0xd9, 0x7d, 0x02, 0xd1, 0xee, +0x91, 0xf2, 0x91, 0xea, 0xe4, 0x78, 0x99, 0xf6, 0x0a, 0xea, 0xc3, 0x94, 0x24, 0x40, 0x9e, 0xe4, +0xff, 0xfa, 0x74, 0x23, 0x2a, 0xf8, 0xe6, 0x30, 0xe7, 0x02, 0x7b, 0x01, 0x06, 0x91, 0xf3, 0xb1, +0x30, 0xc3, 0x94, 0xe0, 0xec, 0x94, 0x1f, 0x50, 0x06, 0x74, 0x23, 0x2a, 0xf8, 0x16, 0x0f, 0x0a, +0xba, 0x24, 0xdf, 0xef, 0x6a, 0x60, 0x05, 0xeb, 0x70, 0x02, 0x21, 0x6b, 0x7a, 0x23, 0x74, 0x23, +0x2a, 0xf8, 0xe6, 0xff, 0x7e, 0x00, 0x7c, 0x00, 0x7d, 0xff, 0x12, 0x01, 0x72, 0x91, 0xf3, 0xf5, +0x83, 0x12, 0x3a, 0x2e, 0x91, 0xf3, 0x12, 0x17, 0x6c, 0xff, 0xea, 0x25, 0xe0, 0x24, 0xe7, 0xf5, +0x82, 0xe4, 0x34, 0x00, 0x91, 0xea, 0xaf, 0x02, 0x1a, 0xef, 0x70, 0xd2, 0x90, 0xff, 0x41, 0x04, +0xf0, 0x90, 0xff, 0x42, 0xf0, 0xe4, 0x90, 0xff, 0x87, 0xf0, 0x90, 0xff, 0x18, 0xf0, 0xfd, 0x7f, +0x10, 0x91, 0xb5, 0x0d, 0x7f, 0x11, 0x91, 0xb5, 0x1d, 0x7f, 0x16, 0x91, 0xb5, 0x0d, 0x7f, 0x17, +0x91, 0xb5, 0x90, 0xff, 0x50, 0x74, 0x03, 0xf0, 0x90, 0xff, 0x68, 0xf0, 0xc2, 0xaf, 0x7d, 0x06, +0x7f, 0x10, 0x51, 0xdb, 0x7d, 0x06, 0x7f, 0x17, 0xb1, 0x1e, 0x7d, 0x02, 0x7f, 0x10, 0x51, 0xdb, +0x7d, 0x02, 0x7f, 0x17, 0x51, 0xdb, 0x7d, 0x02, 0x51, 0xd9, 0x7d, 0x02, 0xb1, 0x08, 0xe4, 0xfa, +0x0a, 0xba, 0xff, 0xfc, 0xc2, 0xaf, 0x7d, 0x07, 0x51, 0xd9, 0xb1, 0x06, 0x90, 0xff, 0x55, 0x74, +0x14, 0xf1, 0x0e, 0x90, 0xff, 0x50, 0x74, 0x07, 0xd1, 0xfa, 0xb1, 0x0f, 0x90, 0xff, 0x52, 0xe0, +0xff, 0xa3, 0xe0, 0x90, 0x00, 0xdf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x5a, 0xe0, 0xff, +0xa3, 0xe0, 0x90, 0x00, 0xe1, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x62, 0xe0, 0xff, 0xa3, +0xe0, 0x90, 0x00, 0xe3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x6a, 0xe0, 0xff, 0xa3, 0xe0, +0x90, 0x00, 0xe5, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x22, 0x7f, 0x11, 0x11, 0xb7, 0xd2, 0xaf, 0xc2, +0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, +0x00, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x91, 0xff, 0xc2, 0xaf, 0x90, +0x04, 0x53, 0x71, 0xc9, 0x7d, 0x05, 0x51, 0xdb, 0x90, 0x04, 0x54, 0x71, 0xc9, 0x7d, 0x05, 0x51, +0xdb, 0x90, 0x04, 0x55, 0x71, 0xc9, 0x7d, 0x05, 0x51, 0xdb, 0x90, 0x04, 0x56, 0x71, 0xc9, 0x7d, +0x05, 0xd1, 0xee, 0x90, 0x04, 0x53, 0x91, 0xdf, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, +0x90, 0x04, 0x54, 0x91, 0xe0, 0x90, 0xff, 0x62, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x04, 0x55, +0x91, 0xe0, 0x90, 0xff, 0x6a, 0xe0, 0xfe, 0xa3, 0xe0, 0x90, 0x04, 0x56, 0x91, 0xdf, 0xd5, 0x1c, +0x0c, 0x90, 0xff, 0x4a, 0xe4, 0xf0, 0x90, 0xff, 0x50, 0xd1, 0xfa, 0x80, 0x55, 0x90, 0x04, 0x53, +0xe0, 0x24, 0x02, 0xf0, 0x90, 0x04, 0x55, 0xe0, 0x24, 0x02, 0xf0, 0x90, 0x04, 0x53, 0xe0, 0x04, +0xa3, 0xf0, 0xa3, 0xe0, 0x04, 0xa3, 0xf0, 0x75, 0x54, 0x64, 0x75, 0x55, 0x00, 0xf1, 0x08, 0x7d, +0x03, 0xed, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x50, 0xb1, 0x66, 0xe0, 0x20, 0xe7, 0x0d, 0x74, 0x01, +0xa8, 0x05, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x55, 0xaf, 0x05, 0x1d, 0xef, 0x70, +0xe0, 0xe5, 0x55, 0x64, 0x0f, 0x60, 0x07, 0xaf, 0x54, 0x15, 0x54, 0xef, 0x70, 0xd1, 0x11, 0x7f, +0x11, 0x69, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x00, 0xd0, 0xd0, +0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xe0, 0xff, 0xe5, 0x1f, 0x24, 0x06, 0xf5, +0x82, 0xe4, 0x35, 0x1e, 0xf5, 0x83, 0xe5, 0x82, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, +0xe4, 0x93, 0xff, 0x22, 0x75, 0x1e, 0x07, 0x75, 0x1f, 0x36, 0x78, 0x8d, 0x7c, 0x00, 0x7a, 0x07, +0x79, 0x64, 0x7f, 0x08, 0x12, 0x3a, 0x25, 0x90, 0x07, 0x64, 0xe4, 0x93, 0x78, 0x8d, 0xf6, 0x43, +0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x07, 0xf0, 0xe4, 0x90, 0xff, 0x87, 0xf0, 0x90, 0xff, 0x4b, +0x74, 0x13, 0xf0, 0x90, 0xff, 0x4b, 0xe0, 0x30, 0xe3, 0xf9, 0x90, 0xff, 0x49, 0x74, 0x05, 0xf0, +0xe4, 0xfd, 0x7f, 0x11, 0xb1, 0x37, 0x7d, 0x01, 0x7f, 0x11, 0x91, 0xb5, 0xc2, 0xaf, 0x0d, 0x51, +0xd9, 0x7d, 0x07, 0x7f, 0x11, 0x11, 0xb7, 0xd2, 0xaf, 0xe4, 0xfd, 0x7f, 0x16, 0xb1, 0x37, 0xe4, +0xfd, 0x7f, 0x16, 0x91, 0xb5, 0xc2, 0xaf, 0x7d, 0x02, 0x7f, 0x16, 0x51, 0xdb, 0xb1, 0x06, 0xe4, +0xf5, 0x1c, 0xf5, 0x19, 0xf5, 0x1d, 0xf5, 0x1a, 0x20, 0x06, 0x1f, 0xfe, 0x7f, 0x2a, 0xfd, 0x7b, +0x01, 0x7a, 0x02, 0x79, 0x09, 0x12, 0x04, 0xdf, 0x7f, 0x54, 0x7b, 0x01, 0x7a, 0x00, 0x79, 0x8b, +0xf1, 0x36, 0x75, 0x23, 0x05, 0x75, 0x24, 0x01, 0x80, 0x0c, 0x75, 0x23, 0x02, 0xe4, 0xf5, 0x24, +0x90, 0xff, 0x87, 0x74, 0x03, 0xf0, 0xe4, 0xfb, 0xb1, 0x70, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x83, +0xf5, 0x83, 0xe4, 0x93, 0xf5, 0x25, 0xeb, 0x54, 0x01, 0x55, 0x24, 0xfd, 0xaf, 0x25, 0x91, 0xb5, +0xad, 0x24, 0xaf, 0x25, 0xb1, 0x37, 0xc2, 0xaf, 0xad, 0x23, 0xaf, 0x25, 0x11, 0xb7, 0xd2, 0xaf, +0x0b, 0xbb, 0x24, 0xd4, 0x22, 0x12, 0x39, 0xf7, 0x90, 0xff, 0x13, 0xd3, 0x94, 0x03, 0x40, 0x0f, +0xef, 0x75, 0xf0, 0x04, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0xed, +0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22, 0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22, 0xff, +0xe0, 0x25, 0xe0, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, +0xf0, 0x22, 0xff, 0xea, 0x25, 0xe0, 0x24, 0xdf, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x22, 0xf0, 0x90, +0xff, 0x43, 0x74, 0x9f, 0xf0, 0x22, 0x7d, 0x07, 0x7f, 0x16, 0x11, 0xb7, 0xd2, 0xaf, 0x22, 0x90, +0xff, 0x40, 0x74, 0x09, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x30, 0xe4, 0xf9, 0x80, 0xe1, 0x11, 0xb7, +0xd2, 0xaf, 0xb1, 0x0f, 0xc2, 0xaf, 0x22, 0x25, 0xe0, 0x24, 0x61, 0xf5, 0x82, 0xe4, 0x34, 0x01, +0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0x22, 0x12, 0x39, 0xf7, 0xc2, 0xaf, 0x75, 0xa0, 0xff, 0xbf, +0x01, 0x04, 0x7e, 0x18, 0x80, 0x08, 0xef, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x12, 0xfe, 0xed, 0xa8, +0x06, 0x60, 0x05, 0xe2, 0x4c, 0xf2, 0x80, 0x08, 0xe2, 0xff, 0xec, 0xf4, 0xfd, 0xef, 0x5d, 0xf2, +0xe4, 0xf5, 0xa0, 0xd2, 0xaf, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0xff, 0x8f, 0x82, 0xf5, 0x83, 0x22, +0xe5, 0x1f, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x1e, 0xf5, 0x83, 0xe5, 0x82, 0x22, 0xab, 0x05, +0xef, 0x14, 0xfa, 0xc2, 0xaf, 0xb1, 0x70, 0x2a, 0x71, 0xd9, 0xad, 0x03, 0x11, 0xb7, 0xd2, 0xaf, +0xaf, 0x02, 0x1a, 0xef, 0x70, 0xed, 0x22, 0xa9, 0x07, 0xb9, 0xa5, 0x0a, 0x75, 0x88, 0x08, 0x75, +0x89, 0x80, 0x91, 0xff, 0xc1, 0x75, 0x75, 0x91, 0x01, 0xe4, 0xf5, 0x91, 0x30, 0x05, 0x10, 0xe9, +0x54, 0xe0, 0x60, 0x0b, 0xd1, 0x75, 0xe4, 0xf5, 0x91, 0x7d, 0x05, 0x7f, 0x24, 0xb1, 0x7e, 0x22, +0x75, 0x22, 0xff, 0x75, 0x5f, 0x01, 0xe5, 0x62, 0x70, 0x0c, 0xc2, 0x06, 0x71, 0xe4, 0x12, 0x18, +0x0d, 0x75, 0x62, 0x01, 0xc1, 0x64, 0xe5, 0x62, 0x64, 0x01, 0x70, 0x65, 0x78, 0x9a, 0xf6, 0x12, +0x30, 0x04, 0x7f, 0x7b, 0x12, 0x18, 0x32, 0x20, 0x00, 0x1c, 0xe5, 0x56, 0x70, 0x18, 0x05, 0x60, +0xe5, 0x60, 0xd3, 0x94, 0x64, 0x40, 0x1d, 0x75, 0x60, 0x64, 0xe5, 0x63, 0x7f, 0x14, 0x60, 0x02, +0x7f, 0x1e, 0x8f, 0x61, 0x80, 0x0e, 0xe4, 0xf5, 0x60, 0x12, 0x39, 0x5e, 0x7f, 0x0b, 0x40, 0x02, +0x7f, 0x1e, 0x8f, 0x61, 0xc2, 0x05, 0xe5, 0x63, 0x60, 0x18, 0x7f, 0x7b, 0x12, 0x37, 0x11, 0x8f, +0x22, 0x7f, 0x0c, 0x7a, 0x00, 0x79, 0x7b, 0x12, 0x39, 0x8b, 0xe4, 0x78, 0x9a, 0xf6, 0xd2, 0x05, +0x80, 0x06, 0xe4, 0x78, 0x64, 0xf6, 0x08, 0xf6, 0x7f, 0x7b, 0xad, 0x22, 0x12, 0x31, 0x80, 0x80, +0x23, 0xe5, 0x62, 0xb4, 0x02, 0x06, 0x7f, 0xa5, 0xb1, 0x97, 0x80, 0x18, 0xe5, 0x62, 0xb4, 0x03, +0x10, 0xd2, 0x06, 0x71, 0xe4, 0x31, 0x07, 0xe4, 0xf5, 0x62, 0x00, 0xe4, 0x78, 0x99, 0xf6, 0x80, +0xf9, 0xe4, 0xf5, 0x62, 0xf1, 0x1c, 0xe5, 0x5f, 0x60, 0x0a, 0xaf, 0x22, 0xb1, 0x97, 0xe4, 0x78, +0x99, 0xf6, 0x80, 0xf2, 0x22, 0xe4, 0xfd, 0x7f, 0x24, 0xb1, 0x7e, 0x75, 0x91, 0x03, 0x22, 0x78, +0x8d, 0xe6, 0xf5, 0x34, 0x76, 0x04, 0x75, 0x33, 0x3c, 0xe4, 0xf5, 0x35, 0x78, 0x99, 0xf6, 0xff, +0xe5, 0x33, 0xb4, 0x3c, 0x04, 0xd1, 0xd8, 0xe4, 0xf0, 0xd1, 0xd8, 0xe0, 0x24, 0x02, 0xf0, 0x0f, +0xef, 0xc3, 0x94, 0x24, 0x40, 0xea, 0x11, 0x18, 0xf1, 0x1c, 0xe4, 0xff, 0xef, 0xb1, 0x27, 0xc3, +0x94, 0x99, 0xec, 0x94, 0x01, 0x50, 0x08, 0xd1, 0xd8, 0xe0, 0x24, 0xfe, 0xf0, 0x05, 0x35, 0x0f, +0xef, 0xc3, 0x94, 0x24, 0x40, 0xe6, 0xe5, 0x35, 0x94, 0x24, 0x50, 0x07, 0xaf, 0x33, 0x15, 0x33, +0xef, 0x70, 0xb6, 0x78, 0x8d, 0xa6, 0x34, 0x22, 0x74, 0x37, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, +0xf5, 0x83, 0x22, 0x74, 0x53, 0x2b, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0x22, 0x11, 0xb7, +0xd2, 0xaf, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0x22, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90, +0xff, 0x60, 0xf0, 0x90, 0xff, 0x68, 0xf0, 0x22, 0x78, 0x91, 0xe6, 0x90, 0xff, 0x55, 0xf0, 0x90, +0xff, 0x5d, 0xf0, 0x90, 0xff, 0x65, 0xf0, 0x90, 0xff, 0x6d, 0xf0, 0x22, 0xe5, 0x1c, 0x60, 0x03, +0x00, 0x80, 0xf9, 0x78, 0x61, 0x7c, 0x01, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0x33, 0x7e, +0x00, 0x7f, 0x54, 0x02, 0x00, 0xf4, 0x7e, 0x00, 0x7d, 0x00, 0x02, 0x04, 0xdf, 0xf1, 0x1c, 0x11, +0x18, 0xe4, 0xf5, 0x37, 0xf5, 0x38, 0xf5, 0x39, 0xf5, 0x3a, 0x90, 0x03, 0x32, 0xf0, 0xa3, 0xf0, +0xf5, 0x34, 0xf5, 0x33, 0xf5, 0x32, 0x12, 0x39, 0xa0, 0xe0, 0xf5, 0x3b, 0xa3, 0xe0, 0xf5, 0x3c, +0x12, 0x39, 0xa0, 0xc0, 0x83, 0xc0, 0x82, 0xae, 0x3b, 0xaf, 0x3c, 0x12, 0x17, 0x73, 0xc3, 0xa3, +0xe0, 0x9f, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x9e, 0xd0, 0x82, +0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x3a, 0x19, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x17, 0x7a, +0x12, 0x39, 0xa0, 0x12, 0x3a, 0x2e, 0x12, 0x3a, 0x19, 0xf5, 0x83, 0x12, 0x3a, 0x6c, 0x12, 0x17, +0x61, 0xff, 0xe5, 0x32, 0xb1, 0x27, 0xc3, 0x9f, 0xf5, 0x36, 0xec, 0x9e, 0xf5, 0x35, 0xe5, 0x32, +0x12, 0x13, 0x8c, 0xe4, 0xf0, 0xa3, 0xf0, 0xc3, 0x12, 0x17, 0xa1, 0x40, 0x4a, 0xe5, 0x32, 0xd3, +0x94, 0x0f, 0xe5, 0x32, 0x40, 0x06, 0x54, 0x01, 0x24, 0x86, 0x80, 0x04, 0x54, 0x01, 0x24, 0x84, +0xf8, 0xe2, 0xff, 0xe4, 0x8f, 0x44, 0xf5, 0x43, 0xf5, 0x42, 0xf5, 0x41, 0xab, 0x44, 0xaa, 0x43, +0xa9, 0x42, 0xa8, 0x41, 0xae, 0x35, 0xaf, 0x36, 0x12, 0x24, 0x3e, 0x12, 0x24, 0x28, 0x8c, 0x41, +0xe4, 0x7b, 0x80, 0xfa, 0xf9, 0xf8, 0x12, 0x03, 0x6c, 0x12, 0x24, 0x28, 0x8c, 0x41, 0xe5, 0x32, +0x71, 0x8c, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x39, 0xaf, 0x3a, 0xf1, 0x73, 0xe5, 0x3a, 0x2f, +0xff, 0xe5, 0x39, 0x3e, 0xfe, 0xc3, 0xef, 0x95, 0x36, 0xe5, 0x35, 0xf1, 0x81, 0x50, 0x09, 0x85, +0x32, 0x33, 0x85, 0x35, 0x39, 0x85, 0x36, 0x3a, 0xd3, 0xe5, 0x38, 0x95, 0x36, 0xe5, 0x35, 0x64, +0x80, 0xf8, 0xe5, 0x37, 0x64, 0x80, 0x98, 0x40, 0x06, 0x85, 0x35, 0x37, 0x85, 0x36, 0x38, 0xf1, +0x61, 0xff, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xdb, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0x12, 0x0d, 0x30, +0xc3, 0x9f, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0xd3, 0xef, 0x94, 0x13, 0xee, 0x94, 0x05, +0x40, 0x03, 0x43, 0x1a, 0x10, 0xb1, 0x39, 0x50, 0x03, 0x02, 0x0f, 0x56, 0xe4, 0xf5, 0x3d, 0xf5, +0x3e, 0xf5, 0x3f, 0xf5, 0x40, 0x90, 0x03, 0x31, 0xf0, 0xf5, 0x32, 0xe5, 0x32, 0x25, 0xe0, 0xb1, +0x41, 0xf1, 0x6c, 0xff, 0xe5, 0x32, 0x25, 0xe0, 0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0x2f, 0xff, +0xec, 0x3e, 0xf8, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x5a, 0xc8, 0xf2, 0x08, 0xef, 0xf2, 0xd1, 0x5c, +0xd3, 0x94, 0xb1, 0xee, 0x94, 0x01, 0x40, 0x1e, 0xe5, 0x32, 0x94, 0x08, 0x50, 0x0e, 0xef, 0x95, +0x3e, 0xee, 0x95, 0x3d, 0x40, 0x15, 0x8e, 0x3d, 0x8f, 0x3e, 0x80, 0x0f, 0xf1, 0x89, 0x40, 0x0b, +0x8e, 0x3f, 0x8f, 0x40, 0x80, 0x05, 0xef, 0x25, 0x34, 0xf5, 0x34, 0x05, 0x32, 0xe5, 0x32, 0x64, +0x10, 0x70, 0xa8, 0xe5, 0x34, 0x75, 0xf0, 0x32, 0x84, 0xf5, 0x34, 0xe4, 0xf5, 0x32, 0xe5, 0x32, +0xc3, 0x94, 0x10, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04, 0xae, 0x3f, 0xaf, 0x40, 0x8e, +0x3b, 0x8f, 0x3c, 0xe5, 0x32, 0x71, 0x8c, 0xf1, 0xa8, 0x40, 0x1b, 0xf1, 0x73, 0xc3, 0xeb, 0x9f, +0xea, 0x9e, 0x50, 0x12, 0xe5, 0x32, 0xc3, 0x94, 0x10, 0x50, 0x05, 0x90, 0x03, 0x32, 0x80, 0x03, +0x90, 0x03, 0x33, 0xe0, 0x04, 0xf0, 0xf1, 0x2a, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04, +0xae, 0x3f, 0xaf, 0x40, 0x8e, 0x3b, 0x8f, 0x3c, 0xe5, 0x32, 0x71, 0x8c, 0xf1, 0xa8, 0x40, 0x29, +0x12, 0x3a, 0x46, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x1f, 0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe, +0xa3, 0xe0, 0xff, 0xe5, 0x32, 0xb1, 0x41, 0x12, 0x0d, 0x30, 0xfd, 0xf1, 0xf3, 0xef, 0xc3, 0x94, +0x1e, 0x50, 0x06, 0x90, 0x03, 0x31, 0xe0, 0x04, 0xf0, 0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe, 0xa3, +0xe0, 0xff, 0x4e, 0x60, 0x28, 0xad, 0x34, 0x7c, 0x00, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x10, +0xe5, 0x32, 0x71, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xc3, 0x9d, 0xff, 0xee, 0x9c, 0xfe, 0x80, 0x04, +0x7e, 0x00, 0x7f, 0x01, 0xe5, 0x32, 0x71, 0x8c, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xb1, 0x39, 0x50, +0x02, 0x01, 0xde, 0xf1, 0x2a, 0x50, 0x06, 0xae, 0x3d, 0xaf, 0x3e, 0x80, 0x04, 0xae, 0x3f, 0xaf, +0x40, 0x8e, 0x3b, 0x8f, 0x3c, 0xc3, 0x90, 0x03, 0x30, 0xe0, 0x95, 0x3c, 0x90, 0x03, 0x2f, 0xe0, +0x95, 0x3b, 0x50, 0x03, 0x12, 0x3a, 0x6c, 0xe5, 0x13, 0x70, 0x0e, 0xae, 0x3b, 0xaf, 0x3c, 0xfc, +0x7d, 0x19, 0x12, 0x01, 0xd9, 0x8e, 0x14, 0x8f, 0x15, 0x75, 0x3b, 0x00, 0x75, 0x3c, 0x0a, 0xc3, +0xe5, 0x3e, 0x95, 0x40, 0xff, 0xe5, 0x3d, 0x95, 0x3f, 0xfe, 0x12, 0x00, 0x12, 0xaa, 0x06, 0xab, +0x07, 0xe5, 0x3e, 0x25, 0x40, 0xff, 0xe5, 0x3d, 0x35, 0x3f, 0xfe, 0xf1, 0x7a, 0xef, 0x78, 0x02, +0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x0c, 0x20, +0x03, 0x09, 0x74, 0x04, 0x25, 0x3c, 0xf5, 0x3c, 0xe4, 0x80, 0x0b, 0x30, 0x03, 0x0c, 0x74, 0xfc, +0x25, 0x3c, 0xf5, 0x3c, 0x74, 0xff, 0x35, 0x3b, 0xf5, 0x3b, 0x90, 0x03, 0x31, 0xe0, 0xff, 0xd3, +0x95, 0x3c, 0xe5, 0x3b, 0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x40, 0x2d, 0xe5, 0x13, 0x94, 0x05, +0x50, 0x08, 0x74, 0x03, 0x25, 0x13, 0xf5, 0x13, 0x80, 0x03, 0x75, 0x13, 0x50, 0xe5, 0x11, 0xb4, +0x02, 0x17, 0x53, 0x1a, 0xf7, 0x90, 0x00, 0xcd, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0xa3, 0xe4, 0xf0, +0xa3, 0x04, 0xf0, 0xa3, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0xd3, 0xf1, 0x91, 0x40, 0x21, 0xe5, 0x33, +0x25, 0xe0, 0x24, 0x89, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x12, 0x0d, 0x30, 0x4c, 0x70, 0x0a, 0xe5, +0x33, 0xb1, 0x41, 0x12, 0x0d, 0x30, 0x4c, 0x60, 0x06, 0x75, 0x1d, 0x28, 0x43, 0x1a, 0x08, 0xef, +0xd3, 0x94, 0x05, 0x40, 0x1c, 0xe5, 0x3a, 0x94, 0xdc, 0xe5, 0x39, 0x64, 0x80, 0x94, 0x85, 0x50, +0x10, 0xf1, 0x91, 0x40, 0x0c, 0xe5, 0x56, 0x70, 0x02, 0xf5, 0x1d, 0x20, 0x00, 0x03, 0x53, 0x1a, +0xf7, 0xc3, 0xe4, 0x95, 0x38, 0xff, 0xe4, 0x95, 0x37, 0xfe, 0xc3, 0x74, 0x13, 0x9f, 0xee, 0x64, +0x80, 0xf8, 0x74, 0x05, 0x64, 0x80, 0x98, 0x50, 0x10, 0x74, 0x62, 0x95, 0x3a, 0xe5, 0x39, 0x64, +0x80, 0xf8, 0x74, 0x03, 0x64, 0x80, 0x98, 0x50, 0x0d, 0x90, 0x03, 0x31, 0xe0, 0xd3, 0x94, 0x1b, +0x40, 0x0a, 0xe5, 0x56, 0x70, 0x06, 0x43, 0x1a, 0x10, 0x75, 0x1d, 0x01, 0xe5, 0x1d, 0x60, 0x02, +0x61, 0x75, 0xf5, 0x32, 0xf1, 0x61, 0xff, 0xe5, 0x32, 0x12, 0x0d, 0x27, 0xc3, 0x9f, 0xf5, 0x36, +0xec, 0x9e, 0xf5, 0x35, 0xf1, 0x55, 0xe0, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x12, 0x2f, 0x2a, +0xf5, 0x35, 0xfe, 0x7d, 0x02, 0x12, 0x3a, 0x0d, 0xf1, 0x55, 0xef, 0xf0, 0x12, 0x00, 0x12, 0xd3, +0xef, 0x94, 0x28, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x2d, 0xae, 0x35, 0x7d, 0x14, 0x12, 0x3a, +0x0d, 0x12, 0x00, 0x12, 0xd3, 0xef, 0x94, 0x90, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x12, 0xf1, +0x9c, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x90, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0x70, 0x8e, 0x35, 0x8f, +0x36, 0xf1, 0x55, 0xe4, 0xf0, 0x80, 0x12, 0xf1, 0x9c, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, +0x04, 0x7e, 0xff, 0x7f, 0xff, 0x8e, 0x35, 0x8f, 0x36, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xb5, 0xf5, +0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe5, 0x35, 0x85, 0x36, 0xf0, 0x12, 0x02, 0x0f, 0xb1, 0x39, +0x50, 0x02, 0x41, 0xe4, 0x22, 0x15, 0x1d, 0x22, 0xe5, 0x36, 0x25, 0xe0, 0x24, 0x8b, 0xf5, 0x82, +0xe4, 0x34, 0x00, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x35, 0x25, 0xe0, 0x24, 0x8b, +0xf5, 0x82, 0xe4, 0x34, 0x00, 0xf5, 0x83, 0x22, 0x8f, 0x32, 0xe5, 0x32, 0x25, 0xe0, 0xf5, 0x35, +0x04, 0xf5, 0x36, 0xe5, 0x35, 0x24, 0xfe, 0xf5, 0x33, 0xe5, 0x35, 0x14, 0xf5, 0x34, 0xe5, 0x35, +0x24, 0x02, 0xf5, 0x37, 0xe5, 0x35, 0x24, 0x03, 0xf5, 0x38, 0xe5, 0x32, 0xd3, 0x94, 0x07, 0x40, +0x18, 0x71, 0x8a, 0xf1, 0x1a, 0x71, 0x8c, 0xd1, 0xdf, 0xf1, 0x34, 0x40, 0x46, 0xe5, 0x3b, 0x13, +0xfe, 0xe5, 0x3c, 0x13, 0xff, 0xe5, 0x35, 0x80, 0x35, 0x71, 0x78, 0xd1, 0xdf, 0xe5, 0x32, 0xd3, +0x94, 0x01, 0x40, 0x09, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x56, 0x12, 0x39, 0xc4, 0xe5, 0x32, 0xc3, +0x94, 0x06, 0x50, 0x09, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x5e, 0x12, 0x39, 0xc4, 0xf1, 0x34, 0x40, +0x12, 0xae, 0x3b, 0xaf, 0x3c, 0x7c, 0x00, 0x7d, 0x03, 0x12, 0x01, 0x84, 0xe5, 0x36, 0x71, 0x8c, +0x12, 0x3a, 0x2e, 0xaf, 0x32, 0xd1, 0xa6, 0xef, 0x64, 0x01, 0x70, 0x5a, 0xd1, 0x5c, 0xe5, 0x32, +0x25, 0xe0, 0x24, 0x5c, 0xf1, 0x42, 0xb1, 0x31, 0xe5, 0x32, 0x70, 0x17, 0x85, 0x36, 0x44, 0x7b, +0x5a, 0x7d, 0x19, 0x91, 0xe5, 0x71, 0x78, 0xb1, 0x15, 0x24, 0xf1, 0xff, 0x85, 0x36, 0x44, 0x7b, +0x78, 0x80, 0x2f, 0xaf, 0x3a, 0x85, 0x36, 0x44, 0x7b, 0x6e, 0x7d, 0x19, 0x91, 0xe5, 0xe5, 0x37, +0x71, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x38, 0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, +0xb1, 0x31, 0x7b, 0x28, 0x7a, 0x00, 0x7d, 0x14, 0xb1, 0x27, 0x24, 0xec, 0xff, 0x85, 0x35, 0x44, +0x7b, 0x64, 0x7d, 0x64, 0x91, 0xe5, 0xaf, 0x32, 0xd1, 0xa6, 0xef, 0x64, 0x02, 0x70, 0x36, 0xd1, +0x5c, 0xe5, 0x32, 0xf1, 0x3e, 0xb1, 0x31, 0xe5, 0x32, 0x64, 0x0f, 0x70, 0x1d, 0x85, 0x35, 0x44, +0x7b, 0x50, 0x7d, 0x19, 0x91, 0xe5, 0x71, 0x8a, 0xf1, 0x1a, 0x71, 0x8c, 0xb1, 0x15, 0x24, 0xf1, +0xff, 0x85, 0x35, 0x44, 0x7b, 0x32, 0x7d, 0x64, 0x80, 0x09, 0xaf, 0x3a, 0x85, 0x35, 0x44, 0x7b, +0x82, 0x7d, 0x18, 0x91, 0xe5, 0x22, 0xab, 0x07, 0xaa, 0x06, 0xaf, 0x05, 0xae, 0x04, 0x12, 0x24, +0x2f, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e, 0xfc, 0xaf, 0x03, 0xae, 0x02, 0x12, 0x01, 0x84, 0xaa, +0x06, 0xab, 0x07, 0xd3, 0xeb, 0x94, 0xc8, 0xea, 0x94, 0x00, 0xaf, 0x03, 0x40, 0x02, 0x7f, 0xc8, +0x22, 0x7b, 0x28, 0x7d, 0x32, 0x8b, 0x43, 0xef, 0xd3, 0x9d, 0x40, 0x02, 0xaf, 0x05, 0xe5, 0x44, +0x71, 0x8c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x7e, 0x00, 0x12, 0x04, 0xb2, 0xc0, 0x07, 0xaf, 0x43, +0xab, 0x07, 0xe4, 0xfa, 0xf9, 0xf8, 0xd0, 0x07, 0x12, 0x03, 0x6c, 0xe5, 0x44, 0x71, 0x8c, 0xee, +0x8f, 0xf0, 0x02, 0x02, 0x0f, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f, +0x3a, 0x7b, 0x50, 0x7a, 0x00, 0x7d, 0x0f, 0xae, 0x39, 0xd1, 0xbd, 0x8e, 0x39, 0x8f, 0x3a, 0xef, +0x22, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x22, 0x05, 0x32, 0xe5, 0x32, 0xc3, 0x94, 0x24, +0x22, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x22, 0x8f, 0x32, 0x8d, 0x33, 0x85, +0x32, 0x34, 0xe4, 0xf5, 0x38, 0xf5, 0x36, 0xf5, 0x3d, 0xf5, 0x3e, 0x75, 0x37, 0xff, 0xe5, 0x34, +0xc3, 0x95, 0x33, 0x40, 0x02, 0xc1, 0x18, 0xe5, 0x34, 0x25, 0xe0, 0xf5, 0x35, 0xaf, 0x34, 0xd1, +0xa6, 0x8f, 0x39, 0xe5, 0x39, 0x60, 0x35, 0xb4, 0x01, 0x0c, 0xe5, 0x34, 0xd1, 0x5e, 0xe5, 0x34, +0x25, 0xe0, 0x24, 0x5c, 0x80, 0x0a, 0xe5, 0x34, 0xd1, 0x5e, 0xe5, 0x34, 0x25, 0xe0, 0x24, 0x58, +0xf1, 0x42, 0x91, 0xb6, 0x8f, 0x39, 0xe5, 0x39, 0x24, 0x03, 0xff, 0x85, 0x35, 0x44, 0x91, 0xe1, +0xe5, 0x39, 0x24, 0x03, 0xff, 0xe5, 0x35, 0x04, 0xf5, 0x44, 0x91, 0xe1, 0xe5, 0x35, 0xb1, 0x41, +0x71, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0x2f, 0xf5, 0x40, 0xec, 0x3e, 0xf5, 0x3f, 0xd3, 0xf1, 0x2b, +0x40, 0x16, 0xd3, 0xe5, 0x40, 0x94, 0xb1, 0xe5, 0x3f, 0x94, 0x01, 0x40, 0x0b, 0x75, 0x38, 0x01, +0x85, 0x3f, 0x3d, 0x85, 0x40, 0x3e, 0x80, 0x39, 0xae, 0x3d, 0xaf, 0x3e, 0x7c, 0x00, 0x7d, 0x07, +0x12, 0x01, 0x84, 0xc3, 0xe5, 0x3e, 0x9f, 0xff, 0xe5, 0x3d, 0x9e, 0xfe, 0xf1, 0x89, 0x40, 0x24, +0xe5, 0x38, 0x60, 0x0d, 0xe4, 0xf5, 0x38, 0x12, 0x39, 0xae, 0xe5, 0x36, 0xc3, 0x94, 0x03, 0x50, +0x17, 0xae, 0x3f, 0xaf, 0x40, 0xf1, 0x7a, 0xe5, 0x40, 0x2f, 0xf5, 0x3e, 0xe5, 0x3f, 0x3e, 0xf5, +0x3d, 0x85, 0x34, 0x37, 0x05, 0x34, 0xa1, 0x5e, 0xe5, 0x38, 0x60, 0x0a, 0xe5, 0x36, 0xc3, 0x94, +0x02, 0x50, 0x03, 0x12, 0x39, 0xae, 0x7b, 0xff, 0xf1, 0xb4, 0xb4, 0xff, 0x04, 0x7f, 0xff, 0x80, +0x02, 0xf1, 0x22, 0xe5, 0x32, 0x7e, 0x02, 0x70, 0x01, 0xfe, 0x74, 0x95, 0x2e, 0xf8, 0xa6, 0x07, +0xab, 0x34, 0xf1, 0xb4, 0xb4, 0xff, 0x04, 0x7f, 0xff, 0x80, 0x02, 0xf1, 0x22, 0xe5, 0x32, 0x7e, +0x03, 0x70, 0x02, 0x7e, 0x01, 0x74, 0x95, 0x2e, 0xf8, 0xa6, 0x07, 0x22, 0xe5, 0x32, 0x25, 0xe0, +0x24, 0x5a, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x22, 0x7d, 0x01, 0xe4, 0xff, 0x8f, 0x3b, 0x8d, +0x3c, 0xe5, 0x3c, 0x75, 0xf0, 0x1f, 0xa4, 0x24, 0x15, 0xd1, 0x62, 0xe5, 0x3b, 0x75, 0xf0, 0x07, +0xa4, 0x24, 0x40, 0xf1, 0x49, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3c, 0x75, 0xf0, 0x1f, 0xa4, 0x24, +0x17, 0xd1, 0x62, 0xe5, 0x3b, 0x75, 0xf0, 0x07, 0xa4, 0x24, 0x42, 0xf1, 0x49, 0xd0, 0xe0, 0x2f, +0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x22, 0xef, 0x60, 0x03, 0xbf, 0x08, 0x03, 0x7f, 0x01, 0x22, 0xef, +0x64, 0x07, 0x60, 0x03, 0xbf, 0x0f, 0x03, 0x7f, 0x02, 0x22, 0x7f, 0x00, 0x22, 0xed, 0xf5, 0x82, +0x75, 0x83, 0x00, 0xc3, 0xef, 0x95, 0x82, 0x74, 0x80, 0xf8, 0x6e, 0x98, 0x50, 0x04, 0x7e, 0x00, +0xaf, 0x82, 0xd3, 0xef, 0x9b, 0xea, 0xf1, 0x81, 0x40, 0x04, 0xae, 0x02, 0xaf, 0x03, 0x22, 0xe0, +0xfc, 0xa3, 0xe0, 0xfd, 0x91, 0xb6, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x90, 0x00, 0xce, 0xe0, 0x25, +0xe0, 0xff, 0x90, 0x00, 0xcd, 0xe0, 0x33, 0xfe, 0x90, 0x00, 0xd0, 0xe0, 0x2f, 0xfd, 0x90, 0x00, +0xcf, 0xe0, 0x3e, 0xfc, 0x90, 0x00, 0xd2, 0xe0, 0x25, 0xe0, 0xff, 0x90, 0x00, 0xd1, 0xe0, 0x33, +0xfe, 0xed, 0x2f, 0xf5, 0x3c, 0xec, 0x3e, 0xf5, 0x3b, 0x22, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, +0x36, 0x22, 0x74, 0x3a, 0x25, 0x34, 0xf8, 0xe6, 0xff, 0x22, 0xc3, 0xe5, 0x40, 0x95, 0x3e, 0xe5, +0x3f, 0x95, 0x3d, 0x22, 0xd3, 0xe5, 0x3a, 0x94, 0x14, 0xe5, 0x39, 0x94, 0x00, 0x22, 0x25, 0xe0, +0x24, 0x58, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0x22, 0xf8, 0xc3, 0xe2, 0x9f, 0xff, 0x18, 0xe2, +0x9e, 0xfe, 0x02, 0x00, 0x12, 0x74, 0x09, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, +0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0xfe, +0xa3, 0xe0, 0x22, 0x7c, 0x00, 0x7d, 0x05, 0x02, 0x01, 0xd9, 0x7c, 0x00, 0x7d, 0x05, 0x02, 0x01, +0x84, 0x64, 0x80, 0xf8, 0xee, 0x64, 0x80, 0x98, 0x22, 0xd3, 0xef, 0x95, 0x40, 0xee, 0x95, 0x3f, +0x22, 0xe5, 0x3a, 0x94, 0xb1, 0xe5, 0x39, 0x64, 0x80, 0x94, 0x81, 0x22, 0xd3, 0xe5, 0x36, 0x94, +0x00, 0xe5, 0x35, 0x64, 0x80, 0x94, 0x80, 0x22, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xd3, 0x94, 0xc8, +0xea, 0x94, 0x00, 0x22, 0x7f, 0x87, 0xad, 0x36, 0xf1, 0xbf, 0x8f, 0x34, 0xe5, 0x34, 0x22, 0xa9, +0x05, 0xe4, 0xfe, 0xfd, 0xfc, 0x7a, 0xff, 0xee, 0xc3, 0x99, 0x50, 0x24, 0xee, 0x6b, 0x60, 0x1b, +0xa8, 0x07, 0xe6, 0xf5, 0x83, 0x08, 0xe6, 0xf5, 0x82, 0xd3, 0x9d, 0xe5, 0x83, 0x9c, 0x40, 0x0b, +0xe5, 0x82, 0x24, 0x20, 0xfd, 0xe4, 0x35, 0x83, 0xfc, 0xaa, 0x06, 0x0e, 0x0f, 0x0f, 0x80, 0xd7, +0xaf, 0x02, 0x22, 0x8e, 0x45, 0x8f, 0x46, 0xd3, 0xe5, 0x46, 0x9d, 0xe5, 0x45, 0x9c, 0x40, 0x02, +0x80, 0x08, 0xaf, 0x05, 0xae, 0x04, 0xad, 0x46, 0xac, 0x45, 0x02, 0x14, 0xb6, 0x7f, 0x03, 0x7b, +0xfe, 0x7a, 0x00, 0x79, 0x88, 0x11, 0x2b, 0xe4, 0xf5, 0x10, 0xf5, 0x1b, 0xf5, 0x12, 0xc2, 0x01, +0xd2, 0x02, 0xc2, 0x03, 0xc2, 0x04, 0x90, 0x04, 0x57, 0xf0, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x02, +0x04, 0xdf, 0x8f, 0x23, 0x7f, 0x0c, 0xa9, 0x23, 0x7a, 0x00, 0x7b, 0x00, 0x11, 0x2b, 0x7f, 0x1c, +0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x3e, 0xd1, 0xd1, 0xe5, 0x10, 0x14, 0x60, 0x32, 0x04, 0x60, 0x02, +0x61, 0x92, 0xe4, 0xf5, 0x1b, 0xf5, 0x13, 0xf5, 0x11, 0xb1, 0xf5, 0xc2, 0x00, 0xfe, 0x7f, 0x3e, +0xfd, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x00, 0x12, 0x04, 0xdf, 0x12, 0x07, 0xe5, 0x75, 0x10, 0x01, +0x7e, 0x00, 0x7f, 0x04, 0x7d, 0xff, 0x7b, 0x01, 0x7a, 0x04, 0x79, 0x45, 0x02, 0x04, 0xdf, 0xe4, +0xf5, 0x1a, 0x12, 0x0f, 0x3d, 0xc2, 0x01, 0xe5, 0x1a, 0x30, 0xe4, 0x20, 0x05, 0x1b, 0xe5, 0x1b, +0xc3, 0x94, 0x0e, 0x40, 0x0d, 0x53, 0x1a, 0xf7, 0xe5, 0x1b, 0xb4, 0x0f, 0x05, 0xe4, 0xf5, 0x10, +0xf5, 0x1b, 0xe5, 0x11, 0xb4, 0x02, 0x08, 0x53, 0x1a, 0xf7, 0x80, 0x03, 0xe4, 0xf5, 0x1b, 0xc2, +0x07, 0xe4, 0xf5, 0x2e, 0xf5, 0x2f, 0xf5, 0x2a, 0xf5, 0x2b, 0xe5, 0x56, 0x70, 0x02, 0x21, 0x5f, +0xe4, 0xf5, 0x30, 0xf5, 0x31, 0x75, 0x24, 0x01, 0xe5, 0x24, 0x12, 0x16, 0x5e, 0xd3, 0x94, 0xb4, +0xee, 0x94, 0x00, 0x40, 0x12, 0x05, 0x31, 0xe5, 0x24, 0x12, 0x17, 0x3e, 0x12, 0x17, 0xf3, 0xef, +0xc3, 0x94, 0x32, 0x50, 0x02, 0x05, 0x30, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x5a, 0xb1, 0xda, 0xce, +0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x25, 0x2f, 0xf5, 0x2f, 0xee, 0x35, 0x2e, 0xf5, 0x2e, 0xe5, +0x24, 0x25, 0xe0, 0x24, 0x6a, 0xb1, 0xda, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x25, 0x2b, +0xf5, 0x2b, 0xee, 0x35, 0x2a, 0xf5, 0x2a, 0x05, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x08, 0x40, 0xa8, +0xe5, 0x56, 0xb4, 0x02, 0x0e, 0xe5, 0x31, 0xd3, 0x94, 0x02, 0x40, 0x02, 0xd2, 0x07, 0x53, 0x1a, +0xf7, 0x80, 0x2c, 0xe5, 0x30, 0xd3, 0x94, 0x04, 0x50, 0x11, 0xe5, 0x2f, 0x94, 0xd0, 0xe5, 0x2e, +0x94, 0x07, 0x40, 0x1b, 0xe5, 0x30, 0xd3, 0x94, 0x02, 0x40, 0x14, 0xe5, 0x2a, 0xc3, 0x13, 0xfe, +0xe5, 0x2b, 0x13, 0xff, 0xd3, 0xe5, 0x2f, 0x9f, 0xe5, 0x2e, 0x9e, 0x40, 0x02, 0xd2, 0x07, 0xe5, +0x1a, 0x20, 0xe3, 0x02, 0x61, 0x50, 0x7d, 0x08, 0xe4, 0xff, 0x12, 0x15, 0x4b, 0x7d, 0x10, 0x7f, +0x08, 0x12, 0x15, 0x4b, 0x75, 0x17, 0x3e, 0xe4, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x04, 0x50, +0x3b, 0x74, 0x95, 0x25, 0x24, 0xf8, 0xe6, 0xa8, 0x17, 0xf2, 0xc3, 0x94, 0x10, 0x50, 0x27, 0xe8, +0xd1, 0xda, 0x7d, 0xff, 0x91, 0x2c, 0x74, 0x95, 0x25, 0x24, 0xf8, 0xe6, 0xff, 0x12, 0x13, 0x98, +0x7d, 0xff, 0xb1, 0xec, 0x91, 0x34, 0xb1, 0xcb, 0x70, 0x0c, 0xa8, 0x17, 0x74, 0xff, 0xf2, 0x74, +0x95, 0x25, 0x24, 0xf8, 0x76, 0xff, 0x05, 0x24, 0x91, 0x1b, 0x80, 0xbe, 0xe4, 0xf5, 0x26, 0xf5, +0x27, 0xf5, 0x28, 0xf5, 0x29, 0x75, 0x17, 0x3e, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x02, 0x40, +0x02, 0x41, 0xe1, 0x74, 0x26, 0x25, 0x24, 0xf8, 0xe6, 0x60, 0x02, 0x41, 0xdb, 0x75, 0x18, 0x4c, +0x75, 0x25, 0x02, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x40, 0x02, 0x41, 0xdb, 0x74, 0x26, 0x25, 0x25, +0xf8, 0xe6, 0x60, 0x02, 0x41, 0xd1, 0xa8, 0x17, 0xe2, 0xf4, 0x70, 0x02, 0x41, 0xd1, 0xa8, 0x18, +0xe2, 0xf4, 0x70, 0x02, 0x41, 0xd1, 0xe8, 0x04, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24, 0x02, 0x12, +0x17, 0x49, 0x8e, 0x2a, 0x8f, 0x2b, 0x75, 0x31, 0x0a, 0x75, 0x30, 0x0a, 0xe5, 0x11, 0xb4, 0x01, +0x06, 0x75, 0x31, 0x05, 0x75, 0x30, 0x05, 0xe5, 0x17, 0x24, 0x03, 0x12, 0x16, 0x62, 0xe5, 0x18, +0x24, 0x04, 0xf8, 0xc3, 0xe2, 0x9f, 0xf5, 0x2d, 0x18, 0xe2, 0x9e, 0xf5, 0x2c, 0xe5, 0x30, 0x7e, +0x01, 0x7f, 0xe0, 0xb1, 0xd2, 0xe5, 0x2b, 0x9f, 0xe5, 0x2a, 0x9e, 0x50, 0x4b, 0xe5, 0x31, 0x7e, +0x03, 0x7f, 0xc0, 0xb1, 0xd2, 0xe5, 0x2d, 0x9f, 0xe5, 0x2c, 0x9e, 0x50, 0x3b, 0xa8, 0x17, 0xe2, +0xff, 0xa8, 0x18, 0xe2, 0xfd, 0x71, 0x96, 0xef, 0xf4, 0x60, 0x25, 0xe5, 0x2c, 0xc3, 0x13, 0xe5, +0x2d, 0x13, 0x90, 0x04, 0x58, 0xf0, 0xad, 0x25, 0x91, 0x2c, 0xad, 0x25, 0xb1, 0xec, 0x91, 0x34, +0x74, 0x26, 0x25, 0x24, 0xf8, 0x76, 0x01, 0x74, 0x26, 0x25, 0x25, 0xf8, 0x76, 0x01, 0x80, 0x04, +0xa8, 0x17, 0x91, 0x22, 0xa8, 0x18, 0x80, 0x37, 0xa8, 0x17, 0xe2, 0x91, 0x14, 0xf5, 0x2c, 0x08, +0xe2, 0xf5, 0x2d, 0xa8, 0x18, 0xe2, 0x91, 0x14, 0xf5, 0x2e, 0x08, 0xe2, 0xf5, 0x2f, 0xfd, 0xac, +0x2e, 0xaf, 0x2d, 0xae, 0x2c, 0x12, 0x17, 0xf3, 0xef, 0xd3, 0x94, 0x32, 0x40, 0x13, 0xd3, 0xe5, +0x2d, 0x95, 0x2f, 0xe5, 0x2c, 0x95, 0x2e, 0x40, 0x04, 0xa8, 0x18, 0x80, 0x02, 0xa8, 0x17, 0x91, +0x22, 0x05, 0x25, 0x74, 0x07, 0x25, 0x18, 0xf5, 0x18, 0x21, 0xe3, 0x05, 0x24, 0x91, 0x1b, 0x21, +0xca, 0x75, 0x17, 0x3e, 0xe4, 0xf5, 0x24, 0xe5, 0x24, 0xc3, 0x94, 0x02, 0x50, 0x62, 0x74, 0x26, +0x25, 0x24, 0xf8, 0xe6, 0x70, 0x54, 0xa8, 0x17, 0xe2, 0xff, 0xf4, 0x60, 0x0d, 0x7d, 0xff, 0x71, +0x96, 0xa8, 0x17, 0xef, 0xf2, 0xbf, 0xff, 0x02, 0x91, 0x25, 0xa8, 0x17, 0xe2, 0xf4, 0x70, 0x3a, +0x75, 0x18, 0x4c, 0x75, 0x25, 0x02, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x50, 0x2d, 0x74, 0x26, 0x25, +0x25, 0xf8, 0xe6, 0x70, 0x1b, 0xa8, 0x18, 0xe2, 0xff, 0xf4, 0x60, 0x14, 0x7d, 0xff, 0x71, 0x96, +0xa8, 0x18, 0xef, 0xf2, 0xf4, 0x60, 0x09, 0xb1, 0xae, 0xa8, 0x18, 0x74, 0xff, 0xf2, 0x80, 0x0a, +0x05, 0x25, 0x74, 0x07, 0x25, 0x18, 0xf5, 0x18, 0x80, 0xcc, 0x05, 0x24, 0x91, 0x1b, 0x80, 0x97, +0xe5, 0x13, 0x60, 0x04, 0x15, 0x13, 0x80, 0x03, 0xe4, 0xb1, 0xf5, 0xe5, 0x12, 0x60, 0x02, 0x15, +0x12, 0xc2, 0x00, 0x75, 0x17, 0x3e, 0x75, 0x18, 0x45, 0x91, 0x3b, 0x12, 0x24, 0x8c, 0xa8, 0x23, +0x7c, 0x00, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x3f, 0xd1, 0xea, 0xe5, 0x23, 0x24, 0x06, +0xf8, 0x7c, 0x00, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x46, 0x7e, 0x00, 0x7f, 0x06, 0x02, +0x00, 0xf4, 0xe4, 0xf5, 0x10, 0x22, 0x8f, 0x32, 0xef, 0x91, 0x14, 0xfe, 0x08, 0xe2, 0xfb, 0xaa, +0x06, 0xed, 0xf4, 0x60, 0x0b, 0xed, 0x91, 0x14, 0xfe, 0x08, 0xe2, 0x2b, 0xfb, 0xee, 0x3a, 0xfa, +0x90, 0x03, 0xe8, 0xaf, 0x32, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x0a, 0x78, 0x68, 0xe2, 0xfe, 0x08, +0xe2, 0x78, 0x79, 0xd1, 0x22, 0xaf, 0x32, 0x12, 0x16, 0xa6, 0xbf, 0x02, 0x0a, 0x78, 0x6a, 0xe2, +0xfe, 0x08, 0xe2, 0x78, 0x5b, 0xd1, 0x22, 0xe5, 0x15, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0x14, 0x35, +0x83, 0xf5, 0x83, 0x30, 0x04, 0x03, 0x75, 0x12, 0x14, 0xe5, 0x12, 0x60, 0x19, 0xe5, 0x13, 0x70, +0x15, 0xfc, 0x7d, 0x03, 0xaf, 0x82, 0xae, 0x83, 0x12, 0x01, 0x84, 0xc3, 0xe5, 0x82, 0x9f, 0xf5, +0x82, 0xe5, 0x83, 0x9e, 0xf5, 0x83, 0xc3, 0xeb, 0x95, 0x82, 0xea, 0x95, 0x83, 0xaf, 0x32, 0x50, +0x02, 0x7f, 0xff, 0x22, 0x25, 0xe0, 0x24, 0x5a, 0xf8, 0xe2, 0x22, 0x74, 0x07, 0x25, 0x17, 0xf5, +0x17, 0x22, 0x74, 0xff, 0xf2, 0xe8, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x22, 0xaf, 0x24, 0x12, 0x21, +0xa7, 0xe5, 0x17, 0x04, 0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x22, 0xe4, 0xf5, 0x33, 0xf5, 0x34, +0xf5, 0x32, 0xb1, 0xcb, 0x70, 0x11, 0xe5, 0x18, 0x24, 0x05, 0xf8, 0xe2, 0x60, 0x09, 0xb1, 0xae, +0xe5, 0x18, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0xb1, 0xcb, 0x60, 0x02, 0x05, 0x33, 0xe5, 0x18, 0x24, +0x05, 0xf8, 0xe2, 0x60, 0x02, 0x05, 0x33, 0x78, 0x1d, 0xe2, 0xff, 0x60, 0x02, 0x05, 0x34, 0x78, +0x3c, 0xe2, 0x60, 0x02, 0x05, 0x34, 0xe5, 0x33, 0x70, 0x03, 0x30, 0x01, 0x02, 0xd2, 0x00, 0x75, +0x35, 0x00, 0x75, 0x36, 0xb4, 0x90, 0x04, 0x57, 0xe0, 0xfe, 0x70, 0x04, 0xe5, 0x13, 0x60, 0x0f, +0x75, 0x35, 0x01, 0x75, 0x36, 0x2c, 0xee, 0x60, 0x06, 0x90, 0x04, 0x57, 0xe0, 0x14, 0xf0, 0xe5, +0x33, 0x64, 0x01, 0x70, 0x69, 0xe5, 0x34, 0x70, 0x02, 0xa1, 0x84, 0xe5, 0x34, 0x64, 0x01, 0x70, +0x45, 0xef, 0x60, 0x1e, 0xe4, 0xfd, 0xb1, 0xa5, 0x78, 0x0b, 0xd1, 0x00, 0x50, 0x06, 0x75, 0x39, +0x00, 0x75, 0x3a, 0x0a, 0xb1, 0xe2, 0x50, 0x02, 0xa1, 0x84, 0xd1, 0x0f, 0x50, 0x02, 0xa1, 0x84, +0xa1, 0x81, 0x78, 0x3c, 0xe2, 0x70, 0x02, 0xa1, 0x84, 0x7d, 0x01, 0xe4, 0xb1, 0xa5, 0x78, 0x2a, +0xd1, 0x00, 0x50, 0x06, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x0a, 0xb1, 0xe2, 0x40, 0x06, 0xd1, 0x0f, +0x40, 0x02, 0xa1, 0x84, 0xa1, 0x81, 0xe5, 0x34, 0x64, 0x02, 0x60, 0x02, 0xa1, 0x84, 0xfd, 0xb1, +0xa5, 0x12, 0x16, 0x69, 0x8e, 0x39, 0x8f, 0x3a, 0xb1, 0xc1, 0x40, 0x78, 0x80, 0x73, 0xe5, 0x33, +0x64, 0x02, 0x70, 0x70, 0xe5, 0x34, 0x60, 0x6c, 0xe5, 0x34, 0x64, 0x01, 0x70, 0x26, 0x78, 0x1d, +0xe2, 0x60, 0x0a, 0xe4, 0xfd, 0xb1, 0xa5, 0xe4, 0xfd, 0x7f, 0x01, 0x80, 0x0a, 0x7d, 0x01, 0x7f, +0x01, 0xb1, 0xa6, 0x7d, 0x01, 0xe4, 0xff, 0x12, 0x16, 0x6d, 0x8e, 0x39, 0x8f, 0x3a, 0xb1, 0xc1, +0x40, 0x42, 0x80, 0x3d, 0xe5, 0x34, 0x64, 0x02, 0x70, 0x3a, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x16, +0x6d, 0xc0, 0x06, 0xc0, 0x07, 0xe4, 0xfd, 0xff, 0x12, 0x16, 0x6d, 0xd0, 0xe0, 0x2f, 0xf5, 0x38, +0xd0, 0xe0, 0x3e, 0xf5, 0x37, 0xe4, 0xfd, 0x7f, 0x01, 0x12, 0x16, 0x6d, 0xc0, 0x06, 0xc0, 0x07, +0x12, 0x16, 0x69, 0xd0, 0xe0, 0x2f, 0xf5, 0x3a, 0xd0, 0xe0, 0x3e, 0xf5, 0x39, 0xb1, 0xc1, 0x40, +0x03, 0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1c, 0xa9, 0x17, 0x7a, 0x00, 0x7b, 0xfe, 0xe5, 0x18, +0x24, 0x07, 0xf8, 0xb1, 0xb6, 0xb1, 0xae, 0xe5, 0x18, 0x24, 0x07, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, +0xa8, 0x18, 0xb1, 0xb6, 0x22, 0xff, 0x12, 0x16, 0x6d, 0x8e, 0x37, 0x8f, 0x38, 0x22, 0xa9, 0x18, +0x7a, 0x00, 0x7b, 0xfe, 0xa8, 0x17, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x07, 0x02, 0x00, +0xf4, 0xd3, 0xe5, 0x38, 0x95, 0x3a, 0xe5, 0x37, 0x95, 0x39, 0x22, 0xe5, 0x17, 0x24, 0x05, 0xf8, +0xe2, 0x22, 0xfd, 0x7c, 0x00, 0x12, 0x01, 0x84, 0xc3, 0x22, 0xf9, 0xe3, 0xfe, 0x09, 0xe3, 0x78, +0x03, 0x22, 0xd3, 0xe5, 0x38, 0x95, 0x36, 0xe5, 0x37, 0x95, 0x35, 0x22, 0xaf, 0x24, 0xf1, 0xcc, +0xe5, 0x17, 0x24, 0x03, 0x22, 0xf5, 0x14, 0xf5, 0x15, 0x90, 0x03, 0x2f, 0xf0, 0xa3, 0xf0, 0x22, +0xe2, 0xf5, 0x39, 0x08, 0xe2, 0xf5, 0x3a, 0xc3, 0x94, 0x0a, 0xe5, 0x39, 0x94, 0x00, 0x22, 0xae, +0x39, 0xaf, 0x3a, 0x7c, 0x00, 0x7d, 0x06, 0x12, 0x01, 0x72, 0xd3, 0xe5, 0x38, 0x9f, 0xe5, 0x37, +0x9e, 0x22, 0xff, 0xe2, 0x2f, 0xff, 0x18, 0xe2, 0x3e, 0xc3, 0x13, 0xfe, 0xef, 0x13, 0x24, 0x84, +0xf5, 0x82, 0xee, 0x34, 0x03, 0xf5, 0x83, 0x22, 0xab, 0x07, 0xaa, 0x05, 0x90, 0x00, 0x01, 0xeb, +0x91, 0x14, 0xf5, 0x45, 0x08, 0xe2, 0xf5, 0x46, 0xaf, 0x03, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x10, +0xe5, 0x82, 0x64, 0x01, 0x45, 0x83, 0x70, 0x67, 0xea, 0x64, 0x01, 0x70, 0x62, 0x0b, 0x80, 0x5f, +0xaf, 0x03, 0x12, 0x16, 0xa6, 0xbf, 0x02, 0x0f, 0xe5, 0x82, 0x64, 0x01, 0x45, 0x83, 0x70, 0x4f, +0xea, 0xf4, 0x70, 0x4b, 0x1b, 0x80, 0x48, 0xeb, 0x91, 0x14, 0xf5, 0x47, 0x08, 0xe2, 0xf5, 0x48, +0xea, 0x2b, 0xfb, 0xae, 0x45, 0xaf, 0x46, 0x7c, 0x00, 0x7d, 0x1e, 0x12, 0x01, 0x84, 0xeb, 0x25, +0xe0, 0x24, 0x5a, 0x12, 0x17, 0x42, 0xd3, 0x9f, 0xec, 0x9e, 0x40, 0x10, 0xe5, 0x48, 0x24, 0xc8, +0xff, 0xe4, 0x35, 0x47, 0xfe, 0xd3, 0xed, 0x9f, 0xec, 0x9e, 0x40, 0x06, 0xc3, 0xeb, 0x9a, 0xfb, +0x80, 0x0d, 0xe5, 0x82, 0x15, 0x82, 0xae, 0x83, 0x70, 0x02, 0x15, 0x83, 0x4e, 0x70, 0x89, 0xd3, +0xea, 0x64, 0x80, 0x94, 0x80, 0x7f, 0x00, 0x40, 0x02, 0x7f, 0x01, 0xef, 0x2b, 0x25, 0xe0, 0xff, +0x22, 0x7e, 0x00, 0x7d, 0x00, 0x02, 0x04, 0xdf, 0xe5, 0x17, 0x24, 0x05, 0xf8, 0x74, 0x01, 0xf2, +0x22, 0x7a, 0x00, 0x7b, 0xfe, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x00, +0xf4, 0xe4, 0xff, 0xfe, 0xfd, 0xfc, 0x78, 0x6a, 0x12, 0x04, 0x64, 0xc3, 0x12, 0x04, 0x21, 0x60, +0x08, 0x78, 0x6e, 0xe6, 0xd3, 0x94, 0x05, 0x40, 0x03, 0x7f, 0xff, 0x22, 0x7f, 0x16, 0x7b, 0x00, +0x7a, 0x00, 0x79, 0x2c, 0xd1, 0xd1, 0xe4, 0xf5, 0x2a, 0x78, 0x6e, 0xe6, 0xff, 0xd3, 0x94, 0x00, +0x40, 0x1a, 0xef, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0, 0xfb, 0x78, 0x6a, 0x12, 0x04, 0x58, 0xa8, +0x03, 0x12, 0x04, 0x32, 0xef, 0x54, 0x0f, 0xff, 0x8f, 0x4c, 0x80, 0x03, 0xe4, 0xf5, 0x4c, 0xe4, +0xf5, 0x2b, 0x74, 0x2c, 0x25, 0x2b, 0xf8, 0xe6, 0x70, 0x63, 0xe5, 0x2b, 0x75, 0xf0, 0x0a, 0xa4, +0x24, 0x16, 0xf5, 0x82, 0xe4, 0x34, 0x06, 0xf5, 0x83, 0x75, 0xf0, 0x02, 0xe5, 0x2a, 0x12, 0x04, +0x96, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfd, 0xac, 0x06, 0x54, 0x0f, 0xab, 0x4c, 0x6b, 0x70, +0x01, 0xe4, 0x60, 0x2f, 0xec, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0xed, 0xc4, 0x54, 0x0f, 0x48, 0x54, +0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x1c, 0xec, 0x54, 0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x13, +0xec, 0xc4, 0x54, 0x0f, 0x6b, 0x70, 0x01, 0xe4, 0x60, 0x09, 0x74, 0x2c, 0x25, 0x2b, 0xf8, 0x76, +0x01, 0x80, 0x0a, 0xe5, 0x2a, 0xb4, 0x04, 0x05, 0xe5, 0x2b, 0x04, 0xff, 0x22, 0x05, 0x2b, 0xe5, +0x2b, 0x64, 0x16, 0x70, 0x8d, 0x78, 0x6e, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x01, 0x16, 0x05, 0x2a, +0xe5, 0x2a, 0xd3, 0x94, 0x04, 0x50, 0x02, 0xe1, 0x19, 0x7f, 0xff, 0x22, 0x8f, 0x32, 0x8d, 0x33, +0xe4, 0xf5, 0x3b, 0xf5, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xf5, 0x3f, 0xf5, 0x3e, 0xf5, 0x3d, 0xf5, +0x3c, 0x85, 0x32, 0x35, 0xe5, 0x35, 0x12, 0x23, 0xe3, 0xf9, 0xff, 0x7d, 0xff, 0xd1, 0x38, 0x8f, +0x34, 0xaf, 0x01, 0x7d, 0x01, 0xd1, 0x38, 0x8f, 0x44, 0xe5, 0x33, 0xf4, 0x60, 0x28, 0xe9, 0x14, +0xf5, 0x34, 0xe9, 0x24, 0x02, 0xf5, 0x44, 0xaf, 0x01, 0x12, 0x16, 0xa6, 0xbf, 0x01, 0x04, 0x89, +0x34, 0x80, 0x07, 0xbf, 0x02, 0x04, 0xe9, 0x04, 0xf5, 0x44, 0xe5, 0x34, 0x25, 0xe0, 0xf5, 0x34, +0xe5, 0x44, 0x25, 0xe0, 0xf5, 0x44, 0x90, 0x04, 0x58, 0xe0, 0xff, 0xd3, 0x94, 0x14, 0x40, 0x02, +0x80, 0x02, 0x7f, 0x14, 0x75, 0x42, 0x00, 0x8f, 0x43, 0xae, 0x42, 0x7d, 0x07, 0x31, 0x8f, 0xef, +0x25, 0x43, 0xf5, 0x43, 0xee, 0x35, 0x42, 0xf5, 0x42, 0xe5, 0x34, 0xc3, 0x95, 0x44, 0x50, 0x7d, +0x75, 0xf0, 0x02, 0xe5, 0x34, 0x90, 0x06, 0xf6, 0x12, 0x04, 0x96, 0xe4, 0x93, 0xf5, 0x40, 0x74, +0x01, 0x93, 0xf5, 0x41, 0xe5, 0x33, 0xf4, 0x60, 0x2a, 0xe5, 0x34, 0xc3, 0x94, 0x10, 0x50, 0x11, +0xc3, 0x90, 0x06, 0xf2, 0x74, 0x01, 0x93, 0x95, 0x43, 0xff, 0xe4, 0x93, 0x95, 0x42, 0xfe, 0x80, +0x0e, 0x90, 0x06, 0xf4, 0x74, 0x01, 0x93, 0x25, 0x43, 0xff, 0xe4, 0x93, 0x35, 0x42, 0xfe, 0x8e, +0x40, 0x8f, 0x41, 0xe5, 0x34, 0x12, 0x13, 0x8c, 0xe0, 0xf5, 0x36, 0xa3, 0xe0, 0xf5, 0x37, 0xff, +0xe4, 0xfc, 0xfd, 0xe5, 0x3f, 0x2f, 0xff, 0xe5, 0x3e, 0x35, 0x36, 0xfe, 0xed, 0x35, 0x3d, 0xfd, +0xec, 0x35, 0x3c, 0x8f, 0x3f, 0x8e, 0x3e, 0x8d, 0x3d, 0xf5, 0x3c, 0xae, 0x36, 0xaf, 0x37, 0x91, +0x36, 0xae, 0x40, 0xaf, 0x41, 0x91, 0x3e, 0x91, 0x10, 0x05, 0x34, 0x01, 0x49, 0xe5, 0x35, 0x65, +0x33, 0x60, 0x0b, 0xe5, 0x33, 0xf4, 0x60, 0x06, 0x85, 0x33, 0x35, 0x02, 0x1f, 0xe4, 0xe4, 0x7b, +0x02, 0xfa, 0xf9, 0xf8, 0xaf, 0x3f, 0xae, 0x3e, 0xad, 0x3d, 0xac, 0x3c, 0x12, 0x05, 0xa8, 0x91, +0x10, 0xfc, 0xab, 0x3f, 0xaa, 0x3e, 0xa9, 0x3d, 0xa8, 0x3c, 0x12, 0x05, 0xa8, 0x8f, 0x3b, 0x8e, +0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x8e, 0x36, 0x8f, 0x37, 0xe5, 0x33, 0xf4, 0x70, 0x3b, 0xf5, 0x42, +0x75, 0x43, 0x05, 0xe5, 0x32, 0x71, 0xe3, 0xc3, 0x94, 0x08, 0x50, 0x16, 0xc3, 0x74, 0xe0, 0x95, +0x43, 0xff, 0x74, 0x01, 0x95, 0x42, 0xfe, 0xd3, 0xe5, 0x37, 0x9f, 0xe5, 0x36, 0x9e, 0x40, 0x19, +0x80, 0x13, 0xe5, 0x43, 0x24, 0xe0, 0xff, 0xe5, 0x42, 0x34, 0x01, 0xfe, 0xc3, 0xe5, 0x37, 0x9f, +0xe5, 0x36, 0x9e, 0x50, 0x04, 0x8e, 0x36, 0x8f, 0x37, 0xac, 0x38, 0xec, 0x33, 0x50, 0x1e, 0x74, +0xff, 0x7f, 0x9c, 0xfe, 0xfd, 0xfc, 0xab, 0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xc3, 0x12, +0x04, 0x0b, 0x50, 0x02, 0x31, 0x9b, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0x80, 0x1d, 0xc3, 0xe5, 0x37, +0x94, 0xc0, 0xe5, 0x36, 0x94, 0x03, 0x40, 0x12, 0xe5, 0x37, 0x94, 0x24, 0xe5, 0x36, 0x94, 0x04, +0x40, 0x02, 0x31, 0x9b, 0x75, 0x36, 0x03, 0x75, 0x37, 0xbf, 0xae, 0x36, 0xaf, 0x37, 0x22, 0x7c, +0x00, 0x12, 0x01, 0xd9, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x01, 0x72, 0xe5, 0x35, 0x75, 0xf0, 0x07, +0xa4, 0x24, 0x43, 0xf8, 0xe4, 0xf2, 0x22, 0x8d, 0x32, 0xab, 0x07, 0xe4, 0xf5, 0x44, 0xf5, 0x43, +0xf5, 0x42, 0xf5, 0x41, 0xf5, 0x48, 0xf5, 0x47, 0xf5, 0x46, 0xf5, 0x45, 0x8b, 0x33, 0xe5, 0x33, +0x71, 0xe3, 0xf5, 0x49, 0xf5, 0x4a, 0xe5, 0x4a, 0xc3, 0x94, 0x08, 0x40, 0x06, 0x74, 0xf8, 0x25, +0x4a, 0xf5, 0x4a, 0xe5, 0x49, 0x25, 0xe0, 0x24, 0x58, 0xf8, 0xe2, 0xf5, 0x35, 0x08, 0xe2, 0xf5, +0x36, 0xe5, 0x49, 0x12, 0x1c, 0x14, 0xf5, 0x37, 0x08, 0xe2, 0xf5, 0x38, 0xe5, 0x49, 0x25, 0xe0, +0x24, 0x5c, 0xf8, 0xe2, 0xf5, 0x39, 0x08, 0xe2, 0xf5, 0x3a, 0x30, 0x02, 0x05, 0x71, 0xdb, 0xff, +0x80, 0x1e, 0xae, 0x37, 0xaf, 0x38, 0x91, 0x2f, 0x7c, 0x00, 0x7d, 0x09, 0x12, 0x01, 0x72, 0xaa, +0x06, 0xab, 0x07, 0x71, 0xdb, 0xff, 0x0d, 0x12, 0x01, 0x84, 0xeb, 0x2f, 0xff, 0xea, 0x3e, 0xfe, +0xab, 0x07, 0xaa, 0x06, 0xe5, 0x4a, 0x70, 0x4f, 0x30, 0x02, 0x05, 0xfe, 0x7f, 0x20, 0x80, 0x04, +0x7e, 0x00, 0x7f, 0x30, 0x8e, 0x3f, 0x8f, 0x40, 0xae, 0x39, 0xaf, 0x3a, 0x71, 0xfc, 0x50, 0x0b, +0xc3, 0xe5, 0x3a, 0x94, 0x2c, 0xe5, 0x39, 0x94, 0x01, 0x50, 0x06, 0xd2, 0x01, 0xe5, 0x33, 0x31, +0x9d, 0x12, 0x1d, 0xc1, 0x40, 0x17, 0xe5, 0x38, 0x95, 0x3a, 0xff, 0xe5, 0x37, 0x95, 0x39, 0xfe, +0x7c, 0x00, 0x7d, 0x06, 0x12, 0x01, 0x72, 0x1d, 0x12, 0x01, 0x84, 0x80, 0x04, 0x7e, 0x00, 0x7f, +0x00, 0x8e, 0x35, 0x8f, 0x36, 0x80, 0x63, 0xe5, 0x4a, 0x64, 0x07, 0x70, 0x44, 0x30, 0x02, 0x05, +0xfe, 0x7f, 0x20, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x30, 0x8e, 0x3f, 0x8f, 0x40, 0xae, 0x35, 0xaf, +0x36, 0x71, 0xfc, 0x50, 0x0b, 0xc3, 0xe5, 0x36, 0x94, 0x90, 0xe5, 0x35, 0x94, 0x01, 0x50, 0x06, +0xd2, 0x01, 0xe5, 0x33, 0x31, 0x9d, 0x12, 0x1d, 0xe2, 0x40, 0x0c, 0xe5, 0x38, 0x95, 0x36, 0xff, +0xe5, 0x37, 0x95, 0x35, 0xfe, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x8e, 0x39, 0x8f, 0x3a, 0x80, +0x19, 0xe5, 0x38, 0xae, 0x37, 0x78, 0x03, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xc3, +0xe5, 0x38, 0x9f, 0xf5, 0x38, 0xe5, 0x37, 0x9e, 0xf5, 0x37, 0xe4, 0xf5, 0x34, 0xe5, 0x4a, 0x25, +0x34, 0xf5, 0x4f, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xfe, 0x74, +0xa1, 0x2f, 0xf5, 0x82, 0x74, 0x07, 0x3e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, +0xe4, 0x8f, 0x4e, 0x8e, 0x4d, 0xf5, 0x4c, 0xf5, 0x4b, 0xab, 0x4e, 0xaa, 0x4d, 0xa9, 0x4c, 0xa8, +0x4b, 0xc0, 0x00, 0x71, 0xec, 0xd0, 0x00, 0x12, 0x02, 0xe1, 0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c, +0x8c, 0x4b, 0xe5, 0x48, 0x25, 0x4e, 0xff, 0xe5, 0x47, 0x35, 0x4d, 0xfe, 0xe5, 0x46, 0x35, 0x4c, +0xfd, 0xe5, 0x45, 0x35, 0x4b, 0x71, 0xd4, 0xf5, 0x45, 0x71, 0xec, 0xe5, 0x44, 0x2f, 0xff, 0xe5, +0x43, 0x3e, 0xfe, 0xed, 0x35, 0x42, 0xfd, 0xec, 0x35, 0x41, 0x91, 0x28, 0xf5, 0x41, 0x05, 0x34, +0xe5, 0x34, 0x64, 0x03, 0x70, 0x87, 0xe5, 0x33, 0xb5, 0x32, 0x02, 0x80, 0x0c, 0xe5, 0x32, 0xb4, +0xff, 0x02, 0x80, 0x05, 0x85, 0x32, 0x33, 0x21, 0xbe, 0xe4, 0x7b, 0x02, 0xfa, 0xf9, 0xf8, 0xaf, +0x44, 0xae, 0x43, 0xad, 0x42, 0xac, 0x41, 0x12, 0x03, 0x6c, 0xab, 0x48, 0xaa, 0x47, 0xa9, 0x46, +0xa8, 0x45, 0x12, 0x02, 0xd4, 0xab, 0x44, 0xaa, 0x43, 0xa9, 0x42, 0xa8, 0x41, 0x12, 0x03, 0x6c, +0x71, 0xd4, 0x8c, 0x45, 0xe4, 0x7b, 0x10, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xa8, 0x71, 0xd4, 0x8c, +0x45, 0xe5, 0x48, 0x24, 0xba, 0xff, 0xe5, 0x47, 0x34, 0xff, 0xfe, 0xe5, 0x46, 0x34, 0xff, 0xfd, +0xe5, 0x45, 0x34, 0xff, 0x71, 0xd4, 0xf5, 0x45, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0x12, 0x16, +0xbd, 0xef, 0x24, 0x01, 0xff, 0xe4, 0x3e, 0xfe, 0x33, 0x95, 0xe0, 0x8f, 0x48, 0x8e, 0x47, 0xf5, +0x46, 0xf5, 0x45, 0x22, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x22, 0x90, 0x03, 0x2f, 0xe0, 0xfe, +0xa3, 0xe0, 0x22, 0x75, 0xf0, 0x07, 0xa4, 0x24, 0x3e, 0xf8, 0xe2, 0x22, 0xe5, 0x34, 0x25, 0xe0, +0x24, 0x35, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0x7c, 0x00, 0x7d, 0x0a, +0x12, 0x01, 0x84, 0xac, 0x3f, 0xad, 0x40, 0x12, 0x01, 0x72, 0xc3, 0xeb, 0x9f, 0xea, 0x9e, 0x22, +0xe5, 0x3b, 0x2f, 0xff, 0xe5, 0x3a, 0x3e, 0xfe, 0xe5, 0x39, 0x3d, 0xfd, 0xe5, 0x38, 0x3c, 0x8f, +0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0xf5, 0x38, 0x22, 0x8f, 0x44, 0x8e, 0x43, 0x8d, 0x42, 0x22, 0x7c, +0x00, 0x7d, 0x0a, 0x02, 0x01, 0x84, 0xab, 0x07, 0xaa, 0x06, 0xe4, 0xf9, 0xf8, 0x22, 0xee, 0x33, +0x95, 0xe0, 0xfd, 0xfc, 0x02, 0x02, 0xe1, 0xc3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x23, 0xed, 0x9b, +0xec, 0x9a, 0x40, 0x06, 0x8c, 0x83, 0x8d, 0x82, 0x80, 0x11, 0xc3, 0xef, 0x9b, 0xee, 0x9a, 0x40, +0x06, 0x8a, 0x83, 0x8b, 0x82, 0x80, 0x04, 0x8e, 0x83, 0x8f, 0x82, 0xae, 0x83, 0xaf, 0x82, 0x80, +0x1a, 0xc3, 0xef, 0x9b, 0xee, 0x9a, 0x40, 0x02, 0x80, 0x11, 0xc3, 0xed, 0x9b, 0xec, 0x9a, 0x40, +0x06, 0xae, 0x02, 0xaf, 0x03, 0x80, 0x04, 0xae, 0x04, 0xaf, 0x05, 0x22, 0x75, 0x16, 0x00, 0x75, +0x17, 0x3e, 0xe4, 0xf5, 0x11, 0xc2, 0x04, 0xf5, 0x32, 0xe5, 0x32, 0xc3, 0x94, 0x02, 0x40, 0x03, +0x02, 0x2e, 0xd7, 0x12, 0x1d, 0xcb, 0x70, 0x03, 0x02, 0x2d, 0x76, 0xe5, 0x17, 0x04, 0xf8, 0xe2, +0xf5, 0x41, 0x08, 0xe2, 0xf5, 0x42, 0xe5, 0x17, 0x24, 0x03, 0xf8, 0xe2, 0xf5, 0x43, 0x08, 0xe2, +0xf5, 0x44, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x05, 0x40, 0x02, 0xc1, 0xa9, 0xa8, 0x16, +0xe4, 0xf2, 0xe8, 0x12, 0x2f, 0xab, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x02, 0x40, 0x36, 0x12, 0x39, +0x7d, 0x12, 0x3a, 0x4d, 0xff, 0xee, 0x95, 0x43, 0xfe, 0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07, +0x12, 0x39, 0x94, 0x12, 0x17, 0x6c, 0xc3, 0x95, 0x42, 0xff, 0xee, 0x95, 0x41, 0xfe, 0x12, 0x00, +0x12, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xd3, 0xef, 0x94, 0xc8, 0xee, 0x64, 0x80, +0x94, 0x80, 0x40, 0x0d, 0x12, 0x39, 0x69, 0x12, 0x3a, 0x05, 0x12, 0x39, 0xd9, 0xe4, 0xf0, 0xc1, +0x0e, 0x12, 0x39, 0x94, 0x12, 0x17, 0x6c, 0xc3, 0x95, 0x42, 0xf5, 0x34, 0xee, 0x95, 0x41, 0xf5, +0x33, 0x12, 0x39, 0x7d, 0x12, 0x3a, 0x4d, 0xf5, 0x36, 0xee, 0x95, 0x43, 0xf5, 0x35, 0xaf, 0x36, +0xfe, 0x12, 0x00, 0x12, 0x8e, 0x47, 0x8f, 0x48, 0x12, 0x3a, 0x55, 0x8e, 0x45, 0x8f, 0x46, 0xc3, +0xe5, 0x48, 0x94, 0x0c, 0xe5, 0x47, 0x94, 0x00, 0x50, 0x04, 0x7f, 0x02, 0x80, 0x1b, 0xd3, 0xe5, +0x48, 0x94, 0x2d, 0xe5, 0x47, 0x94, 0x00, 0x50, 0x0a, 0xe5, 0x46, 0x94, 0x1e, 0xe5, 0x45, 0x94, +0x00, 0x40, 0x04, 0x7f, 0xff, 0x80, 0x02, 0x7f, 0x04, 0x12, 0x39, 0xd9, 0xe0, 0x5f, 0x60, 0x07, +0xe5, 0x16, 0x04, 0xf8, 0x74, 0x04, 0xf2, 0x12, 0x39, 0xd9, 0xef, 0xf0, 0x30, 0xe3, 0x50, 0xae, +0x33, 0xaf, 0x34, 0x31, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0xef, 0x25, 0x42, 0xf5, 0x4a, 0xee, 0x35, +0x41, 0xf5, 0x49, 0xae, 0x35, 0xaf, 0x36, 0x31, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0xef, 0x25, 0x44, +0xf5, 0x4c, 0xee, 0x35, 0x43, 0xf5, 0x4b, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0xaf, 0x4a, 0xae, +0x49, 0x12, 0x16, 0xbd, 0x8e, 0x41, 0x8f, 0x42, 0x7b, 0xbf, 0x7a, 0x03, 0xaf, 0x4c, 0xae, 0x4b, +0x12, 0x16, 0xbd, 0x8e, 0x43, 0x8f, 0x44, 0x90, 0x04, 0x57, 0x74, 0x06, 0xf0, 0x80, 0x2f, 0x12, +0x39, 0x94, 0x12, 0x17, 0x6c, 0x25, 0x42, 0xff, 0xe5, 0x41, 0x3e, 0xc3, 0x13, 0xf5, 0x41, 0xef, +0x13, 0xf5, 0x42, 0x12, 0x39, 0x7d, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, 0x44, 0xff, 0xe5, 0x43, 0x3e, +0xc3, 0x13, 0xf5, 0x43, 0xef, 0x13, 0xf5, 0x44, 0x12, 0x39, 0x69, 0x12, 0x3a, 0x05, 0xe5, 0x16, +0x04, 0xf8, 0xe2, 0x04, 0xf2, 0xe5, 0x17, 0x04, 0x12, 0x39, 0xee, 0xe5, 0x17, 0x24, 0x03, 0x12, +0x39, 0xe5, 0xe5, 0x16, 0x24, 0x11, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x13, 0x12, 0x39, 0xe5, +0xe5, 0x16, 0x24, 0x0d, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x0f, 0x12, 0x39, 0xe5, 0xe5, 0x16, +0x24, 0x19, 0x12, 0x39, 0xee, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x39, 0xe5, 0xe5, 0x16, 0x24, 0x0b, +0x12, 0x2f, 0xb6, 0x24, 0x03, 0x12, 0x2f, 0xb6, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0x12, +0x2e, 0xf2, 0xf5, 0x83, 0xe4, 0xf0, 0xa3, 0xf0, 0x12, 0x2e, 0xe6, 0xf5, 0x83, 0xe4, 0xf0, 0xa3, +0xf0, 0x30, 0x05, 0x07, 0xe5, 0x16, 0x04, 0xf8, 0x74, 0x05, 0xf2, 0xc3, 0xe5, 0x44, 0x94, 0x40, +0xe5, 0x43, 0x94, 0x02, 0x50, 0x0c, 0xe5, 0x44, 0x94, 0x80, 0xe5, 0x43, 0x94, 0x01, 0x40, 0x02, +0xd2, 0x03, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xc3, 0x94, 0x05, 0x40, 0x03, 0x02, 0x2d, 0x63, 0xe5, +0x17, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0x02, 0x2d, 0x63, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, +0xc3, 0xe5, 0x44, 0x9f, 0xff, 0xe5, 0x43, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07, +0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0x12, 0x3a, 0x34, 0x12, 0x00, 0x12, 0xd0, 0xe0, 0x2f, +0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xe5, 0x16, 0x24, 0x0b, 0x12, 0x1c, 0x34, 0xe5, 0x16, 0x24, 0x0c, +0xf9, 0xd3, 0xe3, 0x94, 0x64, 0x19, 0xe3, 0x94, 0x00, 0x40, 0x06, 0x90, 0x04, 0x57, 0x74, 0x14, +0xf0, 0x12, 0x39, 0x94, 0xf5, 0x83, 0x12, 0x3a, 0x3e, 0x24, 0x19, 0x12, 0x17, 0x42, 0xaf, 0x42, +0xae, 0x41, 0x91, 0x47, 0x8e, 0x33, 0x8f, 0x34, 0x12, 0x39, 0x7d, 0x12, 0x3a, 0x3e, 0x24, 0x1b, +0x12, 0x17, 0x42, 0xaf, 0x44, 0xae, 0x43, 0x91, 0x47, 0x8e, 0x35, 0x8f, 0x36, 0x12, 0x39, 0x69, +0x12, 0x3a, 0x05, 0xe5, 0x16, 0x24, 0x0d, 0x12, 0x16, 0x62, 0xc3, 0xe5, 0x34, 0x9f, 0xff, 0xe5, +0x33, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0x8e, 0x49, 0x8f, 0x4a, 0xe5, 0x16, 0x24, 0x0f, 0x12, 0x16, +0x62, 0xc3, 0xe5, 0x36, 0x9f, 0xff, 0xe5, 0x35, 0x9e, 0xfe, 0x12, 0x00, 0x12, 0x8e, 0x4b, 0x8f, +0x4c, 0xd3, 0xe5, 0x4a, 0x94, 0x28, 0xe5, 0x49, 0x64, 0x80, 0x94, 0x80, 0x50, 0x0f, 0xe5, 0x4c, +0x94, 0x28, 0xe5, 0x4b, 0x64, 0x80, 0x94, 0x80, 0x50, 0x03, 0x02, 0x28, 0xad, 0xae, 0x33, 0xaf, +0x34, 0x7d, 0x04, 0x31, 0x8f, 0xac, 0x06, 0xad, 0x07, 0xe5, 0x16, 0x24, 0x0d, 0x12, 0x3a, 0x64, +0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x3a, 0x5c, 0x24, 0x0d, 0x12, 0x1c, 0x34, 0xae, +0x35, 0xaf, 0x36, 0x7c, 0x00, 0x7d, 0x04, 0x31, 0x91, 0xac, 0x06, 0xad, 0x07, 0xe5, 0x16, 0x24, +0x0f, 0x12, 0x3a, 0x64, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x3a, 0x5c, 0x24, 0x0f, +0x12, 0x1c, 0x34, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5, 0x4b, 0x64, 0x80, 0xf8, 0xe5, 0x49, 0x64, +0x80, 0x98, 0x40, 0x23, 0x75, 0x4d, 0x00, 0x75, 0x4e, 0x00, 0x75, 0x4f, 0x45, 0x75, 0x50, 0x00, +0x75, 0x51, 0x00, 0x75, 0x52, 0x47, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x2e, 0xd8, 0xe5, 0x4c, 0x24, +0x02, 0xfd, 0xe4, 0x35, 0x4b, 0x80, 0x21, 0x75, 0x4d, 0x00, 0x75, 0x4e, 0x00, 0x75, 0x4f, 0x47, +0x75, 0x50, 0x00, 0x75, 0x51, 0x00, 0x75, 0x52, 0x45, 0xae, 0x4b, 0xaf, 0x4c, 0x12, 0x2e, 0xd8, +0xe5, 0x4a, 0x24, 0x02, 0xfd, 0xe4, 0x35, 0x49, 0xfc, 0x12, 0x01, 0x84, 0x8e, 0x37, 0x8f, 0x38, +0xc3, 0xe5, 0x38, 0x94, 0x14, 0xe5, 0x37, 0x94, 0x00, 0x50, 0x08, 0x75, 0x37, 0x00, 0x75, 0x38, +0x14, 0x80, 0x11, 0xd3, 0xe5, 0x38, 0x94, 0xbe, 0xe5, 0x37, 0x94, 0x00, 0x40, 0x06, 0x75, 0x37, +0x00, 0x75, 0x38, 0xbe, 0xe5, 0x38, 0x24, 0xc8, 0xff, 0xe4, 0x35, 0x37, 0xab, 0x50, 0xaa, 0x51, +0xa9, 0x52, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0xc3, 0x74, 0xc8, 0x95, 0x38, 0xff, 0xe4, 0x95, 0x37, +0xab, 0x4d, 0xaa, 0x4e, 0xa9, 0x4f, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0xe5, 0x16, 0x24, 0x04, 0xf9, +0xe3, 0x70, 0x02, 0x19, 0xe3, 0x70, 0x0f, 0xe5, 0x16, 0x24, 0x06, 0xf9, 0xe3, 0x70, 0x02, 0x19, +0xe3, 0x70, 0x03, 0xf1, 0xbe, 0xf2, 0xe5, 0x16, 0x24, 0x03, 0x12, 0x16, 0x62, 0xd1, 0xd8, 0xe5, +0x46, 0x2f, 0xff, 0xe5, 0x45, 0x3e, 0xfe, 0x0d, 0x12, 0x01, 0x84, 0x8e, 0x45, 0x8f, 0x46, 0xe5, +0x16, 0x24, 0x05, 0x12, 0x16, 0x62, 0xd1, 0xd8, 0xe5, 0x48, 0x2f, 0xff, 0xe5, 0x47, 0x3e, 0xfe, +0x0d, 0x12, 0x01, 0x84, 0x8e, 0x47, 0x8f, 0x48, 0xf1, 0xbe, 0xf2, 0x80, 0x28, 0xe5, 0x16, 0x24, +0x03, 0x12, 0x16, 0x62, 0x4e, 0x60, 0x02, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0xfa, 0x8e, 0x45, 0x8f, +0x46, 0xe5, 0x16, 0x24, 0x05, 0x12, 0x16, 0x62, 0x4e, 0x60, 0x02, 0x80, 0x04, 0x7e, 0x00, 0x7f, +0xfa, 0x8e, 0x47, 0x8f, 0x48, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0xc3, 0xe5, 0x34, 0x9f, +0xf5, 0x4a, 0xe5, 0x33, 0x9e, 0xf5, 0x49, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xc3, 0xe5, +0x36, 0x9f, 0xf5, 0x4c, 0xe5, 0x35, 0x9e, 0xf5, 0x4b, 0xa8, 0x16, 0xe2, 0x60, 0x02, 0x21, 0xaf, +0xf5, 0x41, 0x75, 0x42, 0x19, 0xe5, 0x17, 0x24, 0x04, 0xf9, 0xc3, 0xe3, 0x94, 0xe0, 0x19, 0xe3, +0x94, 0x01, 0x50, 0x07, 0x90, 0x03, 0x32, 0xe0, 0xff, 0x80, 0x05, 0x90, 0x03, 0x33, 0xe0, 0xff, +0x75, 0x37, 0x00, 0x8f, 0x38, 0x05, 0x38, 0xe5, 0x38, 0x70, 0x02, 0x05, 0x37, 0xe5, 0x16, 0x24, +0x13, 0x12, 0x16, 0x62, 0xc3, 0x94, 0xc0, 0xee, 0x94, 0x00, 0x40, 0x09, 0xd3, 0xef, 0x94, 0x00, +0xee, 0x94, 0x03, 0x40, 0x0b, 0x74, 0x0f, 0x25, 0x42, 0xf5, 0x42, 0xe4, 0x35, 0x41, 0xf5, 0x41, +0xac, 0x37, 0xad, 0x38, 0xae, 0x41, 0xaf, 0x42, 0x12, 0x01, 0x72, 0x12, 0x01, 0x72, 0x7c, 0x00, +0x7d, 0x23, 0x12, 0x01, 0x84, 0xef, 0x25, 0x42, 0xf5, 0x42, 0xee, 0x35, 0x41, 0xf5, 0x41, 0xd1, +0xfe, 0xaa, 0x06, 0xab, 0x07, 0xae, 0x41, 0xaf, 0x42, 0x12, 0x17, 0x7a, 0x12, 0x3a, 0x34, 0xd3, +0xeb, 0x9f, 0xea, 0x9e, 0x50, 0x0b, 0xf1, 0x05, 0xd3, 0xef, 0x95, 0x42, 0xee, 0x95, 0x41, 0x40, +0x1e, 0xe5, 0x13, 0x70, 0x1a, 0xa8, 0x16, 0x04, 0xf2, 0x7d, 0x03, 0xf1, 0x63, 0xe5, 0x16, 0x24, +0x07, 0x12, 0x1c, 0x34, 0x7d, 0x03, 0xf1, 0x5a, 0xe5, 0x16, 0x24, 0x09, 0x12, 0x1c, 0x34, 0xe5, +0x16, 0x24, 0x0b, 0x12, 0x16, 0x62, 0x7c, 0x00, 0x7d, 0x14, 0x12, 0x01, 0x84, 0x7c, 0x00, 0x7d, +0x28, 0x12, 0x01, 0x72, 0xef, 0x24, 0x0a, 0xf5, 0x42, 0xe4, 0x3e, 0xf5, 0x41, 0xf5, 0x43, 0x85, +0x42, 0x44, 0xd3, 0xe5, 0x42, 0x95, 0x4c, 0xe5, 0x41, 0x95, 0x4b, 0x40, 0x0b, 0xae, 0x4b, 0xaf, +0x4c, 0x7d, 0x02, 0x12, 0x01, 0xd9, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xc3, 0xe5, 0x42, 0x9f, +0xf5, 0x42, 0xe5, 0x41, 0x9e, 0xf5, 0x41, 0xd3, 0xe5, 0x44, 0x95, 0x4a, 0xe5, 0x43, 0x95, 0x49, +0x40, 0x06, 0x7d, 0x02, 0xf1, 0x63, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xc3, 0xe5, 0x44, 0x9f, +0xf5, 0x44, 0xe5, 0x43, 0x9e, 0xf5, 0x43, 0xf1, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xd1, 0xfe, 0xd0, +0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x7c, 0x00, 0x7d, 0x1e, 0x12, 0x01, 0xd9, 0x8e, 0x33, +0x8f, 0x34, 0xd3, 0xe5, 0x34, 0x94, 0x0a, 0xf1, 0x11, 0x40, 0x06, 0x75, 0x33, 0x00, 0x75, 0x34, +0x0a, 0xae, 0x33, 0xaf, 0x34, 0x7c, 0x00, 0x7d, 0x04, 0x12, 0x01, 0xd9, 0xc3, 0xe5, 0x34, 0x9f, +0xf5, 0x36, 0xe5, 0x33, 0x9e, 0xf5, 0x35, 0xd3, 0xe5, 0x4a, 0x94, 0x00, 0xe5, 0x49, 0x64, 0x80, +0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x02, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0xfe, 0xef, 0x25, +0x4a, 0xf5, 0x4a, 0xee, 0x35, 0x49, 0xf5, 0x49, 0xd3, 0xe5, 0x4c, 0x94, 0x00, 0xe5, 0x4b, 0x64, +0x80, 0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x02, 0x80, 0x04, 0x7e, 0xff, 0x7f, 0xfe, 0xef, +0x25, 0x4c, 0xf5, 0x4c, 0xee, 0x35, 0x4b, 0xf5, 0x4b, 0xc3, 0x74, 0x0a, 0xf1, 0x4a, 0xe5, 0x16, +0x24, 0x07, 0x12, 0x17, 0x42, 0x12, 0x01, 0x72, 0xc3, 0x74, 0x0c, 0xf1, 0x52, 0x12, 0x01, 0xd9, +0xaa, 0x06, 0xab, 0x07, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x3a, 0x46, 0xeb, 0x2f, 0xfb, 0xea, 0x3e, +0xfa, 0xc3, 0x74, 0x0d, 0xf1, 0x52, 0xae, 0x49, 0xaf, 0x4a, 0x12, 0x01, 0xd9, 0xef, 0x2b, 0xf5, +0x34, 0xee, 0x3a, 0xf5, 0x33, 0xc3, 0x74, 0x0a, 0xf1, 0x42, 0xe5, 0x16, 0x24, 0x09, 0x12, 0x17, +0x42, 0x12, 0x01, 0x72, 0xf1, 0x6c, 0x12, 0x01, 0xd9, 0xaa, 0x06, 0xab, 0x07, 0x7d, 0x04, 0xf1, +0x5a, 0xeb, 0x2f, 0xfb, 0xea, 0x3e, 0xfa, 0xf1, 0x6c, 0xae, 0x4b, 0xaf, 0x4c, 0x12, 0x01, 0xd9, +0xef, 0x2b, 0xf5, 0x36, 0xee, 0x3a, 0xf5, 0x35, 0xf1, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xd1, 0xfe, +0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x36, 0xae, 0x35, +0x12, 0x00, 0x12, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x3a, 0x55, 0xd0, 0xe0, 0x2f, 0xfd, 0xd0, 0xe0, +0x3e, 0xfc, 0xd0, 0x07, 0xd0, 0x06, 0xd3, 0xed, 0x9f, 0xee, 0x64, 0x80, 0xf8, 0xec, 0x64, 0x80, +0x98, 0x40, 0x16, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x35, 0xf5, 0x36, 0xe5, 0x16, 0x24, 0x07, +0xf1, 0xb6, 0x24, 0x09, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xe5, 0x16, 0x24, 0x19, 0xf8, 0xe2, 0xfe, +0x08, 0xe2, 0xf1, 0x18, 0xf5, 0x35, 0xd3, 0xe5, 0x48, 0x95, 0x46, 0xe5, 0x47, 0x95, 0x45, 0x40, +0x34, 0xf1, 0x83, 0x40, 0x19, 0xe5, 0x34, 0x24, 0x3e, 0xff, 0xe5, 0x33, 0x34, 0xfe, 0xfe, 0x12, +0x17, 0x73, 0xef, 0x25, 0x34, 0xf5, 0x34, 0xee, 0x35, 0x33, 0xf5, 0x33, 0x80, 0x17, 0xf1, 0x0c, +0x50, 0x13, 0xc3, 0x74, 0x1e, 0xf1, 0x4a, 0x12, 0x17, 0x73, 0xc3, 0xe5, 0x34, 0x9f, 0xf5, 0x34, +0xe5, 0x33, 0x9e, 0xf5, 0x33, 0xd3, 0xe5, 0x46, 0x95, 0x48, 0xe5, 0x45, 0x95, 0x47, 0x40, 0x3e, +0xd3, 0xe5, 0x36, 0x94, 0xa2, 0xe5, 0x35, 0x64, 0x80, 0x94, 0x83, 0x40, 0x14, 0xe5, 0x36, 0x24, +0x5e, 0xff, 0xe5, 0x35, 0x34, 0xfc, 0xfe, 0x12, 0x17, 0x73, 0xef, 0xf1, 0x2a, 0xf5, 0x35, 0x80, +0x1d, 0xc3, 0xe5, 0x36, 0x94, 0x1e, 0x12, 0x17, 0xa1, 0x50, 0x13, 0xc3, 0x74, 0x1e, 0xf1, 0x42, +0x12, 0x17, 0x73, 0xc3, 0xe5, 0x36, 0x9f, 0xf5, 0x36, 0xe5, 0x35, 0x9e, 0xf5, 0x35, 0xf1, 0xd6, +0xf1, 0x0c, 0x40, 0x04, 0xf1, 0x83, 0x40, 0x02, 0xc2, 0x02, 0x30, 0x05, 0x0c, 0x75, 0x45, 0x00, +0x75, 0x46, 0x80, 0x75, 0x47, 0x00, 0x75, 0x48, 0x80, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, +0xac, 0x45, 0xad, 0x46, 0x12, 0x04, 0xb2, 0x8f, 0x3c, 0x8e, 0x3b, 0x8d, 0x3a, 0x8c, 0x39, 0xe5, +0x42, 0x25, 0x46, 0xf5, 0x46, 0xe5, 0x41, 0x35, 0x45, 0xf5, 0x45, 0xae, 0x33, 0xaf, 0x34, 0xab, +0x07, 0xaa, 0x06, 0xae, 0x41, 0xaf, 0x42, 0xf1, 0x9d, 0x25, 0x3c, 0xff, 0xee, 0x35, 0x3b, 0xfe, +0xed, 0x35, 0x3a, 0xfd, 0xec, 0x35, 0x39, 0xfc, 0xe5, 0x45, 0xf1, 0x77, 0xe5, 0x46, 0x13, 0xff, +0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xd4, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x45, 0xaf, 0x46, 0x12, 0x24, +0x36, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x03, 0x6c, 0x8f, 0x3c, 0x8e, 0x3b, 0x8d, 0x3a, 0x8c, 0x39, +0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xac, 0x47, 0xad, 0x48, 0x12, 0x04, 0xb2, 0x8f, 0x40, +0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x44, 0x25, 0x48, 0xf5, 0x48, 0xe5, 0x43, 0x35, 0x47, +0xf5, 0x47, 0xae, 0x35, 0xaf, 0x36, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x43, 0xaf, 0x44, 0xf1, 0x9d, +0x25, 0x40, 0xff, 0xee, 0x35, 0x3f, 0xfe, 0xed, 0x35, 0x3e, 0xfd, 0xec, 0x35, 0x3d, 0xfc, 0xe5, +0x47, 0xf1, 0x77, 0xe5, 0x48, 0x13, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xd4, 0xc0, 0x06, 0xc0, +0x07, 0xae, 0x47, 0xaf, 0x48, 0x12, 0x24, 0x36, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x03, 0x6c, 0x8f, +0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xa8, 0x16, 0xe2, 0x64, 0x01, 0x70, 0x6b, 0xe8, 0x24, +0x19, 0x12, 0x17, 0x42, 0xc3, 0xe5, 0x3c, 0x9d, 0xff, 0xe5, 0x3b, 0x9c, 0xfe, 0xd1, 0xf2, 0x12, +0x0c, 0xea, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x17, 0x42, 0xc3, 0xe5, 0x40, 0x9d, 0xff, 0xe5, 0x3f, +0x9c, 0xfe, 0xd1, 0xe6, 0x12, 0x0c, 0xea, 0xe5, 0x16, 0x24, 0x07, 0x12, 0x16, 0x62, 0xd1, 0xd8, +0xd1, 0xf2, 0x12, 0x0d, 0x30, 0xf1, 0x8f, 0x24, 0x07, 0x12, 0x1c, 0x34, 0xe5, 0x16, 0x24, 0x09, +0x12, 0x16, 0x62, 0xd1, 0xd8, 0xd1, 0xe6, 0x12, 0x0d, 0x30, 0xf1, 0x8f, 0x24, 0x09, 0x12, 0x1c, +0x34, 0xe5, 0x17, 0x04, 0xf8, 0xe5, 0x3b, 0xf2, 0xe5, 0x3c, 0xf1, 0x32, 0xe5, 0x3f, 0xf2, 0x08, +0xe5, 0x40, 0xf2, 0xd2, 0x04, 0xc2, 0x03, 0x80, 0x1a, 0xe5, 0x16, 0xf1, 0xab, 0x24, 0x11, 0x12, +0x16, 0x62, 0x12, 0x1c, 0x31, 0xe5, 0x16, 0x24, 0x13, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24, 0x03, +0x12, 0x1c, 0x34, 0x12, 0x1d, 0xcb, 0x60, 0x05, 0xf1, 0x3a, 0xf2, 0x80, 0x54, 0xe5, 0x16, 0x24, +0x02, 0xf8, 0xe4, 0xf2, 0x80, 0x4b, 0xd1, 0xdf, 0x70, 0x23, 0xe5, 0x16, 0x04, 0xf8, 0xe2, 0xd3, +0x94, 0x03, 0x50, 0x06, 0xe5, 0x11, 0x64, 0x02, 0x70, 0x13, 0xe4, 0xf2, 0xf1, 0x3a, 0xf2, 0xe5, +0x16, 0x24, 0x19, 0xf9, 0xe5, 0x17, 0x04, 0x12, 0x1e, 0xe1, 0x12, 0x1e, 0xd8, 0xd1, 0xdf, 0x60, +0x02, 0x14, 0xf2, 0xe2, 0x70, 0x1b, 0xe5, 0x16, 0x04, 0xf8, 0xe4, 0xf2, 0xa8, 0x16, 0xf2, 0xe8, +0x24, 0x0b, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0x05, 0x11, 0x12, 0x39, 0x7d, 0x74, 0xff, 0xf0, 0xa3, +0xf0, 0xe5, 0x11, 0xb4, 0x02, 0x09, 0xd2, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x04, 0x57, 0xf0, 0x12, +0x1d, 0xcb, 0x60, 0x10, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xe2, 0x7f, 0x01, 0x60, 0x02, 0x7f, 0x03, +0x8f, 0x53, 0xc1, 0x70, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xe2, 0x70, 0x02, 0xc1, 0x6d, 0xd1, 0xdf, +0x60, 0x76, 0x75, 0x53, 0x03, 0x12, 0x1e, 0xd8, 0x30, 0x01, 0x08, 0xd1, 0xf2, 0x12, 0x17, 0x6c, +0xff, 0x80, 0x0d, 0xd1, 0xf2, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x21, 0x94, 0x1d, 0x12, 0x01, 0xd9, +0x8e, 0x33, 0x8f, 0x34, 0x30, 0x01, 0x08, 0xd1, 0xe6, 0x12, 0x17, 0x6c, 0xff, 0x80, 0x0d, 0xd1, +0xe6, 0x12, 0x17, 0x6c, 0xff, 0x12, 0x21, 0x94, 0x1d, 0x12, 0x01, 0xd9, 0x8e, 0x35, 0x8f, 0x36, +0xe5, 0x16, 0x24, 0x19, 0x12, 0x16, 0x62, 0xc3, 0x94, 0x0a, 0xee, 0x94, 0x00, 0x40, 0x09, 0xd3, +0xef, 0x94, 0xd6, 0xee, 0x94, 0x01, 0x40, 0x05, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xef, 0xf1, 0x18, +0xf5, 0x35, 0xf1, 0xd6, 0xe5, 0x17, 0x04, 0xf8, 0xe5, 0x33, 0xf2, 0xe5, 0x34, 0xf1, 0x32, 0xe5, +0x35, 0xf2, 0x08, 0xe5, 0x36, 0xf2, 0x80, 0x08, 0x75, 0x53, 0x02, 0x80, 0x03, 0xe4, 0xf5, 0x53, +0xe5, 0x17, 0x24, 0x06, 0xf8, 0xe5, 0x53, 0xf2, 0x64, 0x02, 0x70, 0x18, 0xe5, 0x16, 0x24, 0x19, +0x12, 0x16, 0x62, 0x12, 0x1c, 0x31, 0xe5, 0x16, 0x24, 0x1b, 0x12, 0x16, 0x62, 0xe5, 0x17, 0x24, +0x03, 0x12, 0x1c, 0x34, 0xe5, 0x17, 0x04, 0xf9, 0xe5, 0x16, 0x24, 0x19, 0x12, 0x1e, 0xe1, 0xd1, +0xdf, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0x01, 0xe5, 0x16, 0x24, 0x1d, 0xf8, 0xef, 0xf2, 0xe5, 0x17, +0x04, 0x12, 0x16, 0x62, 0xe5, 0x16, 0x24, 0x15, 0x12, 0x1c, 0x34, 0xe5, 0x17, 0x24, 0x03, 0x12, +0x16, 0x62, 0xe5, 0x16, 0x24, 0x17, 0x12, 0x1c, 0x34, 0x05, 0x32, 0x74, 0x1f, 0x25, 0x16, 0xf5, +0x16, 0x12, 0x1c, 0x1b, 0x02, 0x24, 0x99, 0x22, 0x7c, 0x00, 0x7d, 0x0a, 0x02, 0x01, 0x72, 0xe5, +0x16, 0x24, 0x02, 0xf8, 0xe2, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x4d, 0xf5, 0x82, 0xe4, 0x34, +0x04, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x49, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0x22, 0xaf, 0x4a, +0xae, 0x49, 0x02, 0x00, 0x12, 0xaf, 0x4c, 0xae, 0x4b, 0x02, 0x00, 0x12, 0xc3, 0xe5, 0x34, 0x94, +0x1e, 0xe5, 0x33, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0x34, 0xf5, 0x34, 0xee, 0x35, 0x33, 0xf5, +0x33, 0xe5, 0x16, 0x24, 0x1b, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0x25, 0x36, 0xf5, 0x36, 0xee, 0x35, +0x35, 0x22, 0x08, 0xf2, 0xe5, 0x17, 0x24, 0x03, 0xf8, 0x22, 0xe5, 0x16, 0x24, 0x02, 0xf8, 0x74, +0x02, 0x22, 0x95, 0x36, 0xff, 0xe4, 0x95, 0x35, 0xfe, 0x22, 0x95, 0x34, 0xff, 0xe4, 0x95, 0x33, +0xfe, 0x22, 0x95, 0x34, 0xfd, 0xe4, 0x95, 0x33, 0xfc, 0x22, 0xae, 0x4b, 0xaf, 0x4c, 0x7c, 0x00, +0x02, 0x01, 0xd9, 0xae, 0x49, 0xaf, 0x4a, 0x7c, 0x00, 0x02, 0x01, 0xd9, 0xc3, 0x74, 0x0c, 0x95, +0x36, 0xfd, 0xe4, 0x95, 0x35, 0xfc, 0x22, 0xa8, 0x04, 0xa9, 0x05, 0xaa, 0x06, 0xab, 0x07, 0xc3, +0x13, 0xfe, 0x22, 0xd3, 0xe5, 0x34, 0x94, 0xc2, 0xe5, 0x33, 0x64, 0x80, 0x94, 0x81, 0x22, 0x2f, +0xff, 0xec, 0x3e, 0xfe, 0x7c, 0x00, 0x0d, 0x12, 0x01, 0xd9, 0xe5, 0x16, 0x22, 0xea, 0x33, 0x95, +0xe0, 0xf9, 0xf8, 0xe4, 0xfc, 0xfd, 0x12, 0x02, 0xe1, 0xef, 0x22, 0x24, 0x07, 0xf8, 0xe4, 0xf2, +0x08, 0xf2, 0xe5, 0x16, 0x24, 0x09, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xe5, 0x16, 0x22, 0xe5, 0x16, +0x24, 0x03, 0xf8, 0xe5, 0x45, 0xf2, 0x08, 0xe5, 0x46, 0xf2, 0xe5, 0x16, 0x24, 0x05, 0xf8, 0xe5, +0x47, 0xf2, 0x08, 0xe5, 0x48, 0x22, 0x7b, 0xdf, 0x7a, 0x01, 0xe4, 0xfd, 0xaf, 0x34, 0xae, 0x33, +0x12, 0x16, 0xbd, 0x8e, 0x33, 0x8f, 0x34, 0x7b, 0xbf, 0x7a, 0x03, 0xaf, 0x36, 0xae, 0x35, 0x12, +0x16, 0xbd, 0x8e, 0x35, 0x8f, 0x36, 0x22, 0x00, 0x12, 0x30, 0x21, 0xe4, 0x78, 0x99, 0xf6, 0x12, +0x0d, 0xc0, 0x80, 0xf7, 0x75, 0x88, 0x08, 0x75, 0x89, 0x80, 0xe5, 0x61, 0x75, 0xf0, 0x20, 0xa4, +0xff, 0xe5, 0xf0, 0x44, 0x80, 0xf5, 0x8f, 0x8f, 0x8e, 0xe4, 0x78, 0x99, 0xf6, 0x75, 0x88, 0xa0, +0x22, 0xc2, 0xaf, 0xe4, 0xf5, 0x22, 0x90, 0xff, 0x00, 0x74, 0x02, 0xf0, 0x90, 0xff, 0x03, 0x74, +0x35, 0xf0, 0x90, 0xff, 0x07, 0xe0, 0xf5, 0x23, 0x90, 0xff, 0x03, 0x74, 0x30, 0xf0, 0x75, 0x24, +0x55, 0x90, 0xff, 0x07, 0xe0, 0xf5, 0x25, 0x25, 0x24, 0xf5, 0x24, 0x74, 0x84, 0x25, 0x22, 0xf8, +0x74, 0x80, 0xf2, 0xe5, 0x23, 0xb4, 0xac, 0x15, 0xe5, 0x25, 0xd3, 0x94, 0x6e, 0x40, 0x0e, 0xe5, +0x25, 0x94, 0x96, 0x50, 0x08, 0x74, 0x84, 0x25, 0x22, 0xf8, 0xe5, 0x25, 0xf2, 0x90, 0xff, 0x03, +0xe0, 0x04, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x04, 0x40, 0xc5, 0x90, 0xff, 0x07, 0xe0, +0x65, 0x24, 0x60, 0x0b, 0x78, 0x84, 0x74, 0x80, 0xf2, 0x08, 0xf2, 0x08, 0xf2, 0x08, 0xf2, 0xe4, +0x90, 0xff, 0x00, 0xf0, 0x90, 0xff, 0x88, 0x74, 0x40, 0xf0, 0x74, 0xc0, 0xf0, 0x90, 0xff, 0x01, +0x74, 0x0f, 0xf0, 0x74, 0x0d, 0xf0, 0x43, 0x95, 0x60, 0xe4, 0xf5, 0x96, 0x75, 0x61, 0x0b, 0x11, +0x04, 0x11, 0xbf, 0xe4, 0xf5, 0x60, 0xc2, 0x05, 0xf5, 0x63, 0xf5, 0x62, 0xd2, 0xaf, 0x22, 0xe4, +0x90, 0x03, 0x34, 0xf0, 0x75, 0x58, 0xff, 0xf5, 0x57, 0xf5, 0x56, 0x90, 0x04, 0x35, 0xf0, 0xc2, +0x07, 0xc2, 0x08, 0x90, 0xff, 0x85, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x14, 0x74, 0x04, 0x31, 0x77, +0xc2, 0xaf, 0x7d, 0x03, 0x7f, 0x12, 0x12, 0x08, 0xb7, 0xd2, 0xaf, 0x90, 0xff, 0x12, 0xe0, 0x54, +0xe7, 0xf0, 0x90, 0xff, 0x11, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe7, 0xf0, +0x90, 0xff, 0x14, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x1b, 0xe0, 0x44, 0x18, 0xf0, 0xe4, 0xf5, +0xa3, 0x75, 0xa1, 0x95, 0x75, 0xa2, 0x81, 0x43, 0x90, 0x10, 0x90, 0xff, 0x83, 0xe0, 0x54, 0xcf, +0xf0, 0x7e, 0x01, 0x7f, 0x00, 0x7d, 0x00, 0x7b, 0x01, 0x7a, 0x03, 0x79, 0x35, 0x12, 0x04, 0xdf, +0x90, 0x3b, 0xfc, 0xe4, 0x93, 0x90, 0x03, 0xdb, 0xf0, 0x90, 0x3b, 0xfd, 0xe4, 0x93, 0x90, 0x03, +0xdc, 0xf0, 0x90, 0x3b, 0xfb, 0xe4, 0x93, 0x90, 0x03, 0xdd, 0xf0, 0x90, 0x3b, 0xfa, 0xe4, 0x93, +0x90, 0x03, 0xde, 0xf0, 0x90, 0x3b, 0xf8, 0xe4, 0x93, 0x90, 0x03, 0xdf, 0xf0, 0x90, 0x3b, 0xf9, +0xe4, 0x93, 0x90, 0x03, 0xe0, 0xf0, 0x90, 0x3b, 0xfe, 0xe4, 0x93, 0x90, 0x03, 0xe1, 0xf0, 0x90, +0x3b, 0xff, 0xe4, 0x93, 0x90, 0x03, 0xe2, 0xf0, 0x90, 0xff, 0x18, 0xe0, 0x44, 0x04, 0xf0, 0x22, +0x8f, 0x23, 0x8d, 0x24, 0x31, 0x78, 0xe5, 0x63, 0x60, 0x0f, 0xe5, 0x24, 0xd3, 0x94, 0x17, 0x50, +0x54, 0x78, 0x9a, 0xe6, 0x44, 0x08, 0xf6, 0x80, 0x42, 0xe5, 0x56, 0x60, 0x43, 0x30, 0x07, 0x0e, +0x90, 0x04, 0x35, 0xe0, 0xc3, 0x94, 0x0f, 0x50, 0x0d, 0xe0, 0x04, 0xf0, 0x80, 0x08, 0x90, 0x04, +0x35, 0xe0, 0x60, 0x02, 0x14, 0xf0, 0xe5, 0x56, 0xb4, 0x01, 0x12, 0x90, 0x04, 0x35, 0xe0, 0x64, +0x0f, 0x70, 0x22, 0x91, 0x85, 0x74, 0xc0, 0xf0, 0x75, 0x56, 0x02, 0x80, 0x0e, 0x90, 0x04, 0x35, +0xe0, 0x70, 0x12, 0x91, 0x85, 0x74, 0xe0, 0xf0, 0x75, 0x56, 0x01, 0x75, 0x58, 0x01, 0x80, 0x05, +0xe4, 0x90, 0x04, 0x35, 0xf0, 0x91, 0x8d, 0xe5, 0x25, 0xc3, 0x94, 0x02, 0x50, 0x38, 0x91, 0x4d, +0x91, 0x5c, 0x60, 0x2e, 0x12, 0x02, 0x25, 0x7c, 0x01, 0x7d, 0xe0, 0x91, 0x7d, 0x7b, 0xe0, 0x7a, +0x01, 0x91, 0x48, 0xee, 0x8f, 0xf0, 0x12, 0x02, 0x88, 0x91, 0x4d, 0x91, 0x62, 0x7c, 0x03, 0x7d, +0x20, 0x91, 0x7d, 0x7b, 0xc0, 0x7a, 0x03, 0x91, 0x48, 0x90, 0x00, 0x02, 0xee, 0x8f, 0xf0, 0x12, +0x02, 0xa7, 0x91, 0x98, 0x80, 0xc1, 0xe5, 0x57, 0x60, 0x02, 0x61, 0xe3, 0x30, 0x08, 0x02, 0x81, +0x37, 0xe5, 0x56, 0x70, 0x04, 0x90, 0x03, 0x36, 0xf0, 0xe5, 0x58, 0x20, 0xe0, 0x02, 0x41, 0xd9, +0x78, 0x9a, 0xe6, 0xff, 0x70, 0x08, 0x90, 0x03, 0x34, 0xe0, 0x70, 0x02, 0x41, 0xd9, 0xe4, 0x90, +0x03, 0x37, 0xf0, 0xa3, 0xf0, 0xef, 0x54, 0x07, 0x60, 0x08, 0x90, 0x03, 0x37, 0x74, 0x01, 0xf0, +0x80, 0x06, 0x90, 0x03, 0x38, 0x74, 0x40, 0xf0, 0x90, 0x03, 0x34, 0xe0, 0x78, 0x9a, 0x46, 0xf5, +0x2b, 0x30, 0xe0, 0x0d, 0x90, 0x03, 0x38, 0xe0, 0x44, 0x01, 0xf0, 0xa3, 0x74, 0x90, 0xf0, 0x80, +0x33, 0xe5, 0x2b, 0x30, 0xe1, 0x0b, 0x90, 0x03, 0x38, 0xe0, 0xf0, 0xa3, 0x74, 0xf0, 0xf0, 0x80, +0x23, 0xe5, 0x2b, 0x30, 0xe2, 0x0b, 0x90, 0x03, 0x38, 0xe0, 0xf0, 0xa3, 0x74, 0x50, 0xf0, 0x80, +0x13, 0xe5, 0x2b, 0x30, 0xe3, 0x0e, 0xe5, 0x24, 0x90, 0x05, 0xec, 0x93, 0x90, 0x04, 0x08, 0xf0, +0xe4, 0x78, 0x9a, 0xf6, 0x90, 0x03, 0x3a, 0x74, 0x03, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x91, 0x54, +0x78, 0x9a, 0xe6, 0x90, 0x03, 0x34, 0xf0, 0x30, 0xe4, 0x02, 0xe4, 0xf0, 0x90, 0x03, 0x34, 0xe0, +0x7f, 0xff, 0x60, 0x02, 0x7f, 0x01, 0x8f, 0x58, 0x22, 0xe5, 0x58, 0x20, 0xe1, 0x02, 0x61, 0xe3, +0xe4, 0x90, 0x03, 0x37, 0xf0, 0xe5, 0x11, 0xb4, 0x02, 0x0c, 0xe5, 0x13, 0xd3, 0x94, 0x05, 0x40, +0x05, 0x75, 0x13, 0x05, 0x61, 0xaa, 0xe5, 0x13, 0x60, 0x07, 0x90, 0x04, 0x40, 0x74, 0x01, 0xf0, +0x22, 0x75, 0x26, 0x03, 0xe4, 0xf5, 0x27, 0xe5, 0x23, 0x24, 0x05, 0xf8, 0xe6, 0x70, 0x08, 0xe5, +0x23, 0x24, 0x0b, 0xf8, 0xe6, 0x60, 0x08, 0x7f, 0x20, 0x7a, 0x03, 0x79, 0x38, 0x91, 0xa6, 0x91, +0x8d, 0xe5, 0x25, 0xc3, 0x94, 0x02, 0x40, 0x02, 0x61, 0xaa, 0x91, 0x4d, 0x91, 0x5c, 0x60, 0x76, +0x90, 0x03, 0x37, 0xe0, 0x04, 0xf0, 0x74, 0x35, 0x25, 0x26, 0x91, 0x40, 0x74, 0x80, 0xf0, 0x90, +0x04, 0x40, 0x74, 0x02, 0xf0, 0x91, 0x5c, 0xff, 0xb4, 0x02, 0x0b, 0x74, 0x35, 0x25, 0x26, 0x91, +0x40, 0x74, 0x40, 0xf0, 0x80, 0x0c, 0xef, 0xb4, 0x01, 0x08, 0x74, 0x35, 0x25, 0x26, 0x91, 0x40, +0xe4, 0xf0, 0x91, 0x39, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x91, 0x4d, 0x12, 0x02, 0x25, 0xfb, +0xaa, 0xf0, 0xea, 0xff, 0xed, 0x4f, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xaf, 0x03, 0x91, 0x69, 0x91, +0x40, 0xef, 0xf0, 0xab, 0x28, 0xaa, 0x29, 0x91, 0x62, 0xe5, 0xf0, 0xff, 0xe5, 0x25, 0xc4, 0x54, +0xf0, 0x4f, 0x91, 0x68, 0x91, 0x40, 0xef, 0xf0, 0x91, 0x62, 0x91, 0x68, 0x91, 0x40, 0xef, 0x91, +0x38, 0xe4, 0x91, 0x38, 0xe4, 0xf0, 0x91, 0x98, 0x61, 0x21, 0x90, 0x04, 0x40, 0xe0, 0x60, 0x26, +0x14, 0xf0, 0x90, 0x03, 0x37, 0xe0, 0x70, 0x1c, 0xa3, 0xe0, 0xff, 0xf4, 0x60, 0x06, 0xef, 0x54, +0x0f, 0x44, 0x40, 0xf0, 0x90, 0x03, 0x3e, 0xe0, 0xff, 0xf4, 0x60, 0x06, 0xef, 0x54, 0x0f, 0x44, +0x40, 0xf0, 0x91, 0x54, 0x91, 0x54, 0x90, 0x03, 0x37, 0xe0, 0x7f, 0xff, 0x60, 0x02, 0x7f, 0x02, +0x8f, 0x58, 0x22, 0xe5, 0x57, 0x64, 0xe0, 0x70, 0x4e, 0x31, 0x78, 0xe5, 0x23, 0x24, 0x04, 0xf8, +0xe6, 0x70, 0x05, 0x78, 0x9a, 0xe6, 0x60, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x04, +0x37, 0xef, 0xf0, 0xe5, 0x23, 0x24, 0x0a, 0xf8, 0xe6, 0x60, 0x03, 0xe0, 0x04, 0xf0, 0xa8, 0x23, +0xe6, 0xff, 0x08, 0xe6, 0x90, 0x04, 0x38, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0xe5, 0x23, 0x24, 0x02, +0x91, 0x71, 0xe5, 0x23, 0x24, 0x06, 0x91, 0x71, 0xe5, 0x23, 0x24, 0x08, 0x91, 0x71, 0x78, 0x9a, +0xe6, 0x90, 0x04, 0x36, 0xf0, 0x91, 0x54, 0x22, 0xf0, 0xaf, 0x26, 0x05, 0x26, 0x74, 0x35, 0x2f, +0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83, 0x22, 0xf9, 0xf8, 0x12, 0x03, 0x6c, 0xab, 0x28, 0xaa, +0x29, 0xa9, 0x2a, 0x22, 0x90, 0xff, 0x18, 0xe0, 0x54, 0xfb, 0xf0, 0x22, 0x90, 0x00, 0x05, 0x02, +0x01, 0x33, 0x90, 0x00, 0x02, 0x02, 0x02, 0x50, 0xff, 0xae, 0x26, 0x05, 0x26, 0x74, 0x35, 0x2e, +0x22, 0xf8, 0xe6, 0xff, 0x08, 0xe6, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x22, 0xff, 0xae, 0xf0, +0x12, 0x04, 0xb2, 0xe4, 0x22, 0x78, 0x9a, 0x76, 0x10, 0x90, 0x03, 0x36, 0x22, 0xe4, 0xf5, 0x25, +0xf5, 0x28, 0xf5, 0x29, 0x85, 0x23, 0x2a, 0x22, 0x05, 0x25, 0x74, 0x06, 0x25, 0x2a, 0xf5, 0x2a, +0xe4, 0x35, 0x29, 0xf5, 0x29, 0x22, 0x7e, 0x00, 0x7d, 0xff, 0x7b, 0x01, 0x02, 0x04, 0xdf, 0xc0, +0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xaf, 0xa3, 0xef, 0x54, +0xe8, 0x60, 0x03, 0x75, 0x5c, 0x00, 0xef, 0x20, 0xe0, 0x02, 0xa1, 0xe3, 0xe5, 0x5c, 0x64, 0x02, +0x60, 0x02, 0xa1, 0x7d, 0xaf, 0xa4, 0x05, 0x5d, 0xe5, 0x5d, 0xb4, 0x01, 0x12, 0x8f, 0x5e, 0x74, +0x35, 0x2f, 0xf9, 0xe4, 0x34, 0x03, 0x75, 0x59, 0x01, 0xf5, 0x5a, 0x89, 0x5b, 0xa1, 0x78, 0x78, +0x59, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x04, 0xa2, 0xef, 0x12, 0x01, 0x60, 0xe5, 0x5d, 0x64, 0x02, +0x70, 0x76, 0xe5, 0x5e, 0x70, 0x3f, 0x8f, 0x57, 0xbf, 0x04, 0x0e, 0x75, 0x59, 0x01, 0x75, 0x5a, +0x00, 0x75, 0x5b, 0xdf, 0x75, 0x62, 0x03, 0x80, 0x5f, 0xbf, 0xe0, 0x0b, 0x75, 0x59, 0x01, 0x75, +0x5a, 0x04, 0x75, 0x5b, 0x36, 0x80, 0x51, 0xbf, 0x06, 0x0b, 0x75, 0x59, 0x01, 0x75, 0x5a, 0x01, +0x75, 0x5b, 0x61, 0x80, 0x43, 0xef, 0x64, 0x07, 0x70, 0x3e, 0x75, 0x59, 0x01, 0x75, 0x5a, 0x00, +0x75, 0x5b, 0x8b, 0x80, 0x33, 0xe5, 0x57, 0x70, 0x2f, 0xe5, 0x5e, 0xb4, 0xa5, 0x08, 0xbf, 0x03, +0x05, 0x75, 0x62, 0x02, 0x80, 0x22, 0xe5, 0x5e, 0xb4, 0xd0, 0x07, 0xef, 0x54, 0x01, 0xf5, 0x63, +0x80, 0x16, 0xe5, 0x5e, 0xb4, 0xb0, 0x11, 0xef, 0x54, 0x01, 0xf5, 0x56, 0x90, 0x03, 0x36, 0x74, +0xe0, 0xf0, 0x90, 0x04, 0x40, 0x74, 0x01, 0xf0, 0x75, 0xa3, 0x10, 0x80, 0x66, 0xe5, 0x5c, 0xb4, +0x01, 0x1f, 0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x01, 0x1a, 0xf5, 0xa4, 0x75, 0xa3, 0x04, +0xef, 0x20, 0xe1, 0x4f, 0x74, 0x01, 0x25, 0x5b, 0xf5, 0x5b, 0xe4, 0x35, 0x5a, 0xf5, 0x5a, 0x80, +0x42, 0xe5, 0x5c, 0x70, 0x3b, 0xaf, 0xa4, 0xef, 0xc3, 0x13, 0x64, 0x15, 0x70, 0x32, 0xef, 0x30, +0xe0, 0x1e, 0xe5, 0x57, 0x70, 0x0f, 0x78, 0x59, 0x75, 0xf0, 0x01, 0x12, 0x04, 0xa2, 0x12, 0x01, +0x1a, 0xf5, 0xa4, 0x80, 0x03, 0x85, 0x57, 0xa4, 0x75, 0xa3, 0x14, 0x75, 0x5c, 0x01, 0x80, 0x0c, +0x75, 0xa3, 0x10, 0x75, 0x5d, 0x00, 0x75, 0x5e, 0x00, 0x75, 0x5c, 0x02, 0x31, 0x78, 0x80, 0x03, +0x75, 0xa3, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, +0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0x75, 0x89, 0x80, 0x78, 0x99, 0xe6, 0xc3, 0x94, 0x28, +0x50, 0x04, 0x06, 0x75, 0x8a, 0x00, 0xe5, 0x5f, 0x60, 0x02, 0x15, 0x5f, 0xd0, 0x00, 0xd0, 0xd0, +0xd0, 0xe0, 0x32, 0xc3, 0xef, 0x9b, 0xf5, 0x33, 0xee, 0x9a, 0xf5, 0x32, 0xc3, 0xed, 0x95, 0x31, +0xf5, 0x35, 0xec, 0x95, 0x30, 0xf5, 0x34, 0xaf, 0x33, 0xae, 0x32, 0x12, 0x00, 0x12, 0x8e, 0x36, +0x8f, 0x37, 0xaf, 0x35, 0xae, 0x34, 0x12, 0x00, 0x12, 0xab, 0x07, 0xaa, 0x06, 0xe5, 0x33, 0x45, +0x32, 0x60, 0x19, 0xd3, 0xe5, 0x33, 0x94, 0x00, 0xe5, 0x32, 0x64, 0x80, 0x94, 0x80, 0x40, 0x06, +0x7e, 0x00, 0x7f, 0x01, 0x80, 0x0a, 0x7e, 0xff, 0x7f, 0xff, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, +0x8e, 0x32, 0x8f, 0x33, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x19, 0xd3, 0xe5, 0x35, 0x94, 0x00, 0xe5, +0x34, 0x64, 0x80, 0x94, 0x80, 0x40, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x0a, 0x7e, 0xff, 0x7f, +0xff, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x8e, 0x34, 0x8f, 0x35, 0xd3, 0xeb, 0x95, 0x37, 0xea, +0x95, 0x36, 0xe5, 0x37, 0x40, 0x10, 0x2b, 0xff, 0xe5, 0x36, 0x3a, 0xfe, 0xe5, 0x37, 0x24, 0x01, +0xfd, 0xe4, 0x35, 0x36, 0x80, 0x0c, 0x2b, 0xff, 0xe5, 0x36, 0x3a, 0xfe, 0xeb, 0x24, 0x01, 0xfd, +0xe4, 0x3a, 0xfc, 0x12, 0x01, 0x84, 0xd3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x40, 0x15, 0xd3, +0xe5, 0x37, 0x9b, 0xe5, 0x36, 0x9a, 0x40, 0x07, 0xe4, 0xf5, 0x34, 0xf5, 0x35, 0x80, 0x05, 0xe4, +0xf5, 0x32, 0xf5, 0x33, 0xe4, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x34, 0x06, +0xf1, 0x06, 0xb5, 0x33, 0x19, 0xec, 0xb5, 0x32, 0x15, 0xef, 0x25, 0xe0, 0x24, 0x05, 0xf5, 0x82, +0xe4, 0x34, 0x06, 0xf1, 0x06, 0x65, 0x35, 0x70, 0x03, 0xec, 0x65, 0x34, 0x60, 0x04, 0x0f, 0xbf, +0x09, 0xd4, 0xef, 0x04, 0xff, 0x22, 0xf5, 0x83, 0xe4, 0x93, 0xfd, 0x33, 0x95, 0xe0, 0xfc, 0xed, +0x22, 0xa8, 0x07, 0xe6, 0xf5, 0x23, 0x08, 0xe6, 0xf5, 0x24, 0xef, 0x24, 0x02, 0xf8, 0xe6, 0xf5, +0x25, 0x08, 0xe6, 0xf5, 0x26, 0xef, 0x24, 0x0a, 0xf8, 0xe6, 0x60, 0x12, 0x12, 0x39, 0x53, 0x50, +0x07, 0x08, 0x06, 0xe6, 0x18, 0x70, 0x01, 0x06, 0x75, 0x63, 0x01, 0x02, 0x39, 0x37, 0xef, 0x24, +0x05, 0xf8, 0xe6, 0xf5, 0x29, 0xef, 0x24, 0x04, 0xf8, 0xe6, 0x70, 0x3e, 0xe5, 0x29, 0xb4, 0x02, +0x17, 0xe5, 0x63, 0xb4, 0x04, 0x03, 0x7f, 0x17, 0x22, 0xe5, 0x63, 0x64, 0x08, 0x60, 0x03, 0x02, +0x39, 0x2c, 0x75, 0x63, 0x09, 0x02, 0x39, 0x2c, 0x78, 0x73, 0xe6, 0xc3, 0x94, 0xff, 0x50, 0x01, +0x06, 0x74, 0x1e, 0xc3, 0x78, 0x73, 0x96, 0x50, 0x03, 0x75, 0x63, 0x01, 0xe5, 0x63, 0x64, 0x09, +0x60, 0x03, 0x02, 0x39, 0x2c, 0x05, 0x63, 0x02, 0x39, 0x2c, 0xe5, 0x29, 0x64, 0x01, 0x70, 0x76, +0xe5, 0x63, 0xb4, 0x03, 0x05, 0x75, 0x63, 0x04, 0x80, 0x64, 0xe5, 0x63, 0xb4, 0x09, 0x04, 0x15, +0x63, 0x80, 0x5b, 0x75, 0x63, 0x02, 0xe4, 0x78, 0x64, 0xf6, 0x08, 0xf6, 0x78, 0x6a, 0x12, 0x04, +0x7d, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x78, 0x6e, 0xf6, 0x12, 0x39, 0x46, 0x78, 0x75, 0xf6, 0x18, +0xf6, 0x78, 0x76, 0xf6, 0x78, 0x66, 0x12, 0x39, 0x47, 0xc3, 0xe5, 0x24, 0x94, 0x14, 0xe5, 0x23, +0x64, 0x80, 0x94, 0x80, 0x40, 0x25, 0xe5, 0x26, 0x94, 0x14, 0xe5, 0x25, 0x64, 0x80, 0x94, 0x80, +0x40, 0x19, 0xd3, 0xe5, 0x24, 0x94, 0xcc, 0xe5, 0x23, 0x64, 0x80, 0x94, 0x81, 0x50, 0x0c, 0xe5, +0x26, 0x94, 0xac, 0xe5, 0x25, 0x64, 0x80, 0x94, 0x83, 0x40, 0x03, 0x75, 0x63, 0x01, 0xe4, 0x78, +0x73, 0xf6, 0x78, 0x77, 0x31, 0x47, 0xe5, 0x63, 0xc3, 0x94, 0x02, 0x50, 0x02, 0x21, 0x1a, 0xe5, +0x63, 0xb4, 0x02, 0x02, 0x05, 0x63, 0xc3, 0xe5, 0x26, 0x78, 0x7a, 0x96, 0xff, 0xe5, 0x25, 0x31, +0x40, 0xc0, 0x06, 0xc0, 0x07, 0xc3, 0x78, 0x78, 0x31, 0x3a, 0xd0, 0xe0, 0x2f, 0xf5, 0x28, 0xd0, +0xe0, 0x3e, 0xf5, 0x27, 0xc3, 0xe5, 0x28, 0x94, 0x0f, 0xe5, 0x27, 0x94, 0x00, 0x50, 0x02, 0x01, +0xe3, 0x78, 0x77, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x08, 0xe6, 0xf5, 0x30, 0x08, 0xe6, 0xf5, 0x31, +0xad, 0x26, 0xac, 0x25, 0xaf, 0x24, 0xae, 0x23, 0x12, 0x36, 0x13, 0x78, 0x75, 0xe6, 0xfe, 0x6f, +0x60, 0x08, 0xe4, 0x08, 0xf6, 0x18, 0xa6, 0x07, 0x80, 0x74, 0x78, 0x76, 0xe6, 0x64, 0x02, 0x70, +0x6d, 0x78, 0x74, 0xe6, 0xfd, 0xee, 0xc3, 0x9d, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0x12, 0x00, 0x12, +0xd3, 0xef, 0x94, 0x01, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0x1a, 0x78, 0x74, 0xe6, 0xff, 0x08, +0xe6, 0x9f, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0x12, 0x00, 0x12, 0xc3, 0xef, 0x94, 0x07, 0xee, 0x64, +0x80, 0x94, 0x80, 0x40, 0x05, 0x78, 0x74, 0xe6, 0x70, 0x30, 0x78, 0x6a, 0x12, 0x04, 0x58, 0x78, +0x04, 0x12, 0x04, 0x45, 0x78, 0x6a, 0x12, 0x04, 0x71, 0x78, 0x6a, 0x12, 0x04, 0x64, 0xc0, 0x00, +0x78, 0x75, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0xd0, 0x00, 0x12, 0x03, 0xfe, 0x78, 0x6a, 0x12, +0x04, 0x71, 0x78, 0x6e, 0x06, 0x78, 0x75, 0xe6, 0x18, 0xf6, 0xe4, 0x78, 0x76, 0xf6, 0x78, 0x76, +0x06, 0x31, 0x46, 0xc3, 0xe5, 0x26, 0x78, 0x69, 0x96, 0xff, 0xe5, 0x25, 0x31, 0x40, 0xc0, 0x06, +0xc0, 0x07, 0xc3, 0x78, 0x67, 0x31, 0x3a, 0xd0, 0xe0, 0x2f, 0xf5, 0x28, 0xd0, 0xe0, 0x3e, 0xf5, +0x27, 0xc3, 0xe5, 0x28, 0x94, 0x96, 0xe5, 0x27, 0x94, 0x00, 0x50, 0x0b, 0x78, 0x65, 0xe6, 0x94, +0x78, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x63, 0x08, 0x31, 0x53, 0x50, 0x07, 0x08, 0x06, +0xe6, 0x18, 0x70, 0x01, 0x06, 0x31, 0x5e, 0x40, 0x03, 0x75, 0x63, 0x01, 0xe5, 0x63, 0xb4, 0x0a, +0x06, 0x75, 0x63, 0x01, 0x02, 0x1e, 0xf1, 0x7f, 0xff, 0x22, 0xe5, 0x24, 0x96, 0xff, 0xe5, 0x23, +0x18, 0x96, 0xfe, 0x02, 0x00, 0x12, 0x08, 0xa6, 0x23, 0x08, 0xa6, 0x24, 0x08, 0xa6, 0x25, 0x08, +0xa6, 0x26, 0x22, 0xc3, 0x78, 0x65, 0xe6, 0x94, 0xe8, 0x18, 0xe6, 0x94, 0x03, 0x22, 0xd3, 0x78, +0x65, 0xe6, 0x94, 0xf4, 0x18, 0xe6, 0x94, 0x01, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x41, 0xf5, +0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0xe5, 0x41, 0xf0, 0xa3, 0xe5, 0x42, 0xf0, 0xe5, 0x32, 0x25, +0xe0, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0xf5, 0x83, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x7b, +0x00, 0x02, 0x04, 0xdf, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x41, 0xf5, 0x82, 0xe4, 0x34, 0x04, 0x22, +0xe5, 0x32, 0x25, 0xe0, 0x24, 0x61, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0x22, 0x74, 0x3a, +0x25, 0x36, 0xf8, 0xa6, 0x37, 0xe5, 0x36, 0x25, 0xe0, 0x24, 0x87, 0xf8, 0xa6, 0x3d, 0x08, 0xa6, +0x3e, 0x05, 0x36, 0x22, 0xf9, 0x09, 0xe3, 0x25, 0xe0, 0xff, 0x19, 0xe3, 0x33, 0xfe, 0xef, 0x25, +0x3c, 0xf5, 0x3c, 0xee, 0x35, 0x3b, 0xf5, 0x3b, 0x22, 0x74, 0x51, 0x25, 0x32, 0xf5, 0x82, 0xe4, +0x34, 0x04, 0xf5, 0x83, 0x22, 0xf8, 0xe5, 0x43, 0xf2, 0x08, 0xe5, 0x44, 0xf2, 0x22, 0xf8, 0xe5, +0x41, 0xf2, 0x08, 0xe5, 0x42, 0xf2, 0x22, 0xef, 0x54, 0x07, 0x90, 0x07, 0xdd, 0x93, 0xfc, 0xef, +0xc4, 0x54, 0x0f, 0xff, 0x22, 0xe5, 0x43, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0x22, 0xaf, 0x36, 0x7c, +0x00, 0x12, 0x01, 0xd9, 0x8e, 0x35, 0x8f, 0x36, 0x22, 0xe5, 0x32, 0x25, 0xe0, 0x24, 0x87, 0xf5, +0x82, 0xe4, 0x34, 0x02, 0x22, 0x7d, 0x00, 0x7b, 0xff, 0x7e, 0x00, 0x02, 0x00, 0xf4, 0xee, 0x8f, +0xf0, 0x02, 0x02, 0x0f, 0xc3, 0xe5, 0x42, 0x9f, 0xff, 0xe5, 0x41, 0x9e, 0xfe, 0x22, 0xe0, 0xfa, +0xa3, 0xe0, 0xfb, 0xe5, 0x16, 0x22, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x01, 0xd9, 0xe0, 0xfe, 0xa3, +0xe0, 0xc3, 0x95, 0x44, 0x22, 0xaf, 0x34, 0xae, 0x33, 0x02, 0x00, 0x12, 0x2d, 0xff, 0xec, 0x3e, +0xfe, 0xe5, 0x16, 0x22, 0xf9, 0xe3, 0xfe, 0x09, 0xe3, 0x78, 0x02, 0x22, 0xe5, 0x3b, 0xf0, 0xa3, +0xe5, 0x3c, 0xf0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x01, 0x10, 0x00, 0x0b, 0x04, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst8xxT_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst8xxT_fw.h new file mode 100644 index 000000000000..baeef89a143e --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst8xxT_fw.h @@ -0,0 +1,984 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst8xxT_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { +0x00, 0x00, 0x00, 0x3c, 0xdc, 0x56, +0x02, 0x2b, 0xae, 0x75, 0x91, 0xcc, 0x75, 0x91, 0x00, 0x32, 0x32, 0x22, 0x02, 0x00, 0x03, 0x02, +0x2e, 0xfe, 0x74, 0xb7, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xff, 0x22, 0x22, +0x00, 0x02, 0x32, 0x3f, 0xe4, 0x7b, 0x02, 0xfa, 0xf9, 0xf8, 0xaf, 0x00, 0xae, 0x00, 0xad, 0x00, +0xac, 0x00, 0x12, 0x0f, 0x42, 0xef, 0x25, 0x00, 0xff, 0xee, 0x35, 0x00, 0xfe, 0xed, 0x35, 0x00, +0xfd, 0xec, 0x35, 0x00, 0xfc, 0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0x12, 0x0f, 0x42, +0xef, 0x24, 0xe0, 0xfb, 0xee, 0x34, 0xff, 0xfa, 0xed, 0x34, 0xff, 0xf9, 0xec, 0x34, 0xff, 0xf8, +0x85, 0x0f, 0x82, 0x85, 0x0e, 0x83, 0x22, 0x74, 0x1c, 0x93, 0x24, 0x64, 0xff, 0xe4, 0x33, 0xfe, +0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x8f, +0x00, 0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x00, 0xaa, 0x00, 0xa9, +0x00, 0xa8, 0x00, 0xe4, 0xfc, 0xfd, 0xc3, 0x02, 0x0f, 0xd4, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x0d, +0xf8, 0xe4, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x16, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xa8, 0x07, 0xe8, +0x24, 0x18, 0xf8, 0xe4, 0xf2, 0x08, 0xf2, 0xef, 0x04, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef, 0x24, +0x2b, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c, 0x68, 0x78, 0x66, 0xe6, +0xff, 0x24, 0x05, 0xf8, 0xe4, 0xf2, 0xef, 0x04, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef, 0x24, 0x07, +0x7f, 0x06, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x02, 0x0c, 0x68, 0xeb, 0x25, 0xe0, 0x25, +0xe0, 0x24, 0x61, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x22, 0xe6, 0xff, 0x24, 0x2b, 0xf8, 0xe2, +0xfc, 0x08, 0xe2, 0xfd, 0xa8, 0x07, 0xe8, 0x04, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x78, 0x66, +0xe6, 0xff, 0x24, 0x2d, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xa8, 0x07, 0xe8, 0x22, 0xab, 0x00, +0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xa8, 0x04, +0xa9, 0x05, 0xaa, 0x06, 0xab, 0x07, 0x22, 0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0xe5, 0x00, 0x75, +0xf0, 0x02, 0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x02, 0x0d, 0xe6, 0x74, 0x1d, 0x93, 0x24, 0x64, +0xff, 0xe4, 0x33, 0xfe, 0xe4, 0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8, +0x12, 0x0f, 0x42, 0x8f, 0x00, 0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0xae, 0x00, 0xaf, 0x00, 0xab, +0x00, 0xaa, 0x00, 0xa9, 0x00, 0xa8, 0x00, 0xe4, 0xfc, 0xfd, 0xc3, 0x02, 0x0f, 0xd4, 0xaf, 0x00, +0xef, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xfe, 0x74, 0xb5, 0x2f, 0xf5, +0x82, 0x74, 0x00, 0x3e, 0xf5, 0x83, 0x22, 0x78, 0x68, 0xa6, 0x07, 0x78, 0x6b, 0xe6, 0x78, 0x69, +0xf6, 0x90, 0x00, 0xb7, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x00, 0xb5, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, +0x08, 0x76, 0xff, 0x22, 0x7e, 0x00, 0x7d, 0x00, 0x7f, 0x04, 0x7b, 0x01, 0x7a, 0x00, 0x79, 0xb5, +0x02, 0x10, 0x98, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xed, 0x39, 0xfd, 0xec, 0x38, 0xfc, 0x22, +0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0x85, 0x00, 0x82, 0x75, 0x83, 0x00, 0xe5, 0x00, 0x12, 0x0c, +0xe6, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0xf5, 0x83, 0x22, 0x74, +0x15, 0x93, 0x08, 0x26, 0x25, 0xe0, 0x24, 0x5f, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xef, 0x25, +0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2d, 0xff, 0x18, 0xe2, 0x3c, 0xc3, 0x13, 0xf5, 0x00, 0xef, 0x13, +0xf5, 0x00, 0xd3, 0x74, 0x10, 0x93, 0x95, 0x00, 0x74, 0x0f, 0x93, 0x95, 0x00, 0x22, 0xe5, 0x00, +0x25, 0xe0, 0xff, 0xe5, 0x00, 0x33, 0xfe, 0xef, 0x24, 0xff, 0xff, 0xee, 0x34, 0xff, 0xfe, 0xe4, +0xfc, 0xfd, 0x22, 0xeb, 0x7b, 0x64, 0x2f, 0xff, 0xea, 0x3e, 0xfe, 0xe9, 0x3d, 0xfd, 0xe8, 0x3c, +0xfc, 0xe4, 0xfa, 0xf9, 0xf8, 0x22, 0x74, 0x1c, 0x93, 0x24, 0x64, 0xff, 0xe4, 0x33, 0xfe, 0xe4, +0xfc, 0xfd, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, 0x64, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x8f, 0x00, +0x8e, 0x00, 0x8d, 0x00, 0x8c, 0x00, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xe6, 0xff, +0x33, 0x95, 0xe0, 0xfe, 0xad, 0x00, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xc3, 0x22, 0x93, 0xfd, 0x12, +0x0d, 0x08, 0x7c, 0x00, 0x7d, 0x32, 0x12, 0x0d, 0x1a, 0xe5, 0x28, 0x2f, 0xf5, 0x2e, 0xe5, 0x27, +0x3e, 0xf5, 0x2d, 0xd3, 0xe5, 0x2e, 0x94, 0x00, 0xe5, 0x2d, 0x64, 0x80, 0x94, 0x80, 0x22, 0x7a, +0x00, 0x79, 0x02, 0x7b, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x0c, 0x68, 0x75, 0xf0, 0x2f, 0xa4, +0x24, 0x02, 0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x22, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x60, +0xf8, 0xe2, 0x2f, 0xf5, 0x26, 0x18, 0xe2, 0x3e, 0xf5, 0x25, 0x22, 0x13, 0x2d, 0xff, 0xee, 0x3c, +0xfe, 0x7c, 0x00, 0x7d, 0x03, 0x02, 0x0d, 0x08, 0x25, 0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2f, 0xff, +0x18, 0xe2, 0x3e, 0xfe, 0x22, 0x7e, 0x00, 0x7f, 0x04, 0x7d, 0xff, 0x7b, 0x00, 0x7a, 0x00, 0x79, +0x68, 0x02, 0x10, 0x98, 0x24, 0x09, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x78, 0x66, 0xe6, 0x24, +0x0e, 0xf8, 0xe2, 0xc3, 0x22, 0x74, 0x01, 0x93, 0xfe, 0x74, 0x02, 0x93, 0xff, 0xe4, 0xfc, 0xfd, +0x02, 0x10, 0x17, 0x74, 0x1a, 0x93, 0xff, 0x33, 0x95, 0xe0, 0xfe, 0xfd, 0xfc, 0xeb, 0x2f, 0x22, +0xaf, 0x00, 0xef, 0x33, 0x95, 0xe0, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xab, 0x00, 0xaa, +0x00, 0xa9, 0x00, 0x8f, 0x82, 0xf5, 0x83, 0x02, 0x0d, 0xe6, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x07, +0xaa, 0x06, 0xc3, 0xe5, 0x00, 0x9b, 0xfb, 0xe5, 0x00, 0x9a, 0xfa, 0xe5, 0x00, 0x94, 0x00, 0xf9, +0xe5, 0x00, 0x94, 0x00, 0x22, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x74, 0x04, 0x93, 0xfe, 0x74, +0x05, 0x93, 0xff, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x07, 0xf9, 0x7a, 0x00, 0x7b, 0xfe, 0xef, +0x22, 0xeb, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xe6, 0x22, 0xae, 0x00, 0xaf, 0x00, 0xab, 0x00, 0xaa, +0x00, 0xa9, 0x00, 0xa8, 0x00, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0xff, 0xe5, 0x00, 0x33, 0xab, 0x07, +0xfa, 0xe4, 0xf9, 0xf8, 0x22, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x04, 0x02, 0x0c, +0x68, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0xc3, 0xe5, 0x00, 0x9d, 0xf5, 0x00, 0xe5, 0x00, 0x9c, +0xf5, 0x00, 0xa8, 0x07, 0xe8, 0x22, 0x2f, 0xff, 0xe0, 0x3e, 0xfe, 0xd3, 0xe5, 0x00, 0x9f, 0xe5, +0x00, 0x9e, 0x22, 0xc3, 0xe5, 0x00, 0x95, 0x00, 0xff, 0xe5, 0x00, 0x95, 0x00, 0xfe, 0x22, 0xe4, +0xfa, 0xf9, 0xf8, 0xee, 0x33, 0x95, 0xe0, 0xfd, 0xfc, 0x22, 0x74, 0x18, 0x93, 0xfb, 0x7c, 0x00, +0x7d, 0x0a, 0x12, 0x0d, 0x1a, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x10, 0x6b, 0xef, 0x22, 0xc3, 0xe5, +0x00, 0x95, 0x00, 0xff, 0xe5, 0x00, 0x95, 0x00, 0xfe, 0xe4, 0x95, 0x00, 0xfd, 0xe4, 0x95, 0x00, +0xfc, 0x22, 0xe4, 0x93, 0xfd, 0x7c, 0x00, 0x74, 0x03, 0x93, 0xfe, 0x74, 0x04, 0x93, 0xff, 0x22, +0xc3, 0x74, 0x64, 0x95, 0x23, 0xff, 0xe4, 0x94, 0x00, 0xfe, 0xe4, 0xfc, 0xfd, 0x22, 0x9d, 0xfd, +0xe4, 0x94, 0x00, 0xfc, 0xe5, 0x22, 0x75, 0xf0, 0x0a, 0xa4, 0x22, 0x25, 0xe0, 0x24, 0x5f, 0xf8, +0xe2, 0x22, 0xc3, 0xe5, 0x00, 0x95, 0x00, 0xfb, 0xe5, 0x00, 0x95, 0x00, 0xfa, 0xe4, 0x95, 0x00, +0xf9, 0xe4, 0x95, 0x00, 0x22, 0xe5, 0x00, 0x25, 0x00, 0xff, 0xe5, 0x00, 0x35, 0x00, 0xfe, 0xe4, +0x35, 0x00, 0xfd, 0xe4, 0x35, 0x00, 0xfc, 0x22, 0x7e, 0x00, 0x7f, 0x06, 0x7d, 0x00, 0x7b, 0xfe, +0x02, 0x10, 0x98, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0x12, 0x10, 0x17, 0x12, 0x0e, 0xb7, 0xe4, 0x7b, +0x02, 0xfa, 0xf9, 0xf8, 0x22, 0xf8, 0xe2, 0x2f, 0xf5, 0x28, 0x18, 0xe2, 0x3e, 0xf5, 0x27, 0x22, +0xea, 0x33, 0x95, 0xe0, 0xf9, 0xf8, 0xe4, 0xfc, 0xfd, 0x02, 0x0e, 0xb7, 0x85, 0x0d, 0x82, 0x85, +0x0c, 0x83, 0x74, 0x05, 0x93, 0x22, 0xff, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xef, 0x2d, 0xff, 0xe4, +0x3c, 0xc3, 0x13, 0xef, 0x13, 0x22, 0x24, 0x03, 0xf8, 0xec, 0xf2, 0x08, 0xed, 0xf2, 0x22, 0xf5, +0x83, 0xe5, 0x82, 0x2d, 0xf5, 0x82, 0xe5, 0x83, 0x3c, 0xf5, 0x83, 0xef, 0xf0, 0x22, 0xe5, 0x00, +0x25, 0xe0, 0x24, 0x69, 0xf8, 0xe6, 0x22, 0xf5, 0x00, 0xea, 0x3e, 0xf5, 0x00, 0xe9, 0x3d, 0xf5, +0x00, 0xe8, 0x3c, 0xf5, 0x00, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x05, 0xf8, 0xe2, 0x22, 0x74, +0x1e, 0x93, 0xfe, 0xa8, 0x07, 0xe8, 0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x9e, 0x22, 0x24, 0x02, 0xf8, +0xc3, 0xe2, 0x9d, 0xf5, 0x29, 0x18, 0xe2, 0x9c, 0xf5, 0x28, 0x22, 0x24, 0x04, 0xf8, 0xc3, 0xe2, +0x9d, 0xf5, 0x2b, 0x18, 0xe2, 0x9c, 0xf5, 0x2a, 0x22, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0x2f, 0xff, +0xee, 0x3c, 0xfe, 0xef, 0x78, 0x02, 0x22, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x04, 0x22, 0xff, 0xae, +0xf0, 0xe4, 0xfc, 0xfd, 0x22, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x2b, 0x22, 0x78, 0x66, 0xe6, 0x24, +0x0f, 0xf8, 0x22, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xe9, 0x3d, 0xfd, 0xe8, 0x3c, 0xfc, 0x22, +0xef, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x01, 0xf8, 0x22, 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0x22, +0xab, 0x00, 0xaa, 0x00, 0xa9, 0x00, 0x22, 0xc3, 0xe5, 0x00, 0x9f, 0xf5, 0x00, 0xe5, 0x00, 0x9e, +0xf5, 0x00, 0x22, 0x78, 0x53, 0x12, 0x10, 0x0b, 0x78, 0x4f, 0x12, 0x10, 0x17, 0xeb, 0x22, 0xe5, +0x30, 0x25, 0x30, 0xf5, 0x30, 0xe5, 0x2f, 0x33, 0xf5, 0x2f, 0x22, 0xc3, 0xe5, 0x26, 0x95, 0x28, +0xff, 0xe5, 0x25, 0x95, 0x27, 0xfe, 0x22, 0xe5, 0x00, 0xf0, 0xa3, 0xe5, 0x00, 0xf0, 0x22, 0xf9, +0x7a, 0x00, 0x7b, 0xfe, 0x75, 0xf0, 0x02, 0xe5, 0x00, 0x22, 0x13, 0xfb, 0xaa, 0x06, 0xe4, 0xf9, +0xf8, 0x22, 0xf8, 0xe4, 0xf2, 0x08, 0x74, 0x80, 0xf2, 0xa8, 0x07, 0xe8, 0x22, 0xe4, 0xfc, 0xfd, +0xeb, 0x25, 0x00, 0xff, 0xea, 0x35, 0x00, 0x22, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x02, 0x22, 0xce, +0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0x78, 0x66, 0xe6, 0x24, 0x1a, 0xf8, 0x22, 0x78, 0x66, 0xe6, +0x24, 0x0d, 0xf8, 0x22, 0xd3, 0xe5, 0x35, 0x95, 0x37, 0xe5, 0x34, 0x95, 0x36, 0x22, 0x33, 0xfe, +0x7c, 0x00, 0x7d, 0x03, 0x02, 0x0d, 0x1a, 0x24, 0x40, 0xff, 0xe4, 0x3e, 0xfe, 0x22, 0xe5, 0x00, +0x25, 0xe0, 0x24, 0x68, 0x22, 0xe5, 0x00, 0x25, 0xe0, 0x24, 0x69, 0x22, 0x8f, 0x22, 0x8d, 0x23, +0x12, 0x04, 0xd6, 0x70, 0x03, 0x02, 0x0b, 0x41, 0x12, 0x00, 0x60, 0x12, 0x04, 0xdf, 0x50, 0x06, +0x12, 0x00, 0x9a, 0x02, 0x07, 0x1f, 0x12, 0x05, 0xcd, 0xe2, 0x70, 0x50, 0x12, 0x05, 0x25, 0x12, +0x01, 0x14, 0x12, 0x04, 0xed, 0x12, 0x01, 0x0e, 0x12, 0x04, 0xfb, 0x12, 0x00, 0x60, 0x74, 0x17, +0x93, 0x75, 0x34, 0x00, 0xf5, 0x35, 0xaf, 0x2b, 0xae, 0x2a, 0x12, 0x39, 0xa3, 0xc0, 0x06, 0xc0, +0x07, 0xaf, 0x29, 0xae, 0x28, 0x12, 0x39, 0xa3, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, +0xd3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x40, 0x08, 0x12, 0x05, 0xcd, 0x74, 0x01, 0xf2, 0x80, +0x23, 0xe4, 0xf5, 0x28, 0xf5, 0x29, 0xf5, 0x2a, 0xf5, 0x2b, 0x80, 0x18, 0x78, 0x66, 0xe6, 0xff, +0x24, 0x07, 0x12, 0x01, 0x14, 0x12, 0x04, 0xed, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x09, 0x12, 0x01, +0x14, 0x12, 0x04, 0xfb, 0x12, 0x04, 0x10, 0xc0, 0x04, 0x12, 0x01, 0x30, 0x78, 0x66, 0xe6, 0x24, +0x16, 0x12, 0x00, 0xf3, 0x12, 0x03, 0xd3, 0xd0, 0x00, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05, +0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x23, 0xab, 0x07, 0xae, 0x28, 0xaf, 0x29, 0x12, 0x03, 0xcf, 0x12, +0x0e, 0xb7, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x02, 0x33, 0x12, 0x33, 0x10, +0x8e, 0x28, 0x8f, 0x29, 0x12, 0x04, 0x10, 0xc0, 0x04, 0x12, 0x01, 0x30, 0x78, 0x66, 0xe6, 0x24, +0x18, 0x12, 0x00, 0xf3, 0x12, 0x03, 0xd3, 0xd0, 0x00, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05, +0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x23, 0xab, 0x07, 0xae, 0x2a, 0xaf, 0x2b, 0x12, 0x03, 0xcf, 0x12, +0x0e, 0xb7, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x02, 0x33, 0x12, 0x33, 0x10, +0x8e, 0x2a, 0x8f, 0x2b, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x16, 0xf8, 0xe5, 0x28, 0xf2, 0x08, 0xe5, +0x29, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x18, 0xf8, 0xe5, 0x2a, 0xf2, 0x08, 0xe5, 0x2b, 0xf2, 0x12, +0x00, 0x60, 0x74, 0x1e, 0x93, 0xff, 0x12, 0x02, 0xfc, 0x9f, 0x50, 0x03, 0x02, 0x0b, 0x1a, 0x78, +0x66, 0xe6, 0xfb, 0x24, 0x07, 0xf8, 0xe2, 0xfe, 0x08, 0xe2, 0xfd, 0xac, 0x06, 0xe5, 0x28, 0xa2, +0xe7, 0x13, 0xfe, 0xe5, 0x29, 0x12, 0x02, 0xcb, 0xa8, 0x03, 0xe8, 0x04, 0x12, 0x05, 0x09, 0x12, +0x05, 0xbf, 0xd8, 0xfb, 0xff, 0x12, 0x00, 0x60, 0x74, 0x01, 0x93, 0xfc, 0x74, 0x02, 0x93, 0xfd, +0x12, 0x35, 0x58, 0x8e, 0x24, 0x8f, 0x25, 0x78, 0x66, 0xe6, 0xfb, 0x24, 0x09, 0xf8, 0xe2, 0xfe, +0x08, 0xe2, 0xfd, 0xac, 0x06, 0xe5, 0x2a, 0xa2, 0xe7, 0x13, 0xfe, 0xe5, 0x2b, 0x12, 0x02, 0xcb, +0xa8, 0x03, 0xe8, 0x24, 0x03, 0x12, 0x05, 0x09, 0x12, 0x05, 0xbf, 0xd8, 0xfb, 0xff, 0x12, 0x00, +0x60, 0x74, 0x03, 0x93, 0xfc, 0x74, 0x04, 0x93, 0xfd, 0x12, 0x35, 0x58, 0x8e, 0x26, 0x8f, 0x27, +0x12, 0x00, 0x60, 0x74, 0x1e, 0x93, 0x24, 0x0a, 0xff, 0xe4, 0x33, 0xfe, 0x78, 0x66, 0xe6, 0xfd, +0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x9f, 0xee, 0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x50, 0x59, 0xa8, +0x05, 0xe8, 0x24, 0x16, 0x12, 0x00, 0xf3, 0x12, 0x39, 0xa3, 0x12, 0x00, 0x60, 0x74, 0x1e, 0x93, +0xfd, 0x78, 0x66, 0xe6, 0xf9, 0x24, 0x0e, 0xf8, 0xe2, 0xc3, 0x12, 0x04, 0x1e, 0x24, 0x8d, 0xf5, +0x82, 0xe4, 0x34, 0x00, 0x12, 0x04, 0xaf, 0xa8, 0x01, 0xe8, 0x24, 0x18, 0x12, 0x00, 0xf3, 0x12, +0x39, 0xa3, 0x12, 0x00, 0x60, 0x74, 0x1e, 0x93, 0xfd, 0x12, 0x02, 0xfc, 0x12, 0x04, 0x1e, 0x24, +0xa1, 0xf5, 0x82, 0xe4, 0x34, 0x00, 0x12, 0x04, 0xaf, 0x75, 0x38, 0x00, 0x75, 0x39, 0x80, 0x75, +0x3a, 0x00, 0x75, 0x3b, 0x80, 0x02, 0x09, 0x89, 0x12, 0x04, 0x24, 0x24, 0x96, 0xf9, 0x74, 0x00, +0x35, 0xf0, 0xfa, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x78, 0x66, 0xe6, 0x24, 0x16, +0x12, 0x00, 0xf3, 0x12, 0x39, 0xa3, 0xad, 0x07, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x12, 0x34, +0x7a, 0x8e, 0x34, 0x8f, 0x35, 0x12, 0x04, 0x24, 0x24, 0xaa, 0xf9, 0x74, 0x00, 0x35, 0xf0, 0xfa, +0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x78, 0x66, 0xe6, 0x24, 0x18, 0x12, 0x00, 0xf3, +0x12, 0x39, 0xa3, 0xad, 0x07, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x12, 0x34, 0x7a, 0x8e, 0x36, +0x8f, 0x37, 0x12, 0x05, 0xd4, 0x40, 0x18, 0xe5, 0x35, 0xae, 0x34, 0x78, 0x03, 0xc3, 0x33, 0xce, +0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe5, 0x37, 0x24, 0x01, 0xfd, 0xe4, 0x35, 0x36, 0x80, 0x16, 0xe5, +0x37, 0xae, 0x36, 0x78, 0x03, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe5, 0x35, 0x24, +0x01, 0xfd, 0xe4, 0x35, 0x34, 0xfc, 0x12, 0x0d, 0x1a, 0xab, 0x07, 0xaa, 0x06, 0x78, 0x66, 0xe6, +0xf9, 0x24, 0x10, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xef, 0x2b, 0xff, 0xee, 0x3a, 0xfe, 0xef, +0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xfb, 0xaa, 0x06, 0xc3, 0x94, 0x28, 0xea, +0x94, 0x00, 0x50, 0x06, 0x7a, 0x00, 0x7b, 0x28, 0x80, 0x0d, 0xd3, 0xeb, 0x94, 0x46, 0xea, 0x94, +0x00, 0x40, 0x04, 0x7a, 0x00, 0x7b, 0x46, 0x7c, 0x00, 0x7d, 0x0a, 0xaf, 0x03, 0xae, 0x02, 0x12, +0x0d, 0x08, 0xef, 0x24, 0xf0, 0xf5, 0x39, 0xee, 0x34, 0xfe, 0xf5, 0x38, 0xeb, 0x25, 0xe0, 0xff, +0xea, 0x33, 0xfe, 0xc3, 0x74, 0xd0, 0x9f, 0xf5, 0x3b, 0xe4, 0x9e, 0xf5, 0x3a, 0x12, 0x05, 0xd4, +0x40, 0x12, 0x85, 0x38, 0x34, 0x85, 0x39, 0x35, 0x85, 0x3a, 0x38, 0x85, 0x3b, 0x39, 0x85, 0x34, +0x3a, 0x85, 0x35, 0x3b, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x10, 0xf8, 0xea, 0xf2, 0x08, 0xeb, 0xf2, +0xa8, 0x07, 0xe8, 0x24, 0x12, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xe5, 0x39, 0x2f, 0xff, 0xe5, +0x38, 0x3e, 0xfe, 0xef, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xf5, 0x39, 0x8e, +0x38, 0x78, 0x66, 0xe6, 0xfb, 0x24, 0x14, 0x12, 0x00, 0xf3, 0x12, 0x02, 0xd1, 0xe5, 0x3b, 0x2f, +0xff, 0xe5, 0x3a, 0x3e, 0xfe, 0xef, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xf5, +0x3b, 0x8e, 0x3a, 0xeb, 0x24, 0x12, 0xf8, 0xe5, 0x38, 0xf2, 0x08, 0xe5, 0x39, 0xf2, 0xe9, 0x24, +0x14, 0xf8, 0xe5, 0x3a, 0xf2, 0x08, 0xe5, 0x3b, 0xf2, 0x12, 0x0b, 0x70, 0x7c, 0x00, 0x7d, 0x02, +0x12, 0x0d, 0x6f, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x0b, 0x84, 0xd0, 0xe0, 0x2f, 0xf5, 0x35, 0xd0, +0xe0, 0x3e, 0xf5, 0x34, 0x12, 0x00, 0x60, 0xae, 0x34, 0xaf, 0x35, 0x12, 0x03, 0xda, 0x25, 0x35, +0xf5, 0x35, 0xee, 0x35, 0x34, 0xf5, 0x34, 0xd3, 0xe5, 0x35, 0x95, 0x39, 0xe5, 0x34, 0x95, 0x38, +0x40, 0x06, 0x85, 0x38, 0x34, 0x85, 0x39, 0x35, 0x78, 0x66, 0xe6, 0x24, 0x07, 0x12, 0x00, 0xf3, +0xc3, 0xe5, 0x39, 0x95, 0x35, 0xfd, 0xe5, 0x38, 0x95, 0x34, 0xfc, 0x12, 0x10, 0x6b, 0x8f, 0x2f, +0x8e, 0x2e, 0x8d, 0x2d, 0x8c, 0x2c, 0xae, 0x24, 0xaf, 0x25, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x34, +0xaf, 0x35, 0x12, 0x04, 0x80, 0xef, 0x25, 0x2f, 0xff, 0xee, 0x35, 0x2e, 0xfe, 0xed, 0x35, 0x2d, +0xfd, 0xec, 0x35, 0x2c, 0xfc, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x38, 0xc3, 0x13, 0xfe, 0xe5, 0x39, +0x12, 0x05, 0x9a, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x05, 0x33, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x38, +0xaf, 0x39, 0xab, 0x07, 0xaa, 0x06, 0xe4, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0x8f, 0x2f, +0x8e, 0x2e, 0x8d, 0x2d, 0x8c, 0x2c, 0x12, 0x0b, 0x84, 0x7c, 0x00, 0x7d, 0x02, 0x12, 0x0d, 0x6f, +0xc0, 0x06, 0xc0, 0x07, 0x12, 0x0b, 0x70, 0xd0, 0xe0, 0x2f, 0xf5, 0x37, 0xd0, 0xe0, 0x3e, 0xf5, +0x36, 0x12, 0x00, 0x60, 0xae, 0x36, 0xaf, 0x37, 0x12, 0x03, 0xda, 0x25, 0x37, 0xf5, 0x37, 0xee, +0x35, 0x36, 0xf5, 0x36, 0xd3, 0xe5, 0x37, 0x95, 0x3b, 0xe5, 0x36, 0x95, 0x3a, 0x40, 0x06, 0x85, +0x3a, 0x36, 0x85, 0x3b, 0x37, 0x78, 0x66, 0xe6, 0x24, 0x09, 0x12, 0x00, 0xf3, 0xc3, 0xe5, 0x3b, +0x95, 0x37, 0xfd, 0xe5, 0x3a, 0x95, 0x36, 0xfc, 0x12, 0x10, 0x6b, 0x8f, 0x33, 0x8e, 0x32, 0x8d, +0x31, 0x8c, 0x30, 0xae, 0x26, 0xaf, 0x27, 0xab, 0x07, 0xaa, 0x06, 0xae, 0x36, 0xaf, 0x37, 0x12, +0x04, 0x80, 0xef, 0x25, 0x33, 0xff, 0xee, 0x35, 0x32, 0xfe, 0xed, 0x35, 0x31, 0xfd, 0xec, 0x35, +0x30, 0xfc, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3a, 0xc3, 0x13, 0xfe, 0xe5, 0x3b, 0x12, 0x05, 0x9a, +0xd0, 0x07, 0xd0, 0x06, 0x12, 0x05, 0x33, 0xc0, 0x06, 0xc0, 0x07, 0xae, 0x3a, 0xaf, 0x3b, 0xab, +0x07, 0xaa, 0x06, 0xe4, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0x8f, 0x33, 0x8e, 0x32, 0x8d, +0x31, 0x8c, 0x30, 0x12, 0x00, 0x60, 0x74, 0x16, 0x93, 0xf4, 0x60, 0x2e, 0x78, 0x66, 0xe6, 0xff, +0x24, 0x0d, 0xf8, 0xe2, 0xb4, 0x01, 0x1b, 0xa8, 0x07, 0xe8, 0x04, 0xf8, 0xe5, 0x2e, 0xf2, 0x08, +0xe5, 0x2f, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x03, 0xf8, 0xe5, 0x32, 0xf2, 0x08, 0xe5, 0x33, 0xf2, +0x80, 0x08, 0x78, 0x66, 0x12, 0x00, 0xfa, 0x12, 0x04, 0xa6, 0x78, 0x66, 0xe6, 0xff, 0x04, 0x12, +0x01, 0x14, 0x24, 0x07, 0x12, 0x04, 0xa8, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x03, 0x12, 0x01, 0x14, +0x12, 0x02, 0xf4, 0x94, 0x14, 0x50, 0x03, 0xe2, 0x04, 0xf2, 0x12, 0x05, 0x2c, 0x74, 0x01, 0xf2, +0x22, 0x12, 0x05, 0x2c, 0xe2, 0xd3, 0x94, 0x00, 0x40, 0x03, 0xe2, 0x14, 0xf2, 0xe2, 0x70, 0x1f, +0x78, 0x66, 0xe6, 0xff, 0x24, 0x0e, 0xf8, 0xe4, 0xf2, 0xa8, 0x07, 0xe8, 0x24, 0x12, 0x12, 0x05, +0xa2, 0x24, 0x14, 0x12, 0x05, 0xa2, 0x24, 0x10, 0xf8, 0xe4, 0xf2, 0x08, 0x74, 0x28, 0xf2, 0x22, +0x78, 0x66, 0xe6, 0x24, 0x0a, 0xf8, 0xc3, 0xe2, 0x95, 0x27, 0xff, 0x18, 0xe2, 0x95, 0x26, 0xfe, +0x12, 0x39, 0xa3, 0x22, 0x78, 0x66, 0xe6, 0x24, 0x08, 0xf8, 0xc3, 0xe2, 0x95, 0x25, 0xff, 0x18, +0xe2, 0x95, 0x24, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, +0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, +0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, +0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, +0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, +0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, +0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, +0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, +0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, +0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, +0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, +0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, +0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, +0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, +0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, +0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x0b, 0xe8, 0x73, 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, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, +0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, +0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, +0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, +0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, +0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, +0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, +0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, 0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, +0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, 0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, +0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, 0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, +0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, 0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, +0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, +0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, 0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xc2, +0xd5, 0xec, 0x30, 0xe7, 0x09, 0xb2, 0xd5, 0xe4, 0xc3, 0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0xee, 0x30, +0xe7, 0x15, 0xb2, 0xd5, 0xe4, 0xc3, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x12, 0x0d, 0x1a, 0xc3, 0xe4, +0x9d, 0xfd, 0xe4, 0x9c, 0xfc, 0x80, 0x03, 0x12, 0x0d, 0x1a, 0x30, 0xd5, 0x07, 0xc3, 0xe4, 0x9f, +0xff, 0xe4, 0x9e, 0xfe, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, +0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, +0x8a, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x06, 0x87, 0xf0, 0x09, 0xe7, 0x19, 0x22, +0xbb, 0xfe, 0x07, 0xe3, 0xf5, 0xf0, 0x09, 0xe3, 0x19, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, +0xf5, 0xf0, 0x74, 0x01, 0x93, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, +0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, +0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, +0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 0xbb, 0x01, +0x0d, 0xc5, 0x82, 0x29, 0xc5, 0x82, 0xc5, 0x83, 0x3a, 0xc5, 0x83, 0x02, 0x0d, 0xa5, 0x50, 0x11, +0xc5, 0x82, 0x29, 0xf8, 0x08, 0xe5, 0xf0, 0x26, 0xf6, 0x18, 0xf5, 0xf0, 0xe5, 0x82, 0x36, 0xf6, +0x22, 0xbb, 0xfe, 0x11, 0xc5, 0x82, 0x29, 0xf8, 0x08, 0xe2, 0x25, 0xf0, 0xf5, 0xf0, 0xf2, 0x18, +0xe2, 0x35, 0x82, 0xf2, 0x22, 0xf8, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x2a, 0xf5, 0x83, +0x74, 0x01, 0x93, 0x25, 0xf0, 0xf5, 0xf0, 0xe4, 0x93, 0x38, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, +0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, +0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, +0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, +0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, +0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 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, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, +0x08, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xf9, 0x08, 0xe6, 0xfa, 0x08, +0xe6, 0xcb, 0xf8, 0x22, 0xe4, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf9, 0x74, 0x02, 0x93, 0xfa, 0x74, +0x03, 0x93, 0xfb, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0x22, +0xd0, 0x83, 0xd0, 0x82, 0xe4, 0x93, 0xf6, 0x08, 0x74, 0x01, 0x93, 0xf6, 0x08, 0x74, 0x02, 0x93, +0xf6, 0x08, 0x74, 0x03, 0x93, 0xf6, 0x74, 0x04, 0x73, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, +0x35, 0x83, 0xf5, 0x83, 0x22, 0x8a, 0x83, 0x89, 0x82, 0xe4, 0x73, 0xec, 0x8e, 0xf0, 0xa4, 0xcc, +0xc5, 0xf0, 0xcc, 0xcd, 0xf8, 0xef, 0xa4, 0xce, 0xc5, 0xf0, 0x2d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe8, +0xa4, 0x2e, 0xc8, 0xc5, 0xf0, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0xef, 0xa4, 0xff, 0xe5, 0xf0, 0x28, +0xfe, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0xef, 0x4e, 0x60, 0x12, 0xef, 0x60, 0x01, 0x0e, +0xed, 0xbb, 0x01, 0x0b, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x22, 0x89, +0xf0, 0x50, 0x07, 0xf7, 0x09, 0xdf, 0xfc, 0xa9, 0xf0, 0x22, 0xbb, 0xfe, 0xfc, 0xf3, 0x09, 0xdf, +0xfc, 0xa9, 0xf0, 0x22, 0x90, 0x36, 0x03, 0x7d, 0x1f, 0x12, 0x31, 0xda, 0xee, 0x44, 0x80, 0xf5, +0x8f, 0x8f, 0x8e, 0x75, 0x8a, 0xa0, 0x75, 0x8a, 0x0a, 0xe4, 0x90, 0x00, 0xc3, 0xf0, 0x90, 0x00, +0xc9, 0xe0, 0x70, 0x03, 0x02, 0x11, 0xd7, 0x14, 0x70, 0x03, 0x02, 0x12, 0x02, 0x24, 0xfc, 0x70, +0x03, 0x02, 0x13, 0x49, 0x04, 0x60, 0x03, 0x02, 0x13, 0x82, 0xe4, 0xf5, 0x18, 0x78, 0x6e, 0xf6, +0x90, 0x36, 0x12, 0x93, 0x70, 0x0e, 0x75, 0x0a, 0x36, 0x75, 0x0b, 0x2a, 0x12, 0x39, 0xb9, 0x8f, +0x18, 0x02, 0x11, 0xc6, 0xe4, 0xf5, 0x1a, 0xf5, 0x1b, 0x75, 0x0a, 0x38, 0x75, 0x0b, 0x9e, 0x12, +0x14, 0x75, 0x12, 0x31, 0xc7, 0x12, 0x20, 0x0b, 0xe4, 0xf5, 0x19, 0x12, 0x31, 0xac, 0xe4, 0x93, +0xff, 0xe5, 0x19, 0xc3, 0x9f, 0x50, 0x33, 0xaf, 0x19, 0x12, 0x39, 0xc9, 0xac, 0x06, 0xad, 0x07, +0x12, 0x31, 0xac, 0x74, 0x2c, 0x93, 0x75, 0xf0, 0xc8, 0xa4, 0xff, 0xd3, 0xed, 0x9f, 0xec, 0x95, +0xf0, 0x40, 0x13, 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0xa9, 0x19, 0xa8, 0x01, 0x12, 0x0f, 0xf8, +0xef, 0x42, 0x1b, 0xee, 0x42, 0x1a, 0x05, 0x19, 0x80, 0xc1, 0xe5, 0x1a, 0x90, 0x01, 0xab, 0xf0, +0xa3, 0xe5, 0x1b, 0xf0, 0xe4, 0xf5, 0x19, 0xae, 0x1a, 0xaf, 0x1b, 0xe4, 0xfc, 0xfd, 0xe5, 0x19, +0x25, 0xe0, 0x25, 0xe0, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x36, 0xf5, 0x83, 0x12, 0x10, 0x24, +0xc3, 0x12, 0x0f, 0xd4, 0x60, 0x07, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x04, 0xda, 0xe5, 0x19, 0xc3, +0x94, 0x04, 0x50, 0x19, 0x85, 0x19, 0x18, 0x75, 0xf0, 0x9d, 0xe5, 0x19, 0xa4, 0x24, 0x2a, 0xf5, +0x82, 0xe5, 0xf0, 0x34, 0x36, 0xaf, 0x82, 0xf5, 0x0a, 0x8f, 0x0b, 0x80, 0x09, 0xe4, 0xf5, 0x18, +0x75, 0x0a, 0x36, 0x75, 0x0b, 0x2a, 0x90, 0x01, 0xaa, 0xe5, 0x18, 0xf0, 0x90, 0x01, 0xf0, 0x74, +0x40, 0xf0, 0xa3, 0xf0, 0x02, 0x13, 0x82, 0xe4, 0x78, 0x6e, 0xf6, 0x12, 0x2f, 0xde, 0xef, 0x64, +0x01, 0x60, 0xf8, 0x12, 0x14, 0x75, 0xaf, 0x0b, 0xae, 0x0a, 0x12, 0x00, 0x1f, 0xe5, 0x0b, 0x24, +0x79, 0xff, 0xe4, 0x35, 0x0a, 0xfe, 0x12, 0x39, 0x3b, 0x12, 0x31, 0xe4, 0xa3, 0x04, 0xf0, 0x02, +0x13, 0x87, 0xe4, 0xf5, 0x18, 0x78, 0x42, 0xf6, 0x90, 0x01, 0xff, 0xe0, 0xb4, 0x01, 0x09, 0x90, +0x00, 0xc9, 0x74, 0x05, 0xf0, 0x02, 0x13, 0x87, 0x78, 0x6e, 0x76, 0x01, 0x12, 0x31, 0xc7, 0x12, +0x20, 0x0b, 0x78, 0x42, 0xa6, 0x07, 0x12, 0x31, 0xac, 0x74, 0x63, 0x93, 0x70, 0x03, 0x74, 0x62, +0x93, 0x60, 0x1b, 0x08, 0xe6, 0xf5, 0x19, 0x08, 0xe6, 0xf5, 0x1a, 0x08, 0xe6, 0xfe, 0x08, 0xe6, +0xff, 0x78, 0x43, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x08, 0xa6, 0x19, 0x08, 0xa6, 0x1a, 0x7f, 0x5f, +0xe5, 0x0b, 0x24, 0x79, 0xfd, 0xe4, 0x35, 0x0a, 0xfc, 0x12, 0x2c, 0xe4, 0x8f, 0x18, 0x12, 0x31, +0xc7, 0x75, 0x20, 0x36, 0x75, 0x21, 0x23, 0xad, 0x18, 0x12, 0x1b, 0x15, 0x8f, 0x18, 0xe4, 0x78, +0x42, 0xf6, 0x78, 0x47, 0xe6, 0x70, 0x03, 0x02, 0x12, 0xfc, 0xe5, 0x18, 0x70, 0x12, 0x90, 0x01, +0xea, 0xe0, 0x30, 0xe2, 0x0b, 0x78, 0x89, 0xe2, 0x24, 0x01, 0xf2, 0x18, 0xe2, 0x34, 0x00, 0xf2, +0x78, 0x4d, 0xe6, 0x60, 0x07, 0x90, 0x01, 0xea, 0xe0, 0x20, 0xe0, 0x0c, 0xe5, 0x18, 0xb4, 0xaa, +0x0f, 0x90, 0x01, 0xea, 0xe0, 0x30, 0xe1, 0x08, 0x90, 0x00, 0xc8, 0xe0, 0x04, 0xf0, 0x80, 0x08, +0x90, 0x00, 0xc8, 0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x36, 0x08, 0xe4, 0x93, 0x75, 0xf0, 0x64, +0xa4, 0xff, 0xd3, 0x78, 0x89, 0xe2, 0x9f, 0x18, 0xe2, 0x95, 0xf0, 0x50, 0x1b, 0x12, 0x31, 0xac, +0x74, 0x9c, 0x93, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0x90, 0x00, 0xc8, 0xe0, 0xd3, 0x9f, 0xee, +0x64, 0x80, 0xf8, 0x74, 0x80, 0x98, 0x40, 0x14, 0x7f, 0x01, 0x12, 0x39, 0xc4, 0xe4, 0x78, 0x47, +0xf6, 0x78, 0x4d, 0xf6, 0x78, 0x48, 0x76, 0x04, 0x78, 0x4e, 0x76, 0x04, 0x12, 0x31, 0xc7, 0x78, +0x42, 0xe6, 0xf5, 0x20, 0xad, 0x18, 0x12, 0x18, 0xf2, 0x78, 0x47, 0xe6, 0x60, 0x19, 0x90, 0x36, +0x06, 0x7d, 0x64, 0x12, 0x31, 0xda, 0xc3, 0x78, 0x70, 0xe6, 0x9f, 0x18, 0xe6, 0x9e, 0x50, 0x67, +0xa6, 0x06, 0x08, 0xa6, 0x07, 0x80, 0x60, 0x90, 0x01, 0xfe, 0xe0, 0x70, 0x17, 0x78, 0x70, 0xe6, +0x18, 0x46, 0x60, 0x09, 0x08, 0xe6, 0x16, 0x18, 0x70, 0x0a, 0x16, 0x80, 0x07, 0x78, 0x6f, 0x76, +0x00, 0x08, 0x76, 0x14, 0x12, 0x31, 0xe4, 0x80, 0x3e, 0x12, 0x31, 0xac, 0xe4, 0x93, 0x90, 0x01, +0xcb, 0xf0, 0x90, 0x01, 0xff, 0xe0, 0xb4, 0x01, 0x2e, 0x75, 0x1f, 0x01, 0x75, 0x20, 0x01, 0x75, +0x21, 0x40, 0x75, 0x22, 0x01, 0x75, 0x23, 0x01, 0x75, 0x24, 0x80, 0x7b, 0x01, 0x7a, 0x01, 0x79, +0xc0, 0x12, 0x1c, 0xd8, 0xe4, 0x90, 0x01, 0xff, 0xf0, 0x75, 0x8a, 0xa0, 0x90, 0x00, 0xc0, 0xf0, +0x80, 0xd0, 0xe4, 0x90, 0x00, 0xc9, 0xf0, 0x90, 0x01, 0xe5, 0xe0, 0x64, 0x03, 0x60, 0x0b, 0x90, +0x01, 0xb5, 0xe0, 0x64, 0x03, 0x60, 0x03, 0x02, 0x14, 0x20, 0x90, 0x36, 0x0e, 0xe4, 0x93, 0xf5, +0x18, 0x7f, 0x01, 0x12, 0x35, 0x32, 0xe5, 0x18, 0x70, 0x05, 0x90, 0xff, 0x11, 0x80, 0x0d, 0xe5, +0x18, 0xb4, 0x01, 0x0c, 0x90, 0xff, 0x10, 0xe0, 0x44, 0x18, 0xf0, 0xa3, 0xe0, 0x44, 0x18, 0xf0, +0x90, 0x01, 0xb5, 0xe0, 0xb4, 0x03, 0x15, 0x90, 0xff, 0x12, 0xe0, 0x54, 0xe3, 0xf0, 0x90, 0xff, +0x11, 0xe0, 0x54, 0xe3, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe3, 0xf0, 0x75, 0x8f, 0x87, 0x75, +0x8e, 0xff, 0x75, 0x8d, 0x87, 0x75, 0x8c, 0xff, 0x12, 0x31, 0xbe, 0x75, 0x8a, 0xa0, 0xf0, 0xe5, +0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc3, 0xe4, +0xf5, 0x91, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, +0x31, 0xbe, 0x75, 0x8a, 0xa0, 0xf0, 0x75, 0x8a, 0xa0, 0xf0, 0x75, 0x8a, 0xa0, 0xf0, 0x80, 0xc8, +0x75, 0x18, 0x27, 0x75, 0x19, 0x10, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, +0xe0, 0x04, 0xf0, 0x90, 0x00, 0xc3, 0xe0, 0xff, 0xc3, 0x78, 0x6e, 0x96, 0x50, 0x36, 0xe5, 0x19, +0x15, 0x19, 0xac, 0x18, 0x70, 0x02, 0x15, 0x18, 0x4c, 0x60, 0x29, 0xe5, 0x89, 0x30, 0xe7, 0x0c, +0x75, 0x89, 0x80, 0xef, 0xc3, 0x94, 0xff, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc1, 0xe4, +0xf5, 0x91, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x31, 0xb3, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, +0x31, 0xbe, 0x80, 0xbf, 0x22, 0xaf, 0x0b, 0xae, 0x0a, 0x12, 0x22, 0xe9, 0xaf, 0x0b, 0xae, 0x0a, +0x12, 0x35, 0x7b, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff, 0x22, 0x43, +0xad, 0x04, 0x90, 0xff, 0x50, 0x74, 0x0f, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x85, 0x0d, 0x82, 0x85, +0x0c, 0x83, 0x74, 0x26, 0x93, 0x90, 0xff, 0x48, 0xf0, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x74, +0x27, 0x93, 0x90, 0xff, 0x42, 0xf0, 0x90, 0xff, 0x40, 0x74, 0x6c, 0xf0, 0x90, 0xff, 0x57, 0x74, +0xff, 0xf0, 0x90, 0xff, 0x56, 0xe4, 0xf0, 0x90, 0xff, 0x5f, 0x74, 0xff, 0xf0, 0x90, 0xff, 0x5e, +0xe4, 0xf0, 0x85, 0x0d, 0x82, 0x85, 0x0c, 0x83, 0x22, 0x78, 0x5c, 0xe6, 0xff, 0x78, 0x84, 0xe2, +0xfc, 0x08, 0xe2, 0x2f, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0x22, 0xe5, 0x22, 0x75, 0xf0, +0x0a, 0xa4, 0x24, 0x03, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0x90, 0xff, 0x54, 0xe0, +0x90, 0x01, 0xf0, 0xf0, 0x90, 0xff, 0x5c, 0xe0, 0x90, 0x01, 0xf1, 0xf0, 0x75, 0x8a, 0xa0, 0xe4, +0x90, 0x00, 0xc0, 0xf0, 0x8c, 0x8f, 0x8d, 0x8e, 0x75, 0x8a, 0xa0, 0xf0, 0x90, 0xff, 0x43, 0x74, +0x5f, 0xf0, 0xe5, 0x89, 0x22, 0xe5, 0x27, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, +0x34, 0x02, 0xf5, 0x83, 0x22, 0x78, 0x5c, 0xe6, 0xff, 0x24, 0xb7, 0xf5, 0x82, 0xe4, 0x34, 0x02, +0xf5, 0x83, 0xe0, 0x90, 0xff, 0x54, 0xf0, 0x18, 0xe6, 0x24, 0xb7, 0xf5, 0x82, 0xe4, 0x34, 0x02, +0xf5, 0x83, 0xe0, 0x90, 0xff, 0x5c, 0xf0, 0xef, 0xc3, 0x13, 0xff, 0xe5, 0x0d, 0x24, 0x1a, 0xf5, +0x82, 0xe4, 0x35, 0x0c, 0xf5, 0x83, 0xe5, 0x82, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, +0xe4, 0x93, 0x90, 0xff, 0x55, 0xf0, 0x22, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xef, 0x75, 0xf0, 0x0a, +0xa4, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xff, 0xa8, 0x3f, 0x08, 0x08, +0xe6, 0xfa, 0x08, 0xe6, 0xf5, 0x82, 0x8a, 0x83, 0x22, 0x74, 0x28, 0x93, 0x90, 0xff, 0x55, 0xf0, +0x90, 0x01, 0xf0, 0xe0, 0x90, 0xff, 0x54, 0xf0, 0x90, 0x01, 0xf1, 0xe0, 0x90, 0xff, 0x5c, 0xf0, +0x90, 0xff, 0x48, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x94, 0x07, 0xee, 0x94, 0x00, 0x22, 0x75, 0x91, +0xc3, 0xe4, 0xf5, 0x91, 0xe5, 0x89, 0x22, 0xfd, 0x7c, 0x00, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0xc3, +0x9d, 0xff, 0xea, 0x9c, 0xfe, 0xef, 0x78, 0x03, 0x22, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, +0xad, 0x8e, 0xac, 0x8f, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0x22, 0x90, 0xff, 0x52, 0xe0, +0xfe, 0xa3, 0xe0, 0xa6, 0x06, 0x08, 0xf6, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0x22, 0xe5, +0x27, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xd3, +0xe5, 0x2a, 0x94, 0x00, 0xe5, 0x29, 0x64, 0x80, 0x94, 0x80, 0x22, 0x90, 0xff, 0x52, 0xe0, 0xfa, +0xa3, 0xe0, 0xc3, 0x9f, 0xea, 0x9e, 0x22, 0x90, 0xff, 0x5f, 0xf0, 0xed, 0x2b, 0xff, 0xec, 0x3a, +0xfe, 0xef, 0x78, 0x03, 0x22, 0x7f, 0xb4, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0x03, 0x02, 0x10, 0x98, +0x90, 0xff, 0x5e, 0xf0, 0x90, 0xff, 0x56, 0xe0, 0xff, 0xa3, 0xe0, 0xd3, 0x9f, 0x22, 0x75, 0x91, +0xc1, 0xe4, 0xf5, 0x91, 0xe5, 0x89, 0x22, 0x78, 0x84, 0xe2, 0xfc, 0x08, 0xe2, 0x22, 0x74, 0xb7, +0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x26, 0x22, 0xe5, 0x27, +0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0xd3, 0x74, +0x05, 0x93, 0x9f, 0x74, 0x04, 0x93, 0x9e, 0x22, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x0b, 0xf5, 0x82, +0xe4, 0x34, 0x02, 0xf5, 0x83, 0x22, 0x90, 0xff, 0x43, 0x74, 0x9f, 0xf0, 0x22, 0x78, 0x83, 0xe2, +0x90, 0xff, 0x40, 0xf0, 0x22, 0xe5, 0x0d, 0x24, 0x2b, 0xff, 0xe4, 0x35, 0x0c, 0xa9, 0x07, 0x22, +0xef, 0x24, 0x01, 0xff, 0xee, 0x33, 0xfe, 0xef, 0x78, 0x07, 0x22, 0xe5, 0x22, 0xc3, 0x78, 0x65, +0x96, 0x22, 0xe0, 0xfc, 0xa3, 0xe0, 0xc3, 0x9f, 0x22, 0x8f, 0x23, 0x12, 0x05, 0x40, 0xe2, 0xfb, +0x12, 0x00, 0x60, 0x12, 0x04, 0x02, 0x12, 0x0d, 0x1a, 0x8e, 0x2f, 0x8f, 0x30, 0xeb, 0x70, 0x5f, +0x75, 0x24, 0x01, 0x12, 0x05, 0x6f, 0xe4, 0xf5, 0x29, 0xf5, 0x2a, 0x78, 0x61, 0xe2, 0xfe, 0x08, +0xe2, 0xff, 0x78, 0x60, 0x12, 0x02, 0xc1, 0x78, 0x65, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x78, 0x64, +0x12, 0x04, 0x76, 0xc3, 0x74, 0x09, 0x93, 0x94, 0x00, 0x50, 0x05, 0x12, 0x05, 0x7b, 0x80, 0x04, +0xae, 0x27, 0xaf, 0x28, 0x8e, 0x2d, 0x8f, 0x2e, 0x12, 0x00, 0x60, 0x74, 0x09, 0x93, 0xfc, 0x74, +0x0a, 0x12, 0x02, 0x7d, 0x40, 0x06, 0xae, 0x2d, 0xaf, 0x2e, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x01, +0x8e, 0x27, 0x8f, 0x28, 0x78, 0x69, 0xe2, 0xfe, 0x08, 0xe2, 0xff, 0x78, 0x68, 0x80, 0x76, 0x78, +0x67, 0xe6, 0x14, 0x6b, 0x70, 0x7a, 0xf5, 0x24, 0x12, 0x05, 0x6f, 0x12, 0x00, 0x60, 0x74, 0x03, +0x93, 0xf5, 0x29, 0x74, 0x04, 0x93, 0xf5, 0x2a, 0x12, 0x00, 0xec, 0x12, 0x02, 0xb9, 0xeb, 0x25, +0xe0, 0x25, 0xe0, 0x24, 0x5d, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x5c, 0x12, +0x04, 0x75, 0xc3, 0x74, 0x0b, 0x93, 0x94, 0x00, 0x50, 0x05, 0x12, 0x05, 0x7b, 0x80, 0x04, 0xae, +0x27, 0xaf, 0x28, 0x8e, 0x2d, 0x8f, 0x2e, 0x12, 0x00, 0x60, 0x74, 0x0b, 0x93, 0xfc, 0x74, 0x0c, +0x12, 0x02, 0x7d, 0x40, 0x06, 0xae, 0x2d, 0xaf, 0x2e, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x01, 0x8e, +0x27, 0x8f, 0x28, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x59, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, +0x25, 0xe0, 0x24, 0x58, 0xf8, 0xe2, 0x2f, 0xf5, 0x2c, 0x18, 0xe2, 0x3e, 0xf5, 0x2b, 0x80, 0x7d, +0xeb, 0xfd, 0x7c, 0x00, 0xae, 0x2f, 0xaf, 0x30, 0x12, 0x0d, 0x08, 0xac, 0x06, 0xad, 0x07, 0xe5, +0x2f, 0xc3, 0x13, 0xfe, 0xe5, 0x30, 0x13, 0x2d, 0xf5, 0x2a, 0xec, 0x3e, 0xf5, 0x29, 0xeb, 0x25, +0xe0, 0x25, 0xe0, 0x24, 0x5d, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x5c, 0x12, +0x02, 0xc0, 0xeb, 0x25, 0xe0, 0x25, 0xe0, 0x24, 0x65, 0x12, 0x00, 0xf3, 0xeb, 0x25, 0xe0, 0x25, +0xe0, 0x24, 0x64, 0x12, 0x04, 0x75, 0xd3, 0xe5, 0x26, 0x95, 0x28, 0xe5, 0x27, 0x64, 0x80, 0xf8, +0xe5, 0x25, 0x64, 0x80, 0x98, 0x40, 0x11, 0xe4, 0xf5, 0x24, 0x85, 0x27, 0x2b, 0x85, 0x28, 0x2c, +0x85, 0x25, 0x27, 0x85, 0x26, 0x28, 0x80, 0x0f, 0x75, 0x24, 0x01, 0x85, 0x25, 0x2b, 0x85, 0x26, +0x2c, 0x85, 0x27, 0x27, 0x85, 0x28, 0x28, 0x12, 0x00, 0xec, 0x12, 0x02, 0xb9, 0xc3, 0xe5, 0x26, +0x95, 0x2c, 0xf5, 0x26, 0xe5, 0x25, 0x95, 0x2b, 0xf5, 0x25, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x50, +0x05, 0xe4, 0xf5, 0x25, 0xf5, 0x26, 0xc3, 0xe5, 0x28, 0x95, 0x2c, 0xf5, 0x28, 0xe5, 0x27, 0x95, +0x2b, 0xf5, 0x27, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x50, 0x05, 0xe4, 0xf5, 0x27, 0xf5, 0x28, 0x85, +0x27, 0x2b, 0x85, 0x28, 0x2c, 0xae, 0x2b, 0xaf, 0x2c, 0x12, 0x03, 0xd3, 0xe4, 0x7b, 0x80, 0xfa, +0xf9, 0xf8, 0x12, 0x01, 0x2b, 0xae, 0x2f, 0xaf, 0x30, 0x12, 0x04, 0x86, 0xc0, 0x06, 0xc0, 0x07, +0xe5, 0x26, 0x25, 0x28, 0xcf, 0xe5, 0x25, 0x35, 0x27, 0xcf, 0x24, 0x01, 0xcf, 0x34, 0x00, 0xab, +0x07, 0xfa, 0x33, 0x95, 0xe0, 0xf9, 0xf8, 0xd0, 0x07, 0xd0, 0x06, 0x12, 0x0f, 0x42, 0xef, 0x12, +0x05, 0xe7, 0xe4, 0x3d, 0xfd, 0xe4, 0x3c, 0xfc, 0xe4, 0x7b, 0x80, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, +0x42, 0x8e, 0x2b, 0x8f, 0x2c, 0xe5, 0x24, 0x60, 0x0e, 0xe5, 0x2a, 0x25, 0x2c, 0xf5, 0x2c, 0xe5, +0x29, 0x35, 0x2b, 0xf5, 0x2b, 0x80, 0x0d, 0xc3, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2c, 0xe5, 0x29, +0x95, 0x2b, 0xf5, 0x2b, 0xe5, 0x23, 0x12, 0x05, 0x17, 0xf8, 0xe5, 0x2b, 0xf2, 0x08, 0xe5, 0x2c, +0xf2, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x8d, 0x1f, 0x90, 0x01, 0xfa, 0xe0, 0xf5, 0x21, +0xe4, 0xf5, 0x22, 0x85, 0x20, 0x20, 0xe5, 0x1f, 0x60, 0x04, 0x90, 0x00, 0xcb, 0xf0, 0x7d, 0x01, +0x7f, 0x12, 0x12, 0x32, 0xcc, 0x75, 0x23, 0x01, 0x75, 0x24, 0x00, 0x78, 0x73, 0xe6, 0xff, 0x70, +0x0b, 0x74, 0x20, 0x25, 0x24, 0xf5, 0x24, 0xe4, 0x35, 0x23, 0xf5, 0x23, 0x74, 0x00, 0x2f, 0xf9, +0xe4, 0x34, 0x01, 0xfa, 0x7b, 0x01, 0xa8, 0x24, 0xac, 0x23, 0x7d, 0x01, 0x7e, 0x00, 0x7f, 0x20, +0x12, 0x0c, 0x68, 0x7e, 0x00, 0x7f, 0x0b, 0x7d, 0xff, 0xe5, 0x24, 0x24, 0x09, 0xfb, 0xe4, 0x35, +0x23, 0xfa, 0xa9, 0x03, 0x7b, 0x01, 0x12, 0x10, 0x98, 0x05, 0x24, 0xe5, 0x24, 0xae, 0x23, 0x70, +0x02, 0x05, 0x23, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x12, 0x2b, 0x91, 0x90, 0x00, 0x0a, +0x12, 0x2b, 0x2a, 0xff, 0x90, 0x00, 0x04, 0x12, 0x0c, 0xa7, 0x2f, 0xf5, 0x22, 0x90, 0x00, 0x05, +0x12, 0x0c, 0xa7, 0xb4, 0x04, 0x09, 0x12, 0x2b, 0x58, 0x70, 0x04, 0x90, 0x00, 0xca, 0xf0, 0x90, +0x00, 0xca, 0xe0, 0x60, 0x4b, 0x14, 0xf0, 0xe0, 0xff, 0x7e, 0x04, 0x60, 0x02, 0x7e, 0x08, 0x12, +0x2b, 0x72, 0x90, 0x00, 0x05, 0xee, 0x12, 0x0c, 0xe6, 0xef, 0x60, 0x08, 0x12, 0x2b, 0x9b, 0xff, +0xae, 0xf0, 0x80, 0x10, 0x90, 0x00, 0xcb, 0xe0, 0xff, 0xb4, 0x05, 0x02, 0x80, 0x02, 0x7f, 0x00, +0xef, 0x7f, 0x00, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x27, 0xc4, 0x54, 0xf0, 0xfe, 0x12, 0x2b, +0x9b, 0xfd, 0xe5, 0xf0, 0x54, 0x0f, 0xfc, 0xe4, 0x2d, 0xff, 0xee, 0x3c, 0x8f, 0xf0, 0x80, 0x60, +0x12, 0x2b, 0x27, 0x70, 0x09, 0x12, 0x2b, 0x58, 0x70, 0x04, 0xe5, 0x1f, 0x60, 0x57, 0x12, 0x2b, +0x79, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x27, 0x60, 0x17, 0xc4, 0x54, 0xf0, 0xfe, 0x12, 0x0d, 0xbb, +0x24, 0x00, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12, 0x2a, 0xec, 0x12, 0x2b, 0x5e, 0x12, 0x0e, 0x6b, +0x12, 0x2b, 0x52, 0x60, 0x35, 0xc4, 0x54, 0xf0, 0xfe, 0x90, 0x00, 0x06, 0x12, 0x0d, 0xe6, 0x24, +0x00, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x72, 0x90, 0x00, 0x08, 0x12, +0x0d, 0xe6, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x10, 0xfe, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x5e, +0x12, 0x0e, 0x6b, 0x80, 0x05, 0xe4, 0x90, 0x00, 0xcb, 0xf0, 0x90, 0x01, 0xfe, 0xe0, 0xd3, 0x94, +0xf0, 0x40, 0x70, 0x12, 0x2b, 0x91, 0x12, 0x2b, 0x79, 0x12, 0x2b, 0x11, 0x12, 0x2b, 0x72, 0x12, +0x0d, 0xbb, 0xff, 0xae, 0xf0, 0x12, 0x2a, 0xec, 0x90, 0x00, 0x06, 0x12, 0x2b, 0x05, 0x12, 0x2b, +0x72, 0x90, 0x00, 0x08, 0x12, 0x2b, 0x0b, 0x90, 0x01, 0x40, 0x74, 0x40, 0xf0, 0x90, 0x01, 0x60, +0x74, 0x60, 0xf0, 0x75, 0x2b, 0x01, 0x75, 0x2c, 0x41, 0x12, 0x2b, 0xa4, 0xaf, 0x28, 0x12, 0x39, +0xc9, 0xe5, 0x2c, 0xfd, 0x24, 0x02, 0xf5, 0x2c, 0xe5, 0x2b, 0xfc, 0x34, 0x00, 0xf5, 0x2b, 0x8d, +0x82, 0x8c, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xaf, 0x28, 0x12, 0x00, 0x12, 0xef, 0xd3, 0x94, +0x1c, 0x40, 0x06, 0x7e, 0x0f, 0x7f, 0xff, 0x80, 0x05, 0xaf, 0x28, 0x12, 0x39, 0x97, 0x12, 0x2b, +0x33, 0x40, 0xc9, 0x12, 0x2b, 0xa4, 0xaf, 0x28, 0x12, 0x39, 0x97, 0x12, 0x2b, 0x33, 0x40, 0xf6, +0x78, 0x73, 0xe6, 0x7f, 0x00, 0x70, 0x02, 0x7f, 0x20, 0x78, 0x73, 0xa6, 0x07, 0xe5, 0x21, 0x20, +0xe7, 0x2a, 0x30, 0xe6, 0x0a, 0x12, 0x2b, 0x27, 0x70, 0x22, 0x12, 0x2b, 0x58, 0x70, 0x1d, 0xe5, +0x21, 0x30, 0xe5, 0x0f, 0x12, 0x2b, 0x52, 0xff, 0x90, 0x00, 0x05, 0x12, 0x0c, 0xa7, 0x4f, 0x54, +0x84, 0x70, 0x09, 0xe5, 0x21, 0x30, 0xe4, 0x0c, 0xe5, 0x1f, 0x60, 0x08, 0x90, 0x01, 0xed, 0xe0, +0xff, 0x12, 0x31, 0x5d, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x8d, 0x1f, 0xe4, 0xf5, 0x22, +0x90, 0x00, 0x05, 0x12, 0x0c, 0xa7, 0xf5, 0x23, 0x90, 0x00, 0x0b, 0x12, 0x0c, 0xa7, 0x60, 0x08, +0xe4, 0x78, 0x8a, 0xf2, 0x90, 0x00, 0xbf, 0xf0, 0xe5, 0x23, 0xb4, 0x80, 0x29, 0x78, 0x8a, 0x74, +0xff, 0xf2, 0x12, 0x34, 0xe0, 0x90, 0x00, 0xb9, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x34, +0xf1, 0x90, 0x00, 0xbb, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, +0xe0, 0x04, 0xf0, 0x02, 0x1c, 0xa9, 0xe5, 0x23, 0x64, 0x08, 0x60, 0x03, 0x02, 0x1c, 0x56, 0x12, +0x34, 0xe0, 0xc3, 0x90, 0x00, 0xba, 0xe0, 0x90, 0x00, 0xb9, 0x12, 0x1c, 0xce, 0x8e, 0x24, 0x8f, +0x25, 0x12, 0x34, 0xeb, 0xc3, 0x90, 0x00, 0xbc, 0xe0, 0x90, 0x00, 0xbb, 0x12, 0x1c, 0xce, 0x12, +0x34, 0xd9, 0x74, 0x01, 0x93, 0xfc, 0x74, 0x02, 0x12, 0x34, 0xf9, 0x40, 0x12, 0x90, 0x01, 0xec, +0xe0, 0x30, 0xe0, 0x0b, 0x78, 0x8a, 0xe2, 0x54, 0xfe, 0xf2, 0xe4, 0x90, 0x00, 0xbf, 0xf0, 0xe5, +0x25, 0x2f, 0xfd, 0xe5, 0x24, 0x3e, 0xfc, 0x12, 0x34, 0xd9, 0x74, 0x05, 0x93, 0xfb, 0xd3, 0xed, +0x9b, 0xec, 0x94, 0x00, 0x40, 0x0b, 0x78, 0x8a, 0xe2, 0x54, 0xfc, 0xf2, 0xe4, 0x90, 0x00, 0xbf, +0xf0, 0x12, 0x34, 0xd9, 0x74, 0x03, 0x93, 0xfc, 0x74, 0x04, 0x12, 0x34, 0xf9, 0x40, 0x13, 0x78, +0x8a, 0xe2, 0x20, 0xe1, 0x04, 0xe5, 0x1f, 0x60, 0x09, 0x75, 0x22, 0x0c, 0xe4, 0x78, 0x8a, 0xf2, +0xf5, 0x1f, 0x78, 0x8a, 0xe2, 0x54, 0x3c, 0x70, 0x03, 0x02, 0x1c, 0xa9, 0x12, 0x34, 0xd9, 0x74, +0x06, 0x93, 0xfd, 0x7c, 0x00, 0xd3, 0xe5, 0x25, 0x9d, 0xe5, 0x24, 0x9c, 0x50, 0x09, 0xef, 0x9d, +0xee, 0x9c, 0x50, 0x03, 0x02, 0x1c, 0xa9, 0xd3, 0xef, 0x95, 0x25, 0xee, 0x95, 0x24, 0x40, 0x17, +0x12, 0x34, 0xeb, 0xd3, 0x90, 0x00, 0xbc, 0xe0, 0x9f, 0x90, 0x00, 0xbb, 0xe0, 0x95, 0xf0, 0x7f, +0x02, 0x40, 0x02, 0x7f, 0x01, 0x80, 0x15, 0x12, 0x34, 0xe0, 0xd3, 0x90, 0x00, 0xba, 0xe0, 0x9f, +0x90, 0x00, 0xb9, 0xe0, 0x95, 0xf0, 0x7f, 0x04, 0x40, 0x02, 0x7f, 0x03, 0x8f, 0x22, 0x78, 0x8a, +0xe2, 0x54, 0xc3, 0xf2, 0x80, 0x53, 0xe5, 0x23, 0xb4, 0x04, 0x09, 0xe4, 0x90, 0x00, 0xbd, 0xf0, +0xa3, 0xf0, 0x80, 0x45, 0x12, 0x34, 0xd9, 0x74, 0x01, 0x93, 0xfe, 0x74, 0x02, 0x93, 0xff, 0xd3, +0x90, 0x00, 0xbe, 0xe0, 0x9f, 0x90, 0x00, 0xbd, 0xe0, 0x9e, 0x50, 0x07, 0x90, 0x01, 0xec, 0xe0, +0x20, 0xe0, 0x26, 0x78, 0x8a, 0xe2, 0xff, 0x30, 0xe0, 0x1a, 0x90, 0x00, 0xbf, 0xe0, 0xfe, 0xd3, +0x94, 0x02, 0x50, 0x0a, 0xee, 0x7e, 0x0b, 0xb4, 0x01, 0x02, 0x7e, 0x05, 0x8e, 0x22, 0xef, 0x54, +0xfe, 0x78, 0x8a, 0xf2, 0xe4, 0x90, 0x00, 0xbf, 0xf0, 0xc3, 0x90, 0x00, 0xbd, 0xe0, 0x94, 0xff, +0x50, 0x13, 0x12, 0x34, 0xd9, 0xe4, 0x93, 0xff, 0x90, 0x00, 0xbe, 0xe0, 0x2f, 0xf0, 0x90, 0x00, +0xbd, 0xe0, 0x34, 0x00, 0xf0, 0xe5, 0x1f, 0xaf, 0x1f, 0x70, 0x02, 0xaf, 0x22, 0x22, 0x9f, 0xff, +0xe0, 0x95, 0xf0, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, 0x1e, 0x43, 0xad, +0x04, 0x90, 0xff, 0x40, 0xe0, 0x20, 0xe0, 0xf9, 0x43, 0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x37, +0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0xe4, 0xf5, 0x25, 0xf5, 0x25, 0x12, 0x33, 0x70, 0xe5, +0x25, 0xc3, 0x9f, 0x50, 0x22, 0xe9, 0x24, 0x0c, 0xf9, 0xe4, 0x3a, 0x12, 0x33, 0x61, 0xe4, 0xfd, +0x12, 0x34, 0xaa, 0x12, 0x33, 0x57, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x12, 0x33, 0x57, 0xe4, 0xfd, +0x12, 0x32, 0xcc, 0x05, 0x25, 0x80, 0xd5, 0x90, 0xff, 0x4a, 0xe4, 0xf0, 0x90, 0xff, 0x50, 0x74, +0x0f, 0xf0, 0x90, 0xff, 0x58, 0xe4, 0xf0, 0x90, 0xff, 0x40, 0x74, 0x08, 0xf0, 0x90, 0xff, 0x43, +0x74, 0x9f, 0xf0, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0c, 0x8e, 0x90, 0xff, 0x48, 0xf0, +0x90, 0x00, 0x01, 0x12, 0x0c, 0xa7, 0x90, 0xff, 0x42, 0xf0, 0x90, 0x00, 0x02, 0x12, 0x0c, 0xa7, +0x90, 0xff, 0x55, 0xf0, 0x90, 0x00, 0x03, 0x12, 0x0c, 0xa7, 0x90, 0xff, 0x54, 0xf0, 0x90, 0xff, +0x5c, 0xe4, 0xf0, 0xf5, 0x25, 0x12, 0x33, 0x70, 0xe5, 0x25, 0xc3, 0x9f, 0x50, 0x5b, 0xe4, 0xf5, +0x26, 0x75, 0x27, 0x64, 0x90, 0xff, 0x50, 0xe0, 0x20, 0xe7, 0x03, 0x43, 0x26, 0x01, 0xe5, 0x26, +0x64, 0x01, 0x60, 0x03, 0xd5, 0x27, 0xed, 0x12, 0x33, 0x7e, 0x12, 0x33, 0x57, 0x7d, 0x06, 0x12, +0x30, 0xb1, 0x90, 0xff, 0x40, 0x74, 0x29, 0xf0, 0x90, 0xff, 0x40, 0xe0, 0x20, 0xe0, 0xf9, 0x12, +0x33, 0x57, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xab, +0x1f, 0xe5, 0x21, 0xf9, 0x24, 0x02, 0xf5, 0x21, 0xe5, 0x20, 0xfa, 0x34, 0x00, 0xf5, 0x20, 0xee, +0x8f, 0xf0, 0x12, 0x0e, 0x6b, 0x05, 0x25, 0x80, 0x9c, 0xe4, 0xf5, 0x25, 0x90, 0xff, 0x54, 0xf0, +0x75, 0x28, 0x01, 0x12, 0x33, 0x87, 0x74, 0xff, 0x12, 0x33, 0x54, 0x7d, 0x07, 0x12, 0x30, 0xb1, +0x90, 0xff, 0x55, 0x74, 0x64, 0xf0, 0xe4, 0xf5, 0x26, 0xf5, 0x27, 0x90, 0xff, 0x50, 0xe0, 0x30, +0xe7, 0x10, 0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0xb4, 0xe8, 0xee, 0xe5, 0x26, 0xb4, +0x03, 0xe9, 0xe5, 0x28, 0x24, 0x02, 0x90, 0xff, 0x55, 0xf0, 0xe4, 0xf5, 0x26, 0xf5, 0x27, 0x00, +0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0xb4, 0xe8, 0xf4, 0xe5, 0x26, 0xb4, 0x03, 0xef, +0xe4, 0xf5, 0x29, 0xf5, 0x26, 0xf5, 0x27, 0x90, 0xff, 0x50, 0xe0, 0x30, 0xe7, 0x03, 0x00, 0x80, +0x02, 0x05, 0x29, 0x05, 0x27, 0xe5, 0x27, 0x70, 0x02, 0x05, 0x26, 0x64, 0x64, 0x45, 0x26, 0x70, +0xe6, 0xe5, 0x29, 0xd3, 0x94, 0x28, 0x50, 0x0c, 0x12, 0x33, 0x7e, 0x05, 0x28, 0xe5, 0x28, 0xc3, +0x94, 0x64, 0x40, 0xae, 0x12, 0x33, 0x87, 0xe5, 0x28, 0x12, 0x33, 0x54, 0x7d, 0x08, 0x12, 0x30, +0xb1, 0x12, 0x33, 0x7e, 0x12, 0x33, 0x70, 0x05, 0x25, 0xe5, 0x25, 0xc3, 0x9f, 0x50, 0x03, 0x02, +0x1d, 0xe0, 0x90, 0xff, 0x50, 0xe4, 0xf0, 0xff, 0x22, 0xe4, 0x78, 0x62, 0xf6, 0x18, 0xe6, 0x14, +0x70, 0x03, 0x02, 0x1f, 0x69, 0x14, 0x70, 0x03, 0x02, 0x1f, 0xda, 0x24, 0x02, 0x60, 0x03, 0x02, +0x1f, 0xfc, 0x12, 0x14, 0xd2, 0xe4, 0x93, 0x78, 0x65, 0xf6, 0x78, 0x60, 0xe6, 0x30, 0xe0, 0x08, +0x75, 0x23, 0x05, 0x75, 0x24, 0x01, 0x80, 0x06, 0x75, 0x23, 0x08, 0xe4, 0xf5, 0x24, 0xe4, 0xf5, +0x22, 0x12, 0x16, 0xbb, 0x50, 0x3f, 0x12, 0x16, 0x57, 0x25, 0x22, 0x12, 0x14, 0xe4, 0xf5, 0x25, +0xe5, 0x22, 0x54, 0x01, 0xfd, 0xaf, 0x25, 0x12, 0x34, 0xaa, 0xad, 0x24, 0xaf, 0x25, 0x12, 0x32, +0xcc, 0xad, 0x23, 0xaf, 0x25, 0x12, 0x30, 0xb1, 0x78, 0x60, 0xe6, 0xb4, 0x03, 0x13, 0xe5, 0x22, +0x30, 0xe0, 0x0e, 0xe4, 0xfd, 0xaf, 0x25, 0x12, 0x32, 0xcc, 0x7d, 0x08, 0xaf, 0x25, 0x12, 0x30, +0xb1, 0x05, 0x22, 0x80, 0xbc, 0x78, 0x5d, 0xe6, 0xf5, 0x25, 0x75, 0x26, 0x10, 0x76, 0x40, 0x7e, +0x00, 0x7f, 0x12, 0x7d, 0x10, 0x7b, 0x01, 0x7a, 0x02, 0x79, 0xb7, 0x12, 0x10, 0x98, 0xe5, 0x26, +0xd3, 0x94, 0x01, 0x40, 0x3c, 0x12, 0x20, 0x01, 0x12, 0x16, 0xbb, 0x50, 0x2c, 0x12, 0x14, 0xd2, +0x74, 0x02, 0x93, 0x75, 0xf0, 0xa3, 0xa4, 0xff, 0xae, 0xf0, 0x12, 0x14, 0xec, 0x12, 0x16, 0xc2, +0xec, 0x9e, 0x50, 0x08, 0x12, 0x16, 0x5e, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x12, 0x16, 0x5e, 0xc3, +0x13, 0xfe, 0xef, 0x4e, 0xf0, 0x05, 0x22, 0x80, 0xcf, 0xe5, 0x26, 0xc3, 0x13, 0xf5, 0x26, 0x80, +0xbd, 0x78, 0x5d, 0xa6, 0x25, 0x78, 0x61, 0x76, 0x01, 0x12, 0x14, 0xd2, 0x74, 0x05, 0x93, 0x25, +0xe0, 0xf5, 0x25, 0x74, 0x04, 0x93, 0x33, 0xf5, 0x24, 0xe4, 0x78, 0x64, 0xf6, 0xfe, 0xfd, 0x12, +0x16, 0x35, 0x7e, 0x00, 0x7f, 0x24, 0x7d, 0x00, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x5f, 0x12, 0x10, +0x98, 0x75, 0x23, 0x04, 0x12, 0x31, 0x0b, 0x12, 0x20, 0x01, 0x12, 0x16, 0xbb, 0x50, 0x34, 0x12, +0x14, 0xec, 0xe0, 0xfe, 0xa3, 0xe0, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, +0xe5, 0x22, 0x12, 0x15, 0x27, 0xee, 0x8f, 0xf0, 0x12, 0x0d, 0xa5, 0xe5, 0x22, 0x12, 0x15, 0x27, +0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x22, 0x12, 0x16, 0x88, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x05, +0x22, 0x80, 0xc7, 0xd5, 0x23, 0xc1, 0x78, 0x61, 0x76, 0x02, 0x12, 0x31, 0x0b, 0x12, 0x26, 0xc2, +0x78, 0x65, 0xe6, 0xfd, 0xe4, 0xff, 0x12, 0x2f, 0x6e, 0x78, 0x62, 0xe6, 0x30, 0xe1, 0x04, 0x78, +0x64, 0x76, 0x28, 0x78, 0x65, 0xe6, 0xfd, 0xe4, 0xff, 0x02, 0x21, 0x82, 0xe4, 0x78, 0x61, 0xf6, +0x22, 0x12, 0x26, 0xc2, 0x12, 0x31, 0x0b, 0xe4, 0xf5, 0x22, 0x22, 0x8b, 0x1c, 0x8a, 0x1d, 0x89, +0x1e, 0xe4, 0xf5, 0x1f, 0xfe, 0x7f, 0x0c, 0xfd, 0x12, 0x10, 0x98, 0x7a, 0x00, 0x79, 0x02, 0x12, +0x04, 0x58, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x04, 0x58, 0x78, 0x6d, 0xe6, 0x14, 0x60, 0x30, 0x04, +0x60, 0x03, 0x02, 0x21, 0x7b, 0xe4, 0x78, 0x6c, 0xf6, 0xff, 0x12, 0x39, 0xc4, 0x12, 0x1e, 0x89, +0x78, 0x62, 0xe6, 0x30, 0xe4, 0x03, 0x02, 0x21, 0x7f, 0x7e, 0x00, 0x7f, 0x5e, 0x7d, 0x00, 0x7b, +0xfe, 0x7a, 0x00, 0x79, 0x01, 0x12, 0x10, 0x98, 0x78, 0x6d, 0x76, 0x01, 0x02, 0x21, 0x73, 0x12, +0x1e, 0x89, 0x78, 0x62, 0xe6, 0xff, 0x30, 0xe4, 0x03, 0x02, 0x21, 0x7b, 0xef, 0x20, 0xe3, 0x03, +0x02, 0x21, 0x1f, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe1, 0x39, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x21, +0x12, 0x39, 0xcd, 0xef, 0x60, 0x2d, 0x90, 0x00, 0x8b, 0x74, 0x02, 0xf0, 0x78, 0x06, 0x14, 0xf2, +0x78, 0x02, 0x14, 0xf2, 0x08, 0xe5, 0x21, 0xf2, 0x12, 0x00, 0x60, 0x74, 0x03, 0x93, 0xfc, 0x74, +0x04, 0x93, 0xfd, 0xec, 0xc3, 0x13, 0xfe, 0xed, 0x13, 0xff, 0xed, 0x2f, 0x78, 0x05, 0xf2, 0xec, +0x3e, 0x18, 0xf2, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe0, 0x5b, 0x75, 0x25, 0x00, 0x75, 0x26, 0x00, +0x75, 0x27, 0x68, 0x75, 0x28, 0x00, 0x75, 0x29, 0x00, 0x75, 0x2a, 0x6a, 0x7b, 0xfe, 0x7a, 0x00, +0x79, 0x5f, 0x12, 0x29, 0x10, 0xe4, 0xf5, 0x20, 0xe5, 0x20, 0x12, 0x03, 0x72, 0xff, 0xe5, 0x20, +0x12, 0x05, 0x41, 0xef, 0xf2, 0xf4, 0x60, 0x1b, 0xe5, 0x20, 0x12, 0x05, 0xb8, 0xf9, 0xe4, 0xfa, +0x7b, 0xfe, 0xad, 0x20, 0x12, 0x39, 0x8b, 0xe5, 0x20, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x06, 0xf8, +0x74, 0x01, 0xf2, 0x05, 0x20, 0xe5, 0x20, 0xc3, 0x94, 0x02, 0x40, 0xcc, 0x12, 0x2a, 0x0e, 0x90, +0x00, 0x8b, 0x74, 0x01, 0xf0, 0x78, 0x62, 0xe6, 0x30, 0xe5, 0x04, 0x78, 0x6c, 0x76, 0x01, 0x90, +0x00, 0x8b, 0xe0, 0xf5, 0x1f, 0x78, 0x66, 0x76, 0x01, 0xe4, 0xf5, 0x20, 0xe5, 0x20, 0xc3, 0x94, +0x02, 0x50, 0x19, 0x90, 0x00, 0x8b, 0xe0, 0x30, 0xe0, 0x05, 0xaf, 0x20, 0x12, 0x39, 0xaf, 0x12, +0x30, 0x4c, 0x05, 0x20, 0x78, 0x66, 0x74, 0x2f, 0x26, 0xf6, 0x80, 0xe0, 0xa8, 0x1e, 0xac, 0x1d, +0xad, 0x1c, 0x12, 0x02, 0x9f, 0xe5, 0x1e, 0x24, 0x06, 0xf9, 0xe4, 0x35, 0x1d, 0xa8, 0x01, 0xfc, +0xad, 0x1c, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x02, 0xa3, 0x78, 0x0d, 0xe2, 0x70, 0x11, 0x78, 0x3c, +0xe2, 0x70, 0x0c, 0x90, 0x00, 0x8b, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xe4, 0x78, 0x6d, 0xf6, 0xaf, +0x1f, 0x22, 0x8f, 0x27, 0x8d, 0x28, 0x78, 0x64, 0xe6, 0x60, 0x01, 0x16, 0x12, 0x15, 0x25, 0xe0, +0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x27, 0x12, 0x14, 0xee, 0x12, 0x16, 0xc2, 0xf5, 0x2a, 0xec, 0x9e, +0xf5, 0x29, 0x12, 0x16, 0x6e, 0xe0, 0xf5, 0x2b, 0xe4, 0xf5, 0x2c, 0x12, 0x16, 0x0f, 0x40, 0x06, +0xae, 0x29, 0xaf, 0x2a, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe5, 0x27, 0x25, 0xe0, 0x24, 0x5f, +0xf8, 0xee, 0xf2, 0x08, 0xef, 0xf2, 0x90, 0x36, 0x0b, 0xe4, 0x93, 0x60, 0x07, 0x78, 0x64, 0xe6, +0xf5, 0x2c, 0x80, 0x0f, 0x12, 0x16, 0x0f, 0x7f, 0x00, 0x40, 0x02, 0x7f, 0x01, 0xef, 0x78, 0x64, +0x56, 0xf5, 0x2c, 0xe5, 0x2c, 0x60, 0x03, 0x02, 0x22, 0x9e, 0xaf, 0x2a, 0xae, 0x29, 0x12, 0x39, +0xa3, 0x12, 0x14, 0xd2, 0xc3, 0x12, 0x16, 0x7f, 0x50, 0x0d, 0x12, 0x16, 0x10, 0x40, 0x04, 0x05, +0x2b, 0x80, 0x57, 0x15, 0x2b, 0x80, 0x53, 0x12, 0x15, 0xff, 0xe0, 0xff, 0x33, 0x95, 0xe0, 0xfe, +0xef, 0x25, 0x2a, 0xf5, 0x2a, 0xee, 0x35, 0x29, 0xf5, 0x29, 0xd3, 0xe5, 0x2a, 0x94, 0x78, 0x12, +0x16, 0x14, 0x40, 0x09, 0x12, 0x15, 0x25, 0xe4, 0x75, 0xf0, 0x01, 0x80, 0x1a, 0xe5, 0x2a, 0x24, +0x78, 0xe4, 0x35, 0x29, 0xc3, 0x64, 0x80, 0x94, 0x80, 0xe5, 0x27, 0x75, 0xf0, 0x0a, 0x50, 0x11, +0x12, 0x15, 0x2a, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x0d, 0xa5, 0x12, 0x15, 0xff, 0xe4, 0xf0, 0x80, +0x06, 0x12, 0x16, 0x04, 0xe5, 0x2a, 0xf0, 0xe4, 0xf5, 0x2b, 0x12, 0x14, 0xd2, 0x74, 0x01, 0x93, +0xff, 0xd3, 0x64, 0x80, 0xf8, 0xe5, 0x2b, 0x64, 0x80, 0x98, 0x50, 0x17, 0xef, 0x33, 0x95, 0xe0, +0xfe, 0xad, 0x2b, 0xed, 0x33, 0x95, 0xe0, 0xfc, 0xed, 0x2f, 0xec, 0x3e, 0xc3, 0x64, 0x80, 0x94, +0x80, 0x50, 0x15, 0xe4, 0xf5, 0x2b, 0xe5, 0x27, 0x12, 0x14, 0xee, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, +0x12, 0x15, 0x25, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x16, 0x6e, 0xe5, 0x2b, 0xf0, 0x78, 0x64, +0xe6, 0x70, 0x3a, 0x12, 0x15, 0x25, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe5, 0x27, 0x12, 0x16, 0x88, +0x12, 0x16, 0xc2, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x39, 0xa3, 0xaa, 0x06, 0xab, 0x07, 0x12, 0x14, +0xd2, 0x74, 0x04, 0x93, 0xfe, 0x74, 0x05, 0x93, 0xff, 0x7c, 0x00, 0x7d, 0x03, 0x12, 0x0d, 0x08, +0xd3, 0xeb, 0x9f, 0xea, 0x9e, 0x40, 0x06, 0x78, 0x62, 0xe6, 0x44, 0x10, 0xf6, 0x05, 0x27, 0x15, +0x28, 0xe5, 0x28, 0x60, 0x03, 0x02, 0x21, 0x8c, 0x22, 0x8e, 0x1c, 0x8f, 0x1d, 0xe4, 0x78, 0x61, +0xf6, 0x85, 0x1c, 0x0c, 0x85, 0x1d, 0x0d, 0xe5, 0x1d, 0x24, 0x2c, 0xff, 0xe4, 0x35, 0x1c, 0xfa, +0xa9, 0x07, 0x7b, 0xff, 0x78, 0x5d, 0x7c, 0x00, 0x7d, 0x00, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c, +0x68, 0x78, 0x84, 0x74, 0x01, 0xf2, 0x08, 0x74, 0xcc, 0xf2, 0x85, 0x1d, 0x82, 0x85, 0x1c, 0x83, +0xe4, 0x93, 0xff, 0x7e, 0x00, 0xe5, 0x1d, 0x24, 0x06, 0xfd, 0xe4, 0x35, 0x1c, 0xfa, 0xa9, 0x05, +0x7b, 0xff, 0x18, 0xe2, 0xfc, 0x08, 0xe2, 0xf8, 0x7d, 0x01, 0x12, 0x0c, 0x68, 0x90, 0x01, 0xa7, +0xe0, 0xff, 0x12, 0x34, 0x0d, 0x90, 0x00, 0xc1, 0xe0, 0x64, 0x80, 0x70, 0x04, 0xa3, 0xe0, 0x64, +0x75, 0x70, 0x44, 0xff, 0x85, 0x1d, 0x82, 0x85, 0x1c, 0x83, 0xe4, 0x93, 0xfe, 0xef, 0xc3, 0x9e, +0x50, 0x35, 0xe4, 0xf5, 0x1f, 0x12, 0x16, 0x57, 0xfd, 0x12, 0x14, 0xe3, 0xfe, 0xe5, 0x1f, 0x90, +0x39, 0xd0, 0x93, 0xfb, 0xee, 0x6b, 0x60, 0x0b, 0xe5, 0x1f, 0xc3, 0x94, 0x0f, 0x50, 0x04, 0x05, +0x1f, 0x80, 0xe2, 0xe5, 0x1f, 0x90, 0x39, 0xdf, 0x93, 0xfe, 0xed, 0x2f, 0xf5, 0x82, 0xe4, 0x3c, +0xf5, 0x83, 0xee, 0xf0, 0x0f, 0x80, 0xbd, 0x7e, 0x00, 0x7d, 0x00, 0x12, 0x16, 0x35, 0x12, 0x14, +0xd2, 0x74, 0x02, 0x93, 0xff, 0x7e, 0x00, 0x7c, 0x10, 0x7d, 0x00, 0x12, 0x10, 0x6b, 0xe4, 0x7b, +0xc8, 0xfa, 0xf9, 0xf8, 0x12, 0x0f, 0x42, 0x90, 0x02, 0x00, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x78, +0x83, 0x74, 0x09, 0xf2, 0x78, 0x5f, 0xe6, 0xff, 0x20, 0xe3, 0x06, 0x78, 0x83, 0xe2, 0x44, 0x04, +0xf2, 0xef, 0x20, 0xe2, 0x06, 0x78, 0x83, 0xe2, 0x44, 0x20, 0xf2, 0xe4, 0x78, 0x63, 0xf6, 0x43, +0x95, 0x80, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x30, 0xe1, 0x02, 0x7f, 0x40, 0xef, 0x44, 0x37, 0x90, +0xff, 0x41, 0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0x75, 0x1e, 0x11, 0xe5, 0x1e, 0xf4, 0x60, +0x0c, 0xe4, 0xfd, 0xaf, 0x1e, 0x12, 0x32, 0xcc, 0xe4, 0xfd, 0x12, 0x24, 0x30, 0x75, 0x1e, 0x16, +0xe5, 0x1e, 0xf4, 0x60, 0x0c, 0xe4, 0xfd, 0xaf, 0x1e, 0x12, 0x32, 0xcc, 0x7d, 0x01, 0x12, 0x24, +0x30, 0x78, 0x60, 0xe6, 0x7f, 0x08, 0x30, 0xe0, 0x02, 0x7f, 0x05, 0x78, 0x87, 0xef, 0xf2, 0x22, +0xaf, 0x1e, 0x12, 0x34, 0xaa, 0x7d, 0x08, 0xaf, 0x1e, 0x12, 0x30, 0xb1, 0x7d, 0x07, 0xaf, 0x1e, +0x12, 0x30, 0xb1, 0x22, 0x8f, 0x23, 0x12, 0x05, 0x40, 0xe2, 0xff, 0x70, 0x04, 0xf5, 0x24, 0x80, +0x18, 0x78, 0x67, 0xe6, 0xfe, 0x14, 0xb5, 0x07, 0x09, 0xee, 0x25, 0xe0, 0x24, 0xfa, 0xf5, 0x24, +0x80, 0x07, 0xef, 0x25, 0xe0, 0x24, 0xfe, 0xf5, 0x24, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x63, 0x12, +0x00, 0xf3, 0xe5, 0x24, 0x12, 0x02, 0xd8, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x68, 0x12, 0x02, 0xdc, +0xe4, 0xfc, 0xfd, 0x78, 0x4f, 0x12, 0x10, 0x34, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x65, 0x12, 0x00, +0xf3, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x62, 0x12, 0x02, 0xdc, 0xe5, 0x24, 0x25, 0xe0, 0x24, 0x6a, +0x12, 0x02, 0xdc, 0xe4, 0xfc, 0xfd, 0x78, 0x53, 0x12, 0x10, 0x34, 0x12, 0x00, 0x60, 0x74, 0x07, +0x93, 0xfe, 0x74, 0x08, 0x78, 0x53, 0x12, 0x04, 0x63, 0x12, 0x0e, 0xb7, 0xc0, 0x04, 0xc0, 0x05, +0xc0, 0x06, 0xc0, 0x07, 0x12, 0x00, 0x60, 0x78, 0x53, 0x12, 0x03, 0x05, 0x12, 0x0e, 0xb7, 0xd0, +0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x12, 0x01, 0xc3, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, +0xc0, 0x07, 0x12, 0x00, 0x60, 0x74, 0x05, 0x93, 0xfe, 0x74, 0x06, 0x78, 0x4f, 0x12, 0x04, 0x63, +0x12, 0x01, 0x2b, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xc3, 0xef, 0x9b, 0xff, 0xee, +0x9a, 0xfe, 0xed, 0x99, 0xfd, 0xec, 0x98, 0xfc, 0x78, 0x57, 0x12, 0x10, 0x34, 0x78, 0x57, 0x12, +0x10, 0x0b, 0xec, 0x33, 0x50, 0x0b, 0x78, 0x4f, 0x12, 0x10, 0x40, 0x00, 0x00, 0x00, 0x01, 0x80, +0x5b, 0x12, 0x05, 0x63, 0x7b, 0x02, 0x12, 0x02, 0x36, 0x12, 0x0f, 0x42, 0x78, 0x57, 0x12, 0x10, +0x17, 0x12, 0x01, 0xc3, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x05, 0x63, 0x2f, +0xfb, 0xea, 0x3e, 0xfa, 0xe9, 0x3d, 0xf9, 0xe8, 0x3c, 0xf8, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, +0xd0, 0x04, 0x12, 0x0f, 0x42, 0x78, 0x4f, 0x12, 0x10, 0x34, 0x12, 0x00, 0x60, 0x78, 0x4f, 0x12, +0x03, 0x05, 0xd3, 0x12, 0x0f, 0xd4, 0x40, 0x14, 0x12, 0x00, 0x60, 0x74, 0x02, 0x93, 0x24, 0xff, +0xff, 0x74, 0x01, 0x93, 0x12, 0x02, 0x2c, 0x78, 0x4f, 0x12, 0x10, 0x34, 0x78, 0x4f, 0x12, 0x10, +0x0b, 0xe5, 0x23, 0x12, 0x02, 0xac, 0x22, 0x8b, 0x1f, 0x8a, 0x20, 0x89, 0x21, 0x43, 0xad, 0x04, +0x43, 0x95, 0x80, 0x90, 0xff, 0x41, 0x74, 0x80, 0xf0, 0x90, 0xff, 0x49, 0x74, 0x0d, 0xf0, 0xa3, +0xe4, 0xf0, 0x90, 0xff, 0x42, 0x04, 0xf0, 0x90, 0xff, 0x55, 0x74, 0x7d, 0xf0, 0x90, 0xff, 0x54, +0xe4, 0xf0, 0x90, 0xff, 0x5c, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x10, 0xf0, 0xe4, 0xf5, 0x26, 0xf5, +0x27, 0xf5, 0x28, 0xf5, 0x29, 0xf5, 0x25, 0xe4, 0x12, 0x35, 0xaa, 0xf4, 0x60, 0x0d, 0xe4, 0xfd, +0x12, 0x32, 0xcc, 0x12, 0x35, 0xb2, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60, +0x0d, 0xe4, 0xfd, 0x12, 0x32, 0xcc, 0x12, 0x35, 0x9c, 0x7d, 0x08, 0x12, 0x30, 0xb1, 0xe4, 0xff, +0x00, 0x0f, 0xbf, 0xc8, 0xfb, 0x74, 0x03, 0x12, 0x35, 0xaa, 0xf4, 0x60, 0x0d, 0xe4, 0xfd, 0x12, +0x34, 0xaa, 0x12, 0x35, 0xb2, 0x7d, 0x07, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60, 0x0d, +0x7d, 0x01, 0x12, 0x34, 0xaa, 0x12, 0x35, 0x9c, 0x7d, 0x07, 0x12, 0x30, 0xb1, 0x90, 0xff, 0x43, +0x74, 0x9f, 0xf0, 0x90, 0xff, 0x50, 0x74, 0x07, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90, 0xff, 0x40, +0x74, 0x09, 0xf0, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x30, +0xe4, 0xf9, 0x90, 0xff, 0x43, 0x74, 0x9f, 0xf0, 0x90, 0xff, 0x52, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, +0x27, 0xf5, 0x27, 0xee, 0x35, 0x26, 0xf5, 0x26, 0x90, 0xff, 0x5a, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, +0x29, 0xf5, 0x29, 0xee, 0x35, 0x28, 0xf5, 0x28, 0x05, 0x25, 0xe5, 0x25, 0xc3, 0x94, 0x04, 0x50, +0x03, 0x02, 0x25, 0xc7, 0xe5, 0x27, 0xae, 0x26, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, +0xf9, 0xff, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x6b, 0xe5, 0x29, +0xae, 0x28, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xab, 0x22, 0xaa, 0x23, +0xa9, 0x24, 0x90, 0x00, 0x02, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x8a, 0x12, 0x35, 0xb2, 0xf4, 0x60, +0x05, 0xe4, 0xfd, 0x12, 0x30, 0xb1, 0x12, 0x35, 0x9c, 0xf4, 0x60, 0x05, 0xe4, 0xfd, 0x12, 0x30, +0xb1, 0x22, 0xe4, 0xf5, 0x27, 0xe5, 0x27, 0xc3, 0x78, 0x65, 0x96, 0x50, 0x2b, 0x12, 0x16, 0x57, +0x25, 0x27, 0x12, 0x14, 0xe4, 0xf5, 0x28, 0x78, 0x60, 0xe6, 0x54, 0x01, 0xfd, 0xaf, 0x28, 0x12, +0x32, 0xcc, 0x78, 0x60, 0xe6, 0xb4, 0x03, 0x0c, 0xe5, 0x27, 0x30, 0xe0, 0x07, 0xe4, 0xfd, 0xaf, +0x28, 0x12, 0x32, 0xcc, 0x05, 0x27, 0x80, 0xcd, 0x90, 0xff, 0x4a, 0x74, 0x71, 0xf0, 0x90, 0xff, +0x50, 0x74, 0x0f, 0xf0, 0x90, 0xff, 0x58, 0xf0, 0x90, 0xff, 0x40, 0xe4, 0xf0, 0x12, 0x16, 0x96, +0x90, 0xff, 0x54, 0xe4, 0xf0, 0x90, 0xff, 0x5c, 0xf0, 0x78, 0x5e, 0xe6, 0x90, 0xff, 0x42, 0xf0, +0x90, 0xff, 0x55, 0x74, 0x28, 0xf0, 0x90, 0xff, 0x48, 0x74, 0x02, 0xf0, 0x43, 0xad, 0x04, 0x12, +0x16, 0x9d, 0x90, 0xff, 0x43, 0xe0, 0x20, 0xe4, 0x1d, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14, +0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0xe6, 0x12, 0x14, 0x84, 0x50, +0xe1, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0x12, 0x16, 0x96, 0xe4, 0x78, 0x86, 0xf2, 0x78, 0x5c, 0xf6, +0x18, 0x76, 0x01, 0x78, 0x65, 0xe6, 0xc3, 0x13, 0x78, 0x63, 0xf6, 0x78, 0x5e, 0xe6, 0x90, 0xff, +0x42, 0xf0, 0x18, 0xe6, 0x90, 0xff, 0x48, 0xf0, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x20, 0xe4, 0x02, +0x7f, 0x01, 0x90, 0x02, 0x02, 0xef, 0xf0, 0x12, 0x15, 0x35, 0x08, 0x12, 0x14, 0xdb, 0xff, 0x7d, +0x06, 0x12, 0x30, 0xb1, 0x78, 0x5b, 0x12, 0x14, 0xdb, 0xff, 0x7d, 0x06, 0x12, 0x30, 0xb1, 0x78, +0x83, 0xe2, 0xff, 0x90, 0xff, 0x40, 0xf0, 0x78, 0x5f, 0xe6, 0x30, 0xe7, 0x3e, 0x43, 0xad, 0x04, +0xef, 0xf0, 0x90, 0xff, 0x43, 0xe0, 0x20, 0xe4, 0x1d, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14, +0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0xe6, 0x12, 0x14, 0x84, 0x50, +0xe1, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0x7b, 0xff, 0x7a, 0x30, 0x79, 0xb1, 0x12, 0x27, 0xf2, 0x12, +0x15, 0xe4, 0xf0, 0x78, 0x63, 0xe6, 0x70, 0xca, 0x02, 0x31, 0x0b, 0x53, 0xad, 0xfb, 0x12, 0x16, +0x9d, 0x22, 0x15, 0x3f, 0x15, 0x3f, 0x15, 0x3f, 0xa8, 0x3f, 0xa6, 0x03, 0x08, 0xa6, 0x02, 0x08, +0xa6, 0x01, 0x15, 0x3f, 0x12, 0x16, 0x96, 0x78, 0x87, 0xe2, 0xa8, 0x3f, 0xf6, 0x12, 0x14, 0xd9, +0xff, 0xa8, 0x3f, 0xe6, 0xfd, 0x12, 0x15, 0x8e, 0x12, 0x10, 0x69, 0x78, 0x60, 0xe6, 0x64, 0x03, +0x78, 0x5b, 0x60, 0x0d, 0x12, 0x14, 0xdb, 0xff, 0xa8, 0x3f, 0xe6, 0xfd, 0x12, 0x15, 0x8e, 0x80, +0x08, 0x12, 0x14, 0xdb, 0x12, 0x15, 0x8b, 0x7d, 0x08, 0x12, 0x10, 0x69, 0x90, 0xff, 0x52, 0xe0, +0xfe, 0xa3, 0xe0, 0xff, 0x78, 0x5c, 0xe6, 0x12, 0x15, 0x7d, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x12, +0x15, 0xf7, 0xff, 0x18, 0xe6, 0x12, 0x15, 0x7d, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x02, 0x02, +0xe0, 0x60, 0x2e, 0x08, 0xe6, 0xff, 0x12, 0x14, 0xee, 0x12, 0x15, 0x77, 0x12, 0x29, 0x02, 0x12, +0x14, 0xd2, 0x12, 0x16, 0x7e, 0x40, 0x1a, 0x78, 0x5b, 0xe6, 0xff, 0x12, 0x14, 0xee, 0x12, 0x15, +0x77, 0x12, 0x29, 0x02, 0x12, 0x14, 0xd2, 0x12, 0x16, 0x7e, 0x40, 0x05, 0xe4, 0x90, 0x02, 0x02, +0xf0, 0x90, 0x02, 0x02, 0xe0, 0x70, 0x1b, 0x78, 0x5c, 0x06, 0x06, 0x18, 0x06, 0x06, 0x78, 0x63, +0x16, 0x78, 0x5f, 0xe6, 0x7f, 0x00, 0x20, 0xe4, 0x02, 0x7f, 0x01, 0x90, 0x02, 0x02, 0xef, 0xf0, +0x80, 0x05, 0xe4, 0x90, 0x02, 0x02, 0xf0, 0x78, 0x63, 0xe6, 0x70, 0x0a, 0x90, 0xff, 0x50, 0xf0, +0x90, 0xff, 0x58, 0xf0, 0x80, 0x35, 0x12, 0x15, 0x35, 0xa8, 0x3f, 0x76, 0x64, 0x90, 0xff, 0x58, +0xe0, 0xff, 0x90, 0xff, 0x50, 0xe0, 0x4f, 0x30, 0xe7, 0x06, 0xa8, 0x3f, 0x16, 0xe6, 0x70, 0xed, +0x12, 0x14, 0xd9, 0x12, 0x15, 0x8b, 0x7d, 0x06, 0x12, 0x10, 0x69, 0x78, 0x5b, 0x12, 0x14, 0xdb, +0x12, 0x15, 0x8b, 0x7d, 0x06, 0x12, 0x10, 0x69, 0x12, 0x16, 0x9d, 0xe5, 0x3f, 0x24, 0x04, 0xf5, +0x3f, 0x22, 0xe0, 0xfe, 0xa3, 0xe0, 0xc3, 0x9d, 0xff, 0xee, 0x9c, 0xfe, 0x12, 0x39, 0xa3, 0x22, +0x8b, 0x22, 0x8a, 0x23, 0x89, 0x24, 0x12, 0x2d, 0x79, 0x12, 0x2d, 0xfc, 0x12, 0x31, 0xac, 0x74, +0x55, 0x93, 0xf5, 0x2b, 0xe4, 0xf5, 0x2c, 0x12, 0x31, 0xef, 0x12, 0x0c, 0x8e, 0x70, 0x21, 0x12, +0x31, 0xac, 0x74, 0x74, 0x93, 0xf5, 0x2d, 0xc3, 0x64, 0x80, 0x94, 0x80, 0x7f, 0x00, 0x50, 0x02, +0x7f, 0x01, 0x12, 0x29, 0xd6, 0xee, 0x8f, 0xf0, 0x12, 0x0e, 0x1e, 0x75, 0x2c, 0x03, 0x80, 0x3a, +0x12, 0x31, 0xef, 0x12, 0x0c, 0x8e, 0xff, 0xe5, 0x2b, 0x14, 0x6f, 0x70, 0x2d, 0x12, 0x31, 0xac, +0x74, 0x75, 0x93, 0xf5, 0x2d, 0xc3, 0x64, 0x80, 0x94, 0x80, 0xe5, 0x2b, 0x50, 0x06, 0x25, 0xe0, +0x14, 0xff, 0x80, 0x05, 0x25, 0xe0, 0x24, 0xfe, 0xff, 0x12, 0x29, 0xd6, 0xee, 0x8f, 0xf0, 0x12, +0x0e, 0x1e, 0xe5, 0x2b, 0x25, 0xe0, 0x24, 0xfd, 0xf5, 0x2c, 0xe5, 0x2c, 0x60, 0x47, 0x24, 0xff, +0xff, 0xe4, 0x34, 0xff, 0xfe, 0xef, 0x25, 0xe0, 0xff, 0xee, 0x33, 0xab, 0x22, 0xaa, 0x23, 0xa9, +0x24, 0x8f, 0x82, 0xf5, 0x83, 0x12, 0x0d, 0xe6, 0xff, 0xae, 0xf0, 0x75, 0xf0, 0x02, 0xe5, 0x2c, +0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x12, 0x0d, 0xe6, 0x2f, 0xff, 0xee, 0x35, 0xf0, 0xfe, 0x12, +0x31, 0xac, 0xd3, 0x74, 0x77, 0x93, 0x9f, 0x74, 0x76, 0x93, 0x9e, 0x40, 0x08, 0x12, 0x31, 0xef, +0x74, 0xff, 0x12, 0x0c, 0xd4, 0x22, 0x8f, 0x2c, 0xaf, 0x2d, 0xef, 0x33, 0x95, 0xe0, 0xfe, 0x12, +0x39, 0xa3, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0x75, 0xf0, 0x02, 0xe5, 0x2c, 0xa4, 0xf5, 0x82, +0x85, 0xf0, 0x83, 0x12, 0x0d, 0xe6, 0xfd, 0xac, 0xf0, 0xcf, 0xcd, 0xcf, 0xce, 0xcc, 0xce, 0x12, +0x0d, 0x1a, 0x75, 0xf0, 0x02, 0xe5, 0x2c, 0xa4, 0xf5, 0x82, 0x85, 0xf0, 0x83, 0x22, 0xe4, 0xf5, +0x22, 0xf5, 0x23, 0xff, 0xfe, 0x78, 0x35, 0xe2, 0x25, 0xe0, 0xfd, 0x78, 0x06, 0xe2, 0x2d, 0xfd, +0x78, 0x0c, 0xe2, 0xc4, 0x54, 0xf0, 0x2d, 0xfd, 0x78, 0x3b, 0xe2, 0xfc, 0xc4, 0x33, 0x54, 0xe0, +0x2d, 0x24, 0xfe, 0x60, 0x25, 0x24, 0xf0, 0x60, 0x21, 0x14, 0x60, 0x26, 0x24, 0xf2, 0x60, 0x1a, +0x24, 0xfe, 0x60, 0x2e, 0x24, 0xf1, 0x60, 0x0c, 0x14, 0x60, 0x3b, 0x24, 0x02, 0x70, 0x6c, 0xe4, +0xfd, 0xff, 0x80, 0x22, 0x7d, 0x01, 0x7f, 0x01, 0x80, 0x0b, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, +0x80, 0x59, 0xe4, 0xfd, 0xff, 0x12, 0x32, 0x86, 0x8e, 0x22, 0x8f, 0x23, 0xe4, 0xfd, 0x7f, 0x01, +0x80, 0x0f, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x32, 0x86, 0x8e, 0x22, 0x8f, 0x23, 0x7d, 0x01, 0xe4, +0xff, 0x12, 0x32, 0x86, 0x80, 0x35, 0x7d, 0x01, 0x7f, 0x01, 0x12, 0x32, 0x86, 0xc0, 0x06, 0xc0, +0x07, 0xe4, 0xfd, 0xff, 0x12, 0x32, 0x86, 0xd0, 0xe0, 0x2f, 0xf5, 0x23, 0xd0, 0xe0, 0x3e, 0xf5, +0x22, 0xe4, 0xfd, 0x7f, 0x01, 0x12, 0x32, 0x86, 0xc0, 0x06, 0xc0, 0x07, 0x7d, 0x01, 0xe4, 0xff, +0x12, 0x32, 0x86, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0xd3, 0xe5, 0x23, 0x9f, 0xe5, +0x22, 0x9e, 0x40, 0x27, 0x78, 0x24, 0x7c, 0x00, 0x7d, 0x00, 0x12, 0x02, 0x9f, 0x78, 0x02, 0x7c, +0x00, 0x7d, 0xfe, 0x7b, 0xfe, 0x7a, 0x00, 0x79, 0x31, 0x12, 0x02, 0xa5, 0x78, 0x31, 0x7c, 0x00, +0x7d, 0xfe, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x12, 0x02, 0xa5, 0x22, 0xab, 0x25, 0xe5, 0x27, +0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5, 0x26, 0xee, 0x8f, 0xf0, 0x12, +0x0e, 0x6b, 0x90, 0x00, 0x02, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0d, 0xe6, 0xff, 0xae, +0xf0, 0xab, 0x25, 0xe5, 0x27, 0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5, +0x26, 0xee, 0x8f, 0xf0, 0x02, 0x0e, 0x6b, 0x90, 0x00, 0x05, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, +0x02, 0x0c, 0xa7, 0xe5, 0x2a, 0xfd, 0x24, 0x02, 0xf5, 0x2a, 0xe5, 0x29, 0xfc, 0x34, 0x00, 0xf5, +0x29, 0x8d, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x05, 0x28, 0xe5, 0x28, 0xc3, 0x94, +0x10, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x90, 0x00, 0x0b, 0x02, 0x0c, 0xa7, 0xab, 0x25, +0xe5, 0x27, 0xf9, 0x24, 0x02, 0xf5, 0x27, 0xe5, 0x26, 0xfa, 0x34, 0x00, 0xf5, 0x26, 0xe4, 0xf5, +0xf0, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x22, 0xe5, 0x1f, 0xfe, 0x7c, 0x00, 0xe4, 0x25, +0x22, 0xff, 0xec, 0x3e, 0xfe, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff, +0x22, 0x75, 0x25, 0x01, 0x85, 0x23, 0x26, 0x85, 0x24, 0x27, 0x22, 0xab, 0x25, 0xaa, 0x26, 0xa9, +0x27, 0x02, 0x0d, 0xbb, 0x75, 0x29, 0x01, 0x75, 0x2a, 0x61, 0xe4, 0xf5, 0x28, 0x22, 0x78, 0xff, +0xe4, 0xf6, 0xd8, 0xfd, 0x90, 0x00, 0x00, 0x7f, 0x00, 0x7e, 0x03, 0xe4, 0xf0, 0xa3, 0xdf, 0xfc, +0xde, 0xfa, 0x75, 0x81, 0x74, 0x75, 0xa0, 0x00, 0x02, 0x2c, 0x06, 0x02, 0x33, 0xd3, 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, 0x39, 0xbf, 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, 0x90, 0x36, 0x0a, 0xe4, 0x93, +0x70, 0x05, 0x43, 0x90, 0x10, 0x80, 0x03, 0x53, 0x90, 0xef, 0x90, 0x36, 0x0c, 0xe4, 0x93, 0xff, +0x7c, 0x01, 0x7d, 0x00, 0x12, 0x33, 0x94, 0x90, 0x36, 0x0d, 0xe4, 0x93, 0xb4, 0x01, 0x07, 0x90, +0xff, 0x10, 0xe0, 0x44, 0x18, 0xf0, 0x7e, 0x01, 0x7f, 0x00, 0x7d, 0x00, 0x7b, 0x01, 0x7a, 0x01, +0x79, 0x00, 0x12, 0x10, 0x98, 0x7d, 0x01, 0x7f, 0x12, 0x12, 0x32, 0xcc, 0x7d, 0x03, 0x7f, 0x12, +0x12, 0x30, 0xb1, 0x90, 0xff, 0x1b, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xff, 0x14, 0xe0, 0x44, 0x04, +0xf0, 0x90, 0x36, 0x09, 0xe4, 0x93, 0x90, 0x01, 0xfa, 0xf0, 0x90, 0x36, 0x07, 0xe4, 0x93, 0x90, +0x01, 0xea, 0xf0, 0x90, 0x36, 0x11, 0xe4, 0x93, 0x90, 0x01, 0xed, 0xf0, 0x78, 0xa7, 0x7c, 0x01, +0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x36, 0x79, 0x00, 0x7e, 0x00, 0x7f, 0x03, 0x12, 0x0c, 0x68, 0xe4, +0x90, 0x01, 0xec, 0xf0, 0x90, 0x01, 0xfe, 0x04, 0xf0, 0xe4, 0x78, 0x73, 0xf6, 0x90, 0x00, 0xca, +0xf0, 0xa3, 0xf0, 0x22, 0x8f, 0x1c, 0x8c, 0x1d, 0x8d, 0x1e, 0xe4, 0xff, 0x79, 0x01, 0xe4, 0xf5, +0x1f, 0xfe, 0x12, 0x35, 0xf3, 0xe5, 0x82, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe4, +0x93, 0x25, 0xe0, 0x25, 0x1c, 0xf8, 0xe2, 0xfc, 0x08, 0xe2, 0xfd, 0x12, 0x35, 0xf3, 0x74, 0x04, +0x93, 0xfa, 0x74, 0x05, 0x93, 0xfb, 0xc3, 0xed, 0x9b, 0xec, 0x9a, 0x40, 0x02, 0x05, 0x1f, 0x0e, +0xbe, 0x04, 0xcf, 0x12, 0x35, 0xf3, 0x74, 0x06, 0x93, 0xfd, 0xe5, 0x1f, 0xc3, 0x9d, 0x50, 0x04, +0xe4, 0xf9, 0x80, 0x04, 0x0f, 0xbf, 0x05, 0xb6, 0x90, 0x00, 0xcd, 0xe0, 0xb5, 0x01, 0x07, 0xe4, +0x90, 0x00, 0xcc, 0xf0, 0x80, 0x28, 0x90, 0x00, 0xcc, 0xe0, 0x04, 0xf0, 0x85, 0x1e, 0x82, 0x85, +0x1d, 0x83, 0x74, 0x23, 0x93, 0xff, 0x90, 0x00, 0xcc, 0xe0, 0xfd, 0x33, 0x95, 0xe0, 0xfc, 0xd3, +0xed, 0x9f, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x40, 0x05, 0xe4, 0xf0, 0xa3, 0xe9, 0xf0, 0x90, 0x00, +0xcd, 0xe0, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0xaa, 0x22, 0xe4, 0x78, 0x4f, 0xf6, 0x08, 0xf6, 0xfe, +0xfd, 0x12, 0x01, 0xb8, 0x12, 0x02, 0xe5, 0xe4, 0xf9, 0xf5, 0x30, 0xf5, 0x2e, 0x75, 0x2f, 0xff, +0x78, 0x67, 0xe6, 0xff, 0xe9, 0xc3, 0x9f, 0x50, 0x5b, 0xe9, 0x12, 0x00, 0xed, 0xe9, 0x25, 0xe0, +0x25, 0xe0, 0x24, 0x60, 0xf8, 0xe2, 0x2f, 0xf5, 0x32, 0x18, 0xe2, 0x3e, 0xf5, 0x31, 0x12, 0x03, +0x55, 0x78, 0x4f, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xef, 0x2d, 0xfb, 0xee, 0x3c, 0xfa, 0xd3, 0xe5, +0x32, 0x9b, 0xe5, 0x31, 0x9a, 0x40, 0x06, 0x75, 0x30, 0x01, 0x18, 0x80, 0x1d, 0xe5, 0x32, 0x2f, +0xff, 0xe5, 0x31, 0x3e, 0xfe, 0xd3, 0xed, 0x9f, 0xec, 0x9e, 0x40, 0x15, 0xe5, 0x30, 0x60, 0x08, +0xe4, 0xf5, 0x30, 0x12, 0x31, 0xf6, 0x05, 0x2e, 0x78, 0x4f, 0xa6, 0x31, 0x08, 0xa6, 0x32, 0x89, +0x2f, 0x09, 0x80, 0x9c, 0xe5, 0x30, 0x60, 0x03, 0x12, 0x31, 0xf6, 0x22, 0xe4, 0xfb, 0x12, 0x03, +0x71, 0xfa, 0xf4, 0x60, 0x62, 0xea, 0x70, 0x0c, 0x12, 0x00, 0x60, 0x74, 0x11, 0x93, 0xf5, 0x2e, +0x74, 0x12, 0x80, 0x1d, 0x78, 0x67, 0xe6, 0x14, 0xb5, 0x02, 0x0c, 0x12, 0x00, 0x60, 0x74, 0x13, +0x93, 0xf5, 0x2e, 0x74, 0x14, 0x80, 0x0a, 0x12, 0x00, 0x60, 0x74, 0x0f, 0x93, 0xf5, 0x2e, 0x74, +0x10, 0x93, 0xf5, 0x2f, 0x78, 0x0d, 0xe2, 0x70, 0x05, 0x78, 0x3c, 0xe2, 0x60, 0x0e, 0xe5, 0x2f, +0x25, 0xe0, 0xff, 0xe5, 0x2e, 0x12, 0x05, 0xde, 0x8e, 0x2e, 0x8f, 0x2f, 0xea, 0x12, 0x00, 0xed, +0xea, 0x25, 0xe0, 0x12, 0x02, 0xd8, 0xc3, 0xef, 0x95, 0x2f, 0xee, 0x95, 0x2e, 0x50, 0x08, 0xeb, +0x25, 0xe0, 0x24, 0x68, 0xf8, 0x76, 0xff, 0x0b, 0xeb, 0x64, 0x02, 0x70, 0x91, 0x78, 0x68, 0xe6, +0xb4, 0xff, 0x0a, 0x78, 0x6a, 0xe6, 0xff, 0xf4, 0x60, 0x03, 0x12, 0x01, 0x97, 0x22, 0xef, 0x54, +0x07, 0xfe, 0x74, 0x01, 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf9, 0xf4, 0xfe, +0xef, 0x54, 0xf0, 0xf5, 0x3e, 0x64, 0x10, 0x70, 0x1e, 0xbd, 0x08, 0x02, 0x7d, 0x02, 0x90, 0xff, +0x12, 0xed, 0x30, 0xe2, 0x05, 0xe0, 0x49, 0xf0, 0x80, 0x03, 0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15, +0x82, 0x70, 0x14, 0x15, 0x83, 0x80, 0x10, 0xe5, 0x3e, 0x13, 0x13, 0x54, 0x3f, 0x24, 0x11, 0xfb, +0xe4, 0x34, 0xff, 0xf5, 0x83, 0x8b, 0x82, 0xed, 0x24, 0xfb, 0x60, 0x14, 0x14, 0x60, 0x20, 0x24, +0xfe, 0x70, 0x2a, 0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x1e, 0x15, 0x83, 0x80, 0x1a, +0xe0, 0x5e, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x49, 0xf0, 0x22, 0xe0, +0x49, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x5e, 0xf0, 0x22, 0xc0, 0xe0, +0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x78, 0x40, 0xa6, 0xa3, 0x08, 0xa6, 0xa6, +0x75, 0xa3, 0x08, 0xe6, 0xff, 0x30, 0xe4, 0x07, 0x75, 0xd1, 0xdf, 0x78, 0x72, 0x76, 0x00, 0x78, +0x40, 0xe6, 0x30, 0xe0, 0x40, 0xef, 0x20, 0xe0, 0x39, 0x78, 0x72, 0xe6, 0xff, 0x70, 0x18, 0x90, +0x02, 0xf8, 0xe0, 0xfe, 0xf5, 0xd6, 0x18, 0xee, 0xf6, 0xc3, 0x94, 0x10, 0x50, 0x24, 0x78, 0x73, +0xe6, 0x25, 0xd6, 0xf5, 0xd6, 0x80, 0x1b, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, +0x83, 0xe0, 0xff, 0x78, 0x71, 0xe6, 0x06, 0x25, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x08, 0xf5, 0x83, +0xef, 0xf0, 0x78, 0x72, 0x06, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xab, 0x07, +0xaa, 0x05, 0xe4, 0x78, 0x62, 0xf6, 0xeb, 0x12, 0x14, 0xee, 0xe0, 0xf5, 0x29, 0xa3, 0xe0, 0xf5, +0x2a, 0x78, 0x5d, 0xe6, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xae, 0x27, 0xff, 0x7c, 0x00, 0x7d, 0xfc, +0x12, 0x0d, 0x08, 0xd3, 0xe5, 0x2a, 0x9f, 0xe5, 0x29, 0x9e, 0x40, 0x06, 0x78, 0x62, 0xe6, 0x44, +0x20, 0xf6, 0x12, 0x14, 0xd2, 0x74, 0x05, 0x93, 0x25, 0xe0, 0xf5, 0x2a, 0x74, 0x04, 0x93, 0x33, +0xf5, 0x29, 0xeb, 0x12, 0x15, 0x27, 0xe0, 0xfe, 0xa3, 0xe0, 0x25, 0x2a, 0xff, 0xe5, 0x29, 0x3e, +0xfe, 0xeb, 0x12, 0x14, 0xee, 0xe0, 0xfc, 0xa3, 0xe0, 0xd3, 0x9f, 0xec, 0x9e, 0x40, 0x09, 0x78, +0x62, 0xe6, 0x44, 0x02, 0xf6, 0x44, 0x08, 0xf6, 0x0b, 0x1a, 0xea, 0x70, 0x99, 0x22, 0xe4, 0xf5, +0x1c, 0x78, 0x1d, 0x7c, 0x00, 0xfd, 0x7b, 0xff, 0x7a, 0x39, 0x79, 0xf6, 0xfe, 0x7f, 0x02, 0x12, +0x0c, 0x68, 0x75, 0x22, 0x01, 0x75, 0x23, 0x00, 0x75, 0x24, 0xc4, 0x7b, 0x00, 0x7a, 0x00, 0x79, +0x1d, 0x12, 0x25, 0x87, 0xe5, 0x1d, 0xf4, 0x60, 0x14, 0x90, 0x00, 0xc4, 0x12, 0x31, 0xce, 0x40, +0x09, 0xd3, 0xef, 0x94, 0xb8, 0xee, 0x94, 0x0b, 0x40, 0x03, 0x75, 0x1c, 0x01, 0xe5, 0x1e, 0xf4, +0x60, 0x14, 0x90, 0x00, 0xc6, 0x12, 0x31, 0xce, 0x40, 0x09, 0xd3, 0xef, 0x94, 0xb8, 0xee, 0x94, +0x0b, 0x40, 0x03, 0x75, 0x1c, 0x01, 0x78, 0xb0, 0x7c, 0x01, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x00, +0x79, 0xc4, 0x7e, 0x00, 0x7f, 0x04, 0x12, 0x0c, 0x68, 0xaf, 0x1c, 0x22, 0x12, 0x04, 0xd6, 0x60, +0x11, 0xa8, 0x07, 0xe8, 0x24, 0x0b, 0xf8, 0xe2, 0x7f, 0x80, 0x60, 0x02, 0x7f, 0x08, 0x8f, 0x22, +0x80, 0x1e, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x0b, 0xf8, 0xe2, 0x60, 0x11, 0xa8, 0x07, 0xe8, 0x24, +0x0f, 0xf8, 0xe2, 0x7f, 0x04, 0x60, 0x02, 0x7f, 0x08, 0x8f, 0x22, 0x80, 0x03, 0xe4, 0xf5, 0x22, +0xe5, 0x22, 0xb4, 0x04, 0x0f, 0x12, 0x03, 0x64, 0x04, 0x12, 0x00, 0xe0, 0x78, 0x66, 0xe6, 0x24, +0x05, 0xf8, 0xe4, 0xf2, 0x78, 0x66, 0xe6, 0xff, 0x24, 0x06, 0xf8, 0xe5, 0x22, 0xf2, 0xef, 0x04, +0x12, 0x03, 0x6a, 0x24, 0x07, 0xf8, 0x7c, 0x00, 0x7d, 0xfe, 0x7e, 0x00, 0x7f, 0x06, 0x02, 0x0c, +0x68, 0xef, 0x54, 0x07, 0x90, 0x39, 0xee, 0x93, 0xfe, 0xf4, 0xf9, 0xef, 0x54, 0xf0, 0xff, 0x64, +0x10, 0x60, 0x11, 0xef, 0x13, 0x13, 0x54, 0x3f, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xfa, +0xab, 0x82, 0x80, 0x1a, 0xbd, 0x08, 0x02, 0x7d, 0x02, 0x7a, 0xff, 0x7b, 0x12, 0xed, 0x30, 0xe2, +0x05, 0x12, 0x35, 0xcd, 0x80, 0x03, 0x12, 0x35, 0xd5, 0xeb, 0x1b, 0x70, 0x01, 0x1a, 0xed, 0x30, +0xe1, 0x05, 0x12, 0x35, 0xcd, 0x80, 0x03, 0x12, 0x35, 0xd5, 0xeb, 0x1b, 0x70, 0x01, 0x1a, 0xed, +0x30, 0xe0, 0x04, 0x12, 0x35, 0xcd, 0x22, 0x12, 0x35, 0xd5, 0x22, 0x78, 0x63, 0xe6, 0xff, 0x78, +0x63, 0xe6, 0x60, 0x29, 0xe5, 0x89, 0x30, 0xe7, 0x08, 0x12, 0x14, 0x84, 0x50, 0x03, 0xe0, 0x04, +0xf0, 0x12, 0x16, 0x4e, 0x30, 0xe7, 0x08, 0x12, 0x14, 0x84, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x78, +0x63, 0xe6, 0x6f, 0x60, 0xda, 0xe6, 0xff, 0x12, 0x15, 0xe4, 0xf0, 0x80, 0xd2, 0xe4, 0xff, 0x78, +0x65, 0xe6, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x14, 0x12, 0x15, 0x7c, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, +0xef, 0x12, 0x14, 0xee, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x0f, 0x80, 0xe3, 0x22, 0x8f, 0x2d, 0xe4, +0xfd, 0x7f, 0x12, 0x12, 0x32, 0xcc, 0xaf, 0x2d, 0x15, 0x2d, 0xef, 0x60, 0x38, 0x75, 0xb1, 0x11, +0x75, 0xb4, 0x63, 0x75, 0xb0, 0x0d, 0xe5, 0xb1, 0x20, 0xe0, 0x22, 0xe5, 0x89, 0x30, 0xe7, 0x08, +0x12, 0x2b, 0x86, 0x50, 0x03, 0xe0, 0x04, 0xf0, 0x75, 0x91, 0xc1, 0xe4, 0xf5, 0x91, 0xe5, 0x89, +0x30, 0xe7, 0xe3, 0x12, 0x2b, 0x86, 0x50, 0xde, 0xe0, 0x04, 0xf0, 0x80, 0xd9, 0xe4, 0xf5, 0xb0, +0x75, 0xb1, 0x01, 0x80, 0xc1, 0x7d, 0x01, 0x7f, 0x12, 0x02, 0x32, 0xcc, 0x85, 0x0b, 0x82, 0x85, +0x0a, 0x83, 0x22, 0x75, 0x89, 0x80, 0x90, 0x00, 0xc3, 0xe0, 0xc3, 0x94, 0xff, 0x22, 0x75, 0x8a, +0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x43, 0x22, 0xe0, 0xfe, +0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x78, 0xee, 0x94, 0x00, 0x22, 0xe4, 0x93, 0xff, 0x7e, 0x00, 0x7c, +0x00, 0x02, 0x0d, 0x08, 0xe4, 0x78, 0x88, 0xf2, 0x08, 0xf2, 0x90, 0x00, 0xc8, 0xf0, 0x22, 0xab, +0x25, 0xaa, 0x26, 0xa9, 0x27, 0x22, 0x78, 0x4f, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0xad, 0x2f, 0xaf, +0x2e, 0xef, 0xc3, 0x94, 0x02, 0x50, 0x0e, 0xef, 0x25, 0xe0, 0x24, 0x68, 0xf8, 0xa6, 0x05, 0xef, +0x12, 0x01, 0xe3, 0x80, 0x24, 0xc3, 0x90, 0x00, 0xb6, 0xe0, 0x9b, 0x90, 0x00, 0xb5, 0xe0, 0x9a, +0x50, 0x06, 0x78, 0x68, 0xa6, 0x05, 0x80, 0x11, 0xc3, 0x90, 0x00, 0xb8, 0xe0, 0x9b, 0x90, 0x00, +0xb7, 0xe0, 0x9a, 0x50, 0x09, 0x78, 0x6a, 0xa6, 0x05, 0xea, 0xf0, 0xa3, 0xeb, 0xf0, 0x22, 0xc0, +0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, +0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x12, 0x16, 0x96, 0x12, +0x00, 0x0a, 0x7b, 0xff, 0x7a, 0x2e, 0x79, 0x7e, 0x12, 0x27, 0xf2, 0xd0, 0x07, 0xd0, 0x06, 0xd0, +0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, +0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x8f, 0x2a, 0x8d, 0x2b, 0xe5, 0x2b, 0x75, 0xf0, 0x2f, 0xa4, +0x24, 0x0a, 0x12, 0x00, 0xf3, 0xe5, 0x2a, 0x12, 0x05, 0x17, 0x12, 0x32, 0xbd, 0xc0, 0x06, 0xc0, +0x07, 0xe5, 0x2b, 0x75, 0xf0, 0x2f, 0xa4, 0x24, 0x08, 0x12, 0x00, 0xf3, 0xe5, 0x2a, 0x12, 0x05, +0xb8, 0x12, 0x32, 0xbd, 0xd0, 0xe0, 0x2f, 0xff, 0xd0, 0xe0, 0x3e, 0xfe, 0x22, 0xf8, 0xe2, 0xfc, +0x08, 0xe2, 0xc3, 0x9f, 0xff, 0xec, 0x9e, 0xfe, 0x12, 0x39, 0xa3, 0x22, 0x12, 0x35, 0xbd, 0x60, +0x3e, 0xee, 0x64, 0x01, 0x70, 0x18, 0xed, 0x60, 0x07, 0x78, 0x74, 0xe6, 0x4c, 0xf6, 0x80, 0x06, +0xec, 0xf4, 0x78, 0x74, 0x56, 0xf6, 0x78, 0x74, 0xe6, 0x90, 0xff, 0x18, 0xf0, 0x22, 0xaf, 0x06, +0xef, 0x75, 0xf0, 0x04, 0xa4, 0x24, 0x12, 0xff, 0xe5, 0xf0, 0x34, 0xff, 0x8f, 0x82, 0xf5, 0x83, +0xed, 0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22, 0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22, +0xc2, 0xd5, 0xe8, 0x30, 0xe7, 0x0f, 0xb2, 0xd5, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4, +0x99, 0xf9, 0xe4, 0x98, 0xf8, 0xec, 0x30, 0xe7, 0x17, 0xb2, 0xd5, 0x12, 0x33, 0x46, 0x12, 0x0f, +0x42, 0xe4, 0xc3, 0x9b, 0xfb, 0xe4, 0x9a, 0xfa, 0xe4, 0x99, 0xf9, 0xe4, 0x98, 0xf8, 0x80, 0x03, +0x12, 0x0f, 0x42, 0x30, 0xd5, 0x0d, 0xe4, 0xc3, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0xe4, 0x9d, 0xfd, +0xe4, 0x9c, 0xfc, 0x22, 0x12, 0x0c, 0xe6, 0xab, 0x1c, 0xe5, 0x1e, 0x24, 0x0c, 0xf9, 0xe4, 0x35, +0x1d, 0xfa, 0x7e, 0x00, 0xe9, 0x25, 0x25, 0xf9, 0xee, 0x3a, 0xfa, 0x12, 0x0c, 0x8e, 0xff, 0x22, +0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x90, 0x00, 0x0b, 0x12, 0x0c, 0xa7, 0xff, 0x22, 0x75, 0x8a, +0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x22, 0xab, 0x22, 0xaa, 0x23, 0xa9, 0x24, 0x85, 0x25, 0x82, +0x75, 0x83, 0x00, 0x22, 0x8c, 0x08, 0x8d, 0x09, 0x12, 0x39, 0x5a, 0x44, 0x18, 0x12, 0x39, 0x51, +0x90, 0xff, 0x14, 0xe0, 0x44, 0x18, 0xf0, 0x90, 0xff, 0x1b, 0xe0, 0x44, 0x18, 0xf0, 0x75, 0xa3, +0x08, 0xef, 0x44, 0x80, 0xf5, 0xa1, 0x75, 0xa6, 0x28, 0x75, 0xa2, 0xc1, 0xaf, 0x09, 0x85, 0x08, +0xd7, 0x8f, 0xd6, 0x75, 0xd5, 0x02, 0x75, 0xd4, 0xf8, 0x75, 0xd2, 0x01, 0x75, 0xd1, 0xdf, 0x53, +0xac, 0xef, 0x22, 0xc2, 0xaf, 0x12, 0x35, 0x07, 0xe5, 0x9b, 0xb4, 0x5a, 0x16, 0xe5, 0x9a, 0xb4, +0xa5, 0x11, 0xe5, 0x99, 0xb4, 0xf0, 0x0c, 0xe5, 0x98, 0xb4, 0x0f, 0x07, 0x90, 0xff, 0x85, 0xe0, +0x44, 0x20, 0xf0, 0x75, 0x8a, 0x0a, 0xd2, 0xaf, 0x7f, 0x0a, 0x12, 0x34, 0x46, 0x12, 0x39, 0x7a, +0x12, 0x10, 0xc4, 0x75, 0x8a, 0xa0, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x80, 0xf3, 0xad, 0x07, 0x7f, +0x3a, 0x12, 0x35, 0xdd, 0x90, 0x00, 0xc1, 0xe4, 0xf0, 0xa3, 0xef, 0xf0, 0x7f, 0x3b, 0x12, 0x35, +0xdd, 0xef, 0xfb, 0x7a, 0x00, 0x90, 0x00, 0xc2, 0xe0, 0xfe, 0xe4, 0x2b, 0xff, 0xea, 0x3e, 0x90, +0x00, 0xc1, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0xc1, 0xe0, 0xb4, 0x80, 0x08, 0xa3, 0xe0, 0xb4, +0x67, 0x03, 0xbd, 0xb6, 0xf1, 0x22, 0xe4, 0x90, 0x00, 0xc0, 0xf0, 0x90, 0x00, 0xc3, 0xf0, 0xef, +0x70, 0x0e, 0x75, 0x88, 0x08, 0xf5, 0x8d, 0xf5, 0x8c, 0xf5, 0x8f, 0xf5, 0x8e, 0xf5, 0x88, 0x22, +0x75, 0x88, 0x08, 0xe4, 0xf5, 0x8d, 0xf5, 0x8c, 0xef, 0x75, 0xf0, 0x20, 0xa4, 0xff, 0xe5, 0xf0, +0x44, 0x80, 0xf5, 0x8f, 0x8f, 0x8e, 0x75, 0x88, 0xa0, 0x22, 0xe4, 0xf5, 0x3c, 0xf5, 0x3d, 0xff, +0x12, 0x0c, 0x8e, 0x25, 0x3d, 0xf5, 0x3d, 0xe4, 0x35, 0x3c, 0xf5, 0x3c, 0x90, 0xff, 0xff, 0x12, +0x0c, 0xa7, 0x12, 0x0c, 0xd4, 0x74, 0xff, 0x29, 0xf9, 0x74, 0xff, 0x3a, 0xfa, 0x0f, 0xbf, 0x09, +0xdf, 0xed, 0x12, 0x0c, 0xd4, 0xae, 0x3c, 0xaf, 0x3d, 0x22, 0x12, 0x35, 0xbd, 0x60, 0x29, 0x90, +0xff, 0x13, 0xee, 0xd3, 0x94, 0x03, 0x40, 0x11, 0xaf, 0x06, 0xef, 0x75, 0xf0, 0x04, 0xa4, 0x25, +0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0xed, 0x60, 0x04, 0xe0, 0x4c, 0xf0, 0x22, +0xe0, 0xff, 0xec, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0x22, 0x85, 0x21, 0x82, 0x85, 0x20, 0x83, 0x22, +0xab, 0x1c, 0xaa, 0x1d, 0xa9, 0x1e, 0x12, 0x0d, 0xbb, 0xff, 0x22, 0xab, 0x1c, 0xaa, 0x1d, 0xa9, +0x1e, 0x90, 0x00, 0x02, 0x12, 0x0d, 0xe6, 0xff, 0x22, 0x93, 0xfd, 0xd3, 0x90, 0x00, 0xbe, 0xe0, +0x9d, 0x90, 0x00, 0xbd, 0xe0, 0x9c, 0x22, 0x75, 0x9b, 0x5a, 0x75, 0x9a, 0xa5, 0x75, 0x99, 0xf0, +0x75, 0x98, 0x0f, 0x75, 0xac, 0xff, 0x75, 0xad, 0xff, 0x90, 0xff, 0x88, 0x74, 0x40, 0xf0, 0x74, +0xc0, 0xf0, 0x90, 0xff, 0x01, 0x74, 0x01, 0xf0, 0x75, 0x95, 0xf1, 0xe4, 0xf5, 0x96, 0x75, 0x97, +0xc7, 0x22, 0xef, 0x60, 0x0f, 0x43, 0xac, 0x10, 0x12, 0x39, 0x5a, 0x54, 0xe7, 0x12, 0x39, 0x51, +0xe4, 0xf5, 0xa2, 0x22, 0x12, 0x39, 0x52, 0xa3, 0xe0, 0x44, 0x18, 0xf0, 0xa3, 0xe0, 0x54, 0xe7, +0xf0, 0x75, 0xa2, 0xc1, 0x53, 0xac, 0xef, 0x22, 0xc3, 0xef, 0x94, 0x01, 0xee, 0x64, 0x80, 0x94, +0x80, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x11, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x0a, +0xed, 0x24, 0xff, 0xff, 0xec, 0x34, 0xff, 0xfe, 0x80, 0x00, 0x22, 0xe4, 0x78, 0x6d, 0xf6, 0x8f, +0x82, 0x8e, 0x83, 0x74, 0x55, 0x93, 0x78, 0x67, 0xf6, 0xef, 0x24, 0x55, 0xf5, 0x0f, 0xe4, 0x3e, +0xf5, 0x0e, 0x78, 0x00, 0xe2, 0x54, 0xfe, 0xf2, 0x54, 0xfb, 0xf2, 0x22, 0xab, 0x1f, 0xaa, 0x20, +0xa9, 0x21, 0x90, 0x00, 0x01, 0x12, 0x0c, 0xa7, 0xff, 0x22, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, +0x58, 0xf0, 0xab, 0x1f, 0xaa, 0x20, 0xa9, 0x21, 0x12, 0x0c, 0x8e, 0xff, 0x22, 0xef, 0x54, 0x07, +0x90, 0x39, 0xee, 0x93, 0xfc, 0xef, 0xc4, 0x54, 0x0f, 0xfe, 0xef, 0xf4, 0x22, 0x8b, 0x82, 0x8a, +0x83, 0xe0, 0x4e, 0xf0, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe0, 0x59, 0xf0, 0x22, 0x90, 0xff, 0x00, +0x74, 0x02, 0xf0, 0x90, 0xff, 0x04, 0xe4, 0xf0, 0x90, 0xff, 0x03, 0xef, 0xf0, 0x90, 0xff, 0x07, +0xe0, 0xff, 0x22, 0x85, 0x1e, 0x82, 0x85, 0x1d, 0x83, 0x75, 0xf0, 0x07, 0xef, 0x02, 0x10, 0x59, +0xb6, 0x11, 0x01, 0x0a, 0x14, 0x01, 0x02, 0x05, 0x3c, 0x70, 0x00, 0x00, 0x15, 0x00, 0x02, 0x01, +0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, +0x00, 0x00, 0x03, 0x0a, 0x00, 0xc8, 0x03, 0xe8, 0x0f, 0x1e, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, +0x44, 0x41, 0x45, 0x51, 0x46, 0x52, 0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, +0x05, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, +0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, +0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, +0x00, 0xef, 0x00, 0xef, 0x00, 0x46, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, +0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, +0x00, 0x0a, 0x14, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, +0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45, +0x51, 0x46, 0x52, 0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28, +0xff, 0xff, 0xff, 0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, +0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, +0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00, +0xf0, 0x00, 0x46, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, +0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14, +0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03, +0x07, 0x06, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45, 0x51, 0x46, 0x52, +0x56, 0x53, 0x55, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, +0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28, 0xff, 0xff, 0xff, +0x64, 0x1e, 0x90, 0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09, +0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, +0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x46, +0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, +0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14, 0x02, 0x03, 0x07, +0x06, 0x01, 0x2c, 0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, +0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x05, 0x0a, 0x10, 0x3c, 0x01, 0x00, 0x50, 0x44, 0x41, 0x45, 0x51, 0x46, 0x52, 0x56, 0x53, 0x55, +0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, +0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x28, 0x05, 0x0b, 0x28, 0xff, 0xff, 0xff, 0x64, 0x1e, 0x90, +0x01, 0x00, 0x08, 0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, +0x00, 0x28, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, +0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x05, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x46, 0x00, 0x46, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, +0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x9c, 0x00, 0x0a, 0x14, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, +0x04, 0x00, 0x01, 0x08, 0x09, 0x01, 0x2c, 0x04, 0x02, 0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x02, +0x03, 0x07, 0x06, 0x01, 0x2c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0e, 0x10, +0x3c, 0x01, 0x00, 0x64, 0x10, 0x41, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x46, 0x45, 0x44, 0x43, +0x17, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, +0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa0, 0x22, 0x90, 0x00, 0x00, 0x08, +0x08, 0x85, 0x00, 0xc8, 0x00, 0x14, 0x02, 0x58, 0x09, 0x09, 0x85, 0x00, 0xc8, 0x00, 0x28, 0x02, +0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, 0x3c, 0x02, 0x58, 0x0a, 0x02, 0x85, 0x00, 0xc8, 0x00, +0x3c, 0x02, 0x58, 0x07, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x01, 0x2c, 0x05, 0x01, 0x0a, 0x01, 0x04, 0x00, 0x00, 0x00, +0x00, 0x02, 0x08, 0xfa, 0x00, 0x64, 0x14, 0x02, 0x03, 0x0b, 0x0a, 0x00, 0xc8, 0x04, 0x00, 0x01, +0x0c, 0x0d, 0x00, 0x96, 0x04, 0x02, 0x03, 0x0b, 0x0a, 0x00, 0xc8, 0x04, 0x02, 0x03, 0x0b, 0x0a, +0x00, 0xc8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xe4, 0x90, 0x00, 0xcd, 0xf0, +0x8f, 0x82, 0x8e, 0x83, 0x74, 0x23, 0x93, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x00, 0xcc, 0xf0, +0x22, 0xf0, 0x90, 0xff, 0x10, 0xe0, 0x54, 0xe7, 0xf0, 0x22, 0x90, 0xff, 0x12, 0xe0, 0x54, 0xe7, +0xf0, 0x90, 0xff, 0x11, 0xe0, 0x22, 0xef, 0x75, 0xf0, 0x0a, 0xa4, 0x24, 0x03, 0xf5, 0x82, 0xe4, +0x34, 0x02, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x22, 0x12, 0x2c, 0x4b, 0x78, 0x6f, 0x76, +0x00, 0x08, 0x76, 0x28, 0x90, 0x00, 0xc9, 0x74, 0x04, 0xf0, 0x22, 0x8d, 0x22, 0xaf, 0x22, 0x12, +0x24, 0x44, 0xaf, 0x22, 0x02, 0x16, 0xc9, 0xef, 0x25, 0xe0, 0x24, 0x5f, 0xf8, 0xe2, 0xfe, 0x08, +0xe2, 0xff, 0x22, 0xee, 0x30, 0xe7, 0x07, 0xc3, 0xe4, 0x9f, 0xff, 0xe4, 0x9e, 0xfe, 0x22, 0x12, +0x31, 0xac, 0x74, 0x78, 0x93, 0xfd, 0x02, 0x05, 0xfc, 0x7f, 0x30, 0x12, 0x35, 0xdd, 0x22, 0x41, +0x00, 0xc8, 0x00, 0x00, 0x78, 0x61, 0xa6, 0x07, 0x22, 0x12, 0x39, 0x66, 0x22, 0x7f, 0x00, 0x22, +0x11, 0x10, 0x41, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x46, 0x45, 0x44, 0x43, 0x17, 0x16, 0x11, +0x40, 0x41, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x46, 0x45, 0x44, 0x43, 0x42, 0x16, 0x01, 0x02, +0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xb6, 0x02, 0x30, 0x21, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x56, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/cst92xx_fw.h b/drivers/input/touchscreen/hyn/hyn_chips/cst92xx_fw.h new file mode 100644 index 000000000000..0dba256b9e1b --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/cst92xx_fw.h @@ -0,0 +1,2063 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/cst92xx_fw.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_FIRMWARE_H +#define HYNITRON_FIRMWARE_H + +static const uint8_t fw_bin[] = { + 0xFC,0x0F,0x00,0x20,0x01,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xB9,0x33,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF9,0x33,0x00,0x00, + 0x49,0x24,0x00,0x00,0x75,0x6D,0x00,0x00,0x95,0x33,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x70,0xB5,0x05,0x46,0x0C,0x46,0x16,0x46,0x02,0xE0,0x0F,0xCC,0x0F,0xC5,0x10,0x3E, + 0x10,0x2E,0xFA,0xD2,0x08,0x2E,0x02,0xD3,0x03,0xCC,0x03,0xC5,0x08,0x3E,0x04,0x2E, + 0x07,0xD3,0x01,0xCC,0x01,0xC5,0x36,0x1F,0x03,0xE0,0x21,0x78,0x29,0x70,0x64,0x1C, + 0x6D,0x1C,0x76,0x1E,0xF9,0xD2,0x70,0xBD,0xF8,0xB5,0x04,0x2A,0x2C,0xD3,0x83,0x07, + 0x12,0xD0,0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x83,0x07,0x0B,0xD0, + 0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x83,0x07,0x04,0xD0,0x0B,0x78, + 0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0x8B,0x07,0x9B,0x0F,0x05,0xD0,0xC9,0x1A, + 0xDF,0x00,0x20,0x23,0xDE,0x1B,0x08,0xC9,0x0A,0xE0,0xFF,0xF7,0xC1,0xFF,0xF8,0xBD, + 0x1D,0x46,0x08,0xC9,0xFD,0x40,0x1C,0x46,0xB4,0x40,0x2C,0x43,0x10,0xC0,0x12,0x1F, + 0x04,0x2A,0xF5,0xD2,0xF3,0x08,0xC9,0x1A,0x52,0x1E,0xF0,0xD4,0x0B,0x78,0x49,0x1C, + 0x03,0x70,0x40,0x1C,0x52,0x1E,0xEA,0xD4,0x0B,0x78,0x49,0x1C,0x03,0x70,0x40,0x1C, + 0x52,0x1E,0xE4,0xD4,0x09,0x78,0x01,0x70,0xF8,0xBD,0xD2,0xB2,0x10,0xB5,0x13,0x02, + 0x9A,0x18,0x13,0x04,0x9A,0x18,0x00,0xF0,0x0E,0xF8,0x10,0xBD,0x01,0xE0,0x04,0xC0, + 0x09,0x1F,0x04,0x29,0xFB,0xD2,0x8B,0x07,0x01,0xD5,0x02,0x80,0x80,0x1C,0xC9,0x07, + 0x00,0xD0,0x02,0x70,0x70,0x47,0x00,0x29,0x0B,0xD0,0xC3,0x07,0x02,0xD0,0x02,0x70, + 0x40,0x1C,0x49,0x1E,0x02,0x29,0x04,0xD3,0x83,0x07,0x02,0xD5,0x02,0x80,0x80,0x1C, + 0x89,0x1E,0xE3,0xE7,0x00,0x22,0xEE,0xE7,0x00,0x22,0xDF,0xE7,0x00,0x22,0x03,0x09, + 0x8B,0x42,0x2C,0xD3,0x03,0x0A,0x8B,0x42,0x11,0xD3,0x00,0x23,0x9C,0x46,0x4E,0xE0, + 0x03,0x46,0x0B,0x43,0x3C,0xD4,0x00,0x22,0x43,0x08,0x8B,0x42,0x31,0xD3,0x03,0x09, + 0x8B,0x42,0x1C,0xD3,0x03,0x0A,0x8B,0x42,0x01,0xD3,0x94,0x46,0x3F,0xE0,0xC3,0x09, + 0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41,0x83,0x09,0x8B,0x42,0x01,0xD3, + 0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42,0x01,0xD3,0x4B,0x01,0xC0,0x1A, + 0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01,0xC0,0x1A,0x52,0x41,0xC3,0x08, + 0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41,0x83,0x08,0x8B,0x42,0x01,0xD3, + 0x8B,0x00,0xC0,0x1A,0x52,0x41,0x43,0x08,0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A, + 0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46,0x52,0x41,0x10,0x46,0x70,0x47,0x5D,0xE0, + 0xCA,0x0F,0x00,0xD0,0x49,0x42,0x03,0x10,0x00,0xD3,0x40,0x42,0x53,0x40,0x00,0x22, + 0x9C,0x46,0x03,0x09,0x8B,0x42,0x2D,0xD3,0x03,0x0A,0x8B,0x42,0x12,0xD3,0xFC,0x22, + 0x89,0x01,0x12,0xBA,0x03,0x0A,0x8B,0x42,0x0C,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42, + 0x08,0xD3,0x89,0x01,0x92,0x11,0x8B,0x42,0x04,0xD3,0x89,0x01,0x3A,0xD0,0x92,0x11, + 0x00,0xE0,0x89,0x09,0xC3,0x09,0x8B,0x42,0x01,0xD3,0xCB,0x01,0xC0,0x1A,0x52,0x41, + 0x83,0x09,0x8B,0x42,0x01,0xD3,0x8B,0x01,0xC0,0x1A,0x52,0x41,0x43,0x09,0x8B,0x42, + 0x01,0xD3,0x4B,0x01,0xC0,0x1A,0x52,0x41,0x03,0x09,0x8B,0x42,0x01,0xD3,0x0B,0x01, + 0xC0,0x1A,0x52,0x41,0xC3,0x08,0x8B,0x42,0x01,0xD3,0xCB,0x00,0xC0,0x1A,0x52,0x41, + 0x83,0x08,0x8B,0x42,0x01,0xD3,0x8B,0x00,0xC0,0x1A,0x52,0x41,0xD9,0xD2,0x43,0x08, + 0x8B,0x42,0x01,0xD3,0x4B,0x00,0xC0,0x1A,0x52,0x41,0x41,0x1A,0x00,0xD2,0x01,0x46, + 0x63,0x46,0x52,0x41,0x5B,0x10,0x10,0x46,0x01,0xD3,0x40,0x42,0x00,0x2B,0x00,0xD5, + 0x49,0x42,0x70,0x47,0x63,0x46,0x5B,0x10,0x00,0xD3,0x40,0x42,0x01,0xB5,0x00,0x20, + 0xC0,0x46,0xC0,0x46,0x02,0xBD,0x00,0x00,0xFF,0xB5,0x84,0xB0,0x0D,0x9E,0x0E,0x9C, + 0x1D,0x46,0x17,0x46,0x00,0x20,0x2D,0x49,0x03,0x90,0x0A,0x78,0x90,0x42,0x52,0xDA, + 0x00,0x20,0x03,0xE0,0x43,0x00,0x2A,0x4A,0xE2,0x52,0x40,0x1C,0x0A,0x78,0x90,0x42, + 0xF8,0xDB,0x0A,0x22,0x00,0x21,0x05,0x98,0x03,0xF0,0x30,0xF9,0x0A,0x22,0x00,0x21, + 0x38,0x46,0x03,0xF0,0x2B,0xF9,0x01,0x96,0x00,0x95,0x02,0x94,0x03,0xA8,0x07,0xC8, + 0x3B,0x46,0x02,0xF0,0x15,0xFC,0x00,0x28,0x02,0xD0,0x03,0x98,0x40,0x1C,0xDA,0xE7, + 0x1A,0x4A,0x1B,0x48,0x00,0x21,0x13,0x78,0x08,0xE0,0x7A,0x5C,0x00,0x2A,0x04,0xD1, + 0x4A,0x00,0xA2,0x5E,0x82,0x42,0x00,0xDA,0x10,0x46,0x49,0x1C,0x99,0x42,0xF4,0xDB, + 0x00,0x21,0x08,0xE0,0x05,0x9A,0x52,0x5C,0x00,0x2A,0x03,0xD0,0x4A,0x00,0xAB,0x5A, + 0x1B,0x1A,0xAB,0x52,0x49,0x1C,0x0D,0x4A,0x13,0x78,0x99,0x42,0xF2,0xDB,0x00,0x21, + 0x0C,0xE0,0x7A,0x5C,0x00,0x2A,0x04,0xD0,0x4A,0x00,0xB3,0x5A,0x1B,0x18,0xB3,0x52, + 0x03,0xE0,0x4A,0x00,0xA3,0x5A,0x1B,0x1A,0xA3,0x52,0x49,0x1C,0x03,0x4A,0x12,0x78, + 0x91,0x42,0xB6,0xDA,0xED,0xE7,0x08,0xB0,0xF0,0xBD,0x00,0x00,0x3C,0x00,0x00,0x20, + 0xFF,0x7F,0x00,0x00,0xC2,0x06,0xD2,0x0E,0x01,0x21,0x91,0x40,0x40,0x09,0x02,0x4A, + 0x80,0x00,0x80,0x18,0x01,0x60,0x70,0x47,0x00,0xE1,0x00,0xE0,0x83,0x07,0xFF,0x22, + 0xDB,0x0E,0x9A,0x40,0x89,0x07,0x09,0x0E,0x99,0x40,0x00,0x28,0x0B,0xDA,0x00,0x07, + 0x00,0x0F,0x08,0x38,0x83,0x08,0x08,0x48,0x9B,0x00,0x18,0x18,0xC3,0x69,0x93,0x43, + 0x0B,0x43,0xC3,0x61,0x70,0x47,0x83,0x08,0x04,0x48,0x9B,0x00,0x18,0x18,0x03,0x68, + 0x93,0x43,0x0B,0x43,0x03,0x60,0x70,0x47,0x00,0xED,0x00,0xE0,0x00,0xE4,0x00,0xE0, + 0x10,0xB5,0x04,0xF0,0x73,0xFA,0x10,0xBD,0x30,0xB4,0x74,0x46,0x64,0x1E,0x25,0x78, + 0x64,0x1C,0xAB,0x42,0x00,0xD2,0x1D,0x46,0x63,0x5D,0x5B,0x00,0xE3,0x18,0x30,0xBC, + 0x18,0x47,0x00,0x00,0xFF,0xB5,0x14,0x22,0x50,0x43,0x4A,0x4A,0x81,0xB0,0x84,0x18, + 0x49,0x48,0x0A,0x9E,0x40,0x68,0x1D,0x46,0x82,0x69,0x0B,0x99,0x92,0x57,0x00,0x92, + 0x42,0x69,0x02,0x29,0x57,0x57,0x27,0xD0,0x63,0x7C,0x29,0x07,0x1A,0x07,0x12,0x0F, + 0x09,0x0F,0xAA,0x42,0x03,0xD9,0x1A,0x09,0x12,0x01,0x0A,0x43,0x62,0x74,0x62,0x7C, + 0x13,0x09,0xAB,0x42,0x04,0xD2,0x12,0x07,0x12,0x0F,0x09,0x01,0x0A,0x43,0x62,0x74, + 0xA3,0x7C,0x31,0x07,0x1A,0x07,0x12,0x0F,0x09,0x0F,0xB2,0x42,0x03,0xD9,0x1A,0x09, + 0x12,0x01,0x0A,0x43,0xA2,0x74,0xA2,0x7C,0x13,0x09,0xB3,0x42,0x04,0xD2,0x12,0x07, + 0x12,0x0F,0x09,0x01,0x0A,0x43,0xA2,0x74,0x01,0x7B,0x00,0x29,0x27,0xD0,0x00,0x2D, + 0x37,0xD0,0x81,0x7F,0x4A,0x1E,0xAA,0x42,0x0B,0xD1,0xC0,0x7F,0x89,0x1E,0x41,0x43, + 0x88,0x19,0x41,0x00,0x03,0x98,0x3A,0x46,0x41,0x5E,0x02,0x98,0x00,0xF0,0x18,0xFD, + 0x07,0x46,0x25,0x48,0x00,0x2E,0x40,0x68,0xC0,0x7F,0x25,0xD0,0x41,0x1E,0xB1,0x42, + 0x0D,0xD1,0x01,0x46,0x69,0x43,0x08,0x18,0x41,0x00,0x03,0x98,0x08,0x18,0x40,0x38, + 0x3C,0x21,0x41,0x5E,0x00,0x9A,0x02,0x98,0x00,0xF0,0x02,0xFD,0x00,0x90,0x21,0x68, + 0x02,0x98,0x08,0x18,0x20,0x60,0x18,0x48,0x40,0x68,0x81,0x69,0x00,0x29,0x12,0xD0, + 0x00,0x99,0xF2,0x01,0x51,0x18,0x02,0x9A,0x63,0x68,0x51,0x43,0xC9,0x11,0x59,0x18, + 0x0D,0xE0,0xC0,0x7F,0x80,0x19,0xCC,0xE7,0x68,0x43,0x41,0x00,0x03,0x98,0x08,0x18, + 0x02,0x21,0x41,0x5E,0xDE,0xE7,0x02,0x99,0x62,0x68,0x71,0x43,0x51,0x18,0x61,0x60, + 0x40,0x69,0x00,0x28,0x07,0xD0,0xE8,0x01,0x02,0x99,0xC0,0x19,0xA2,0x68,0x48,0x43, + 0xC0,0x11,0x10,0x18,0x03,0xE0,0x02,0x98,0xA1,0x68,0x68,0x43,0x08,0x18,0xA0,0x60, + 0x05,0xB0,0xF0,0xBD,0xE0,0x0A,0x00,0x20,0x30,0x00,0x00,0x20,0xFF,0xB5,0x82,0xB0, + 0x00,0x21,0x0B,0x98,0x41,0x4A,0x01,0x91,0x51,0x68,0x03,0x9C,0xC9,0x7F,0x56,0x78, + 0x61,0x43,0x04,0x9C,0x09,0x19,0x89,0xB2,0x8C,0x46,0x4C,0x00,0x02,0x99,0x14,0x2E, + 0x0C,0x5F,0x03,0xD3,0x00,0x20,0xC0,0x43,0x06,0xB0,0xF0,0xBD,0x00,0x21,0x3B,0xE0, + 0x0E,0x22,0x0D,0x46,0x55,0x43,0x36,0x4A,0xAE,0x46,0xAA,0x18,0x95,0x7A,0x00,0x95, + 0x2F,0x07,0x3F,0x0F,0x83,0x42,0x01,0xD2,0x1D,0x46,0x00,0xE0,0x05,0x46,0xAF,0x42, + 0x28,0xD1,0x00,0x9D,0x2F,0x09,0x83,0x42,0x01,0xD9,0x1D,0x46,0x00,0xE0,0x05,0x46, + 0xAF,0x42,0x1F,0xD1,0x0E,0x20,0x41,0x43,0x29,0x48,0x08,0x18,0x40,0x88,0x41,0x00, + 0x02,0x98,0x40,0x5E,0xA0,0x42,0x01,0xDA,0x60,0x46,0x50,0x80,0x24,0x4B,0x70,0x46, + 0x18,0x5A,0x71,0x46,0x40,0x1C,0x58,0x52,0x04,0x98,0x91,0x88,0x60,0x43,0x08,0x18, + 0x90,0x80,0x03,0x98,0xD1,0x88,0x60,0x43,0x08,0x18,0xD0,0x80,0x10,0x89,0x00,0x19, + 0x10,0x81,0x30,0xE0,0x49,0x1C,0xC9,0xB2,0xB1,0x42,0xC1,0xD3,0x01,0x99,0x00,0x29, + 0x29,0xD1,0x31,0x46,0x0E,0x22,0x51,0x43,0x15,0x4A,0x01,0x25,0x55,0x52,0x89,0x18, + 0x8A,0x7A,0x12,0x4F,0x12,0x09,0x12,0x01,0x83,0x42,0x01,0xD2,0x1D,0x46,0x00,0xE0, + 0x05,0x46,0x2D,0x07,0x2D,0x0F,0x2A,0x43,0x8A,0x72,0x12,0x07,0x12,0x0F,0x3D,0x46, + 0x83,0x42,0x00,0xD9,0x18,0x46,0x00,0x01,0x02,0x43,0x8A,0x72,0x60,0x46,0x48,0x80, + 0x04,0x9A,0x20,0x46,0x50,0x43,0x88,0x80,0x03,0x9A,0x20,0x46,0x50,0x43,0xC8,0x80, + 0x0C,0x81,0x76,0x1C,0x6E,0x70,0x00,0x20,0x8E,0xE7,0x00,0x00,0x30,0x00,0x00,0x20, + 0xA8,0x0B,0x00,0x20,0x70,0xB5,0x20,0x48,0x1F,0x4C,0xC0,0x6B,0x80,0x3C,0x01,0x78, + 0x00,0x20,0x20,0x74,0x22,0x46,0x21,0x70,0xE0,0x32,0xD0,0x8A,0x28,0x28,0x02,0xD8, + 0x13,0x79,0x00,0x2B,0x07,0xD0,0xC8,0x28,0x00,0xD9,0xC8,0x20,0x01,0x23,0xC0,0x08, + 0x23,0x74,0x40,0x18,0x20,0x70,0x20,0x7C,0x23,0x46,0x40,0x1C,0x60,0x74,0xA1,0x6B, + 0x10,0x7A,0x08,0x70,0xA1,0x6B,0x50,0x7A,0x48,0x70,0x00,0x20,0xC0,0x33,0x51,0x7A, + 0xD5,0x79,0x69,0x43,0x49,0x00,0x45,0x00,0x49,0x19,0x9D,0x6B,0x69,0x5A,0x49,0x08, + 0xFF,0x29,0x00,0xDD,0xFF,0x21,0x85,0x1C,0xA6,0x6B,0x40,0x1C,0x40,0xB2,0x71,0x55, + 0x02,0x28,0xEC,0xDB,0xE1,0x6B,0x58,0x7E,0x08,0x70,0xE1,0x6B,0x18,0x7E,0x48,0x70, + 0xE1,0x6B,0x10,0x79,0x88,0x70,0x70,0xBD,0xC4,0x00,0x00,0x20,0xFF,0xB5,0x05,0x46, + 0x06,0x46,0x04,0x46,0x00,0x8A,0xA9,0x8B,0x10,0x36,0x40,0x1A,0x71,0x88,0xEA,0x8B, + 0x40,0x43,0x89,0x1A,0x49,0x43,0x1F,0x46,0x2C,0x34,0x40,0x18,0x06,0xF0,0x82,0xFB, + 0x61,0x89,0x08,0x18,0xC0,0x03,0x00,0x0C,0x60,0x81,0x01,0x99,0x88,0x42,0x04,0xDD, + 0x08,0x20,0x20,0x5E,0x7F,0x1C,0xC0,0x19,0x30,0xE0,0x02,0x99,0x88,0x42,0x11,0xDD, + 0x09,0x98,0x38,0x18,0x42,0x08,0x08,0x20,0x20,0x5E,0x11,0x1A,0x10,0x31,0x20,0x29, + 0x01,0xD9,0x08,0x21,0x00,0xE0,0x04,0x21,0x90,0x42,0x01,0xDD,0x40,0x1A,0x1E,0xE0, + 0x40,0x18,0x1C,0xE0,0xB0,0x88,0xA9,0x8B,0xEA,0x8B,0x40,0x1A,0xF1,0x88,0x40,0x43, + 0x89,0x1A,0x49,0x43,0x40,0x18,0x06,0xF0,0x55,0xFB,0x09,0x99,0xBA,0x08,0x51,0x18, + 0xC9,0xB2,0x80,0x28,0x05,0xDD,0x08,0x20,0x20,0x5E,0x80,0x28,0x01,0xDA,0x40,0x1C, + 0x05,0xE0,0x08,0x20,0x20,0x5E,0x88,0x42,0x03,0xDD,0x40,0x18,0x40,0x10,0x20,0x81, + 0x04,0xE0,0x09,0x99,0x88,0x42,0x01,0xDD,0x40,0x1E,0xF8,0xE7,0x08,0x20,0x20,0x5E, + 0x80,0x21,0x08,0x1A,0x04,0xB0,0xF0,0xBD,0xF0,0xB5,0x23,0x4E,0x04,0x46,0x35,0x68, + 0x85,0xB0,0x28,0x7A,0xFF,0x21,0x40,0x00,0x03,0x90,0x68,0x7A,0x81,0x31,0x48,0x43, + 0x00,0x0A,0x02,0x90,0xE8,0x7A,0x64,0x21,0xC0,0x01,0xFF,0xF7,0xCF,0xFC,0xC7,0xB2, + 0xA8,0x7A,0xFF,0x21,0x02,0x46,0x14,0x32,0x50,0x43,0x78,0x31,0xFF,0xF7,0xD0,0xFC, + 0xC5,0xB2,0x2A,0x46,0x39,0x46,0x20,0x46,0x00,0xF0,0x28,0xF8,0xA0,0x78,0x03,0x28, + 0x05,0xD2,0x20,0x8A,0x69,0x46,0x88,0x80,0x60,0x8A,0xC8,0x80,0x12,0xE0,0x3B,0x46, + 0x00,0x95,0x20,0x46,0x02,0x9A,0x03,0x99,0xFF,0xF7,0x70,0xFF,0x01,0x46,0x30,0x68, + 0x01,0xAA,0x00,0x7B,0x00,0x28,0x20,0x46,0x02,0xD0,0x00,0xF0,0xB9,0xF8,0x01,0xE0, + 0x00,0xF0,0x39,0xF8,0x69,0x46,0x88,0x88,0x20,0x84,0xC9,0x88,0x61,0x84,0x20,0x82, + 0x61,0x82,0x01,0x98,0x05,0xB0,0xF0,0xBD,0x38,0x00,0x00,0x20,0xF0,0xB5,0x05,0x46, + 0x10,0x35,0x04,0x46,0x2C,0x34,0x02,0x22,0x93,0x00,0x5B,0x19,0x1E,0x1F,0x37,0x88, + 0x1F,0x80,0x52,0x1E,0x76,0x88,0x52,0xB2,0x5E,0x80,0x00,0x2A,0xF4,0xDC,0x82,0x89, + 0x2A,0x80,0xC3,0x89,0x6B,0x80,0x80,0x78,0x03,0x28,0x13,0xD2,0x02,0x28,0x11,0xD1, + 0xA8,0x88,0x10,0x1A,0x00,0xB2,0x20,0x80,0x6A,0x88,0xEB,0x88,0xD2,0x1A,0x12,0xB2, + 0x62,0x80,0xA0,0x80,0xE2,0x80,0x40,0x43,0x52,0x43,0x21,0x81,0x80,0x18,0x06,0xF0, + 0xC1,0xFA,0x60,0x81,0xF0,0xBD,0xF7,0xB5,0x86,0xB0,0x02,0x46,0x83,0x8C,0x6C,0x46, + 0x23,0x80,0xC0,0x8C,0x60,0x80,0x14,0x46,0x15,0x46,0x92,0x8D,0x05,0x92,0x9A,0x18, + 0x2C,0x34,0x04,0x23,0xE3,0x5E,0x01,0x26,0x5B,0x10,0xD2,0x18,0x17,0xB2,0x62,0x88, + 0xBC,0x46,0x80,0x18,0x06,0x22,0xA2,0x5E,0xB6,0x02,0x52,0x10,0x80,0x18,0x02,0xB2, + 0x08,0x01,0x01,0x92,0x02,0x46,0x4A,0x43,0xD3,0x11,0x59,0x43,0x49,0x12,0x4A,0x00, + 0x59,0x00,0x89,0x10,0x8B,0x1A,0x40,0x00,0x80,0x10,0x1F,0x1A,0xBE,0x19,0x67,0x46, + 0x00,0x96,0x7E,0x43,0x49,0x00,0x01,0x27,0x49,0x42,0xFF,0x02,0xC9,0x19,0x10,0x35, + 0x04,0x91,0x2F,0x88,0x1B,0x18,0x79,0x43,0x01,0x20,0xC0,0x02,0x1F,0x18,0xAB,0x88, + 0x38,0x46,0x58,0x43,0x89,0x19,0x41,0x18,0x01,0x20,0x03,0x93,0x52,0x00,0x80,0x02, + 0x2B,0x89,0x10,0x18,0x43,0x43,0x02,0x90,0x58,0x18,0x03,0x21,0xC9,0x02,0x8A,0x10, + 0x80,0x18,0xFF,0xF7,0x25,0xFC,0x06,0x46,0x01,0x9A,0x00,0x98,0x04,0x99,0x50,0x43, + 0x6A,0x88,0x51,0x43,0x08,0x18,0xE9,0x88,0x6A,0x89,0x4F,0x43,0x39,0x18,0x02,0x98, + 0x42,0x43,0x50,0x18,0x03,0x21,0xC9,0x02,0x8A,0x10,0x80,0x18,0xFF,0xF7,0x10,0xFC, + 0x03,0x9B,0x05,0x9A,0xF1,0x1A,0x8A,0x1A,0xA2,0x80,0x21,0x80,0x00,0x2E,0x00,0xDA, + 0x00,0x26,0x08,0x99,0x0E,0x80,0xE9,0x88,0x62,0x88,0x41,0x1A,0x8A,0x1A,0xE2,0x80, + 0x61,0x80,0x00,0x28,0x00,0xDA,0x00,0x20,0x08,0x99,0x48,0x80,0x09,0xB0,0xF0,0xBD, + 0xF7,0xB5,0x86,0xB0,0x85,0x8C,0x6B,0x46,0x02,0x46,0x1D,0x80,0xC0,0x8C,0x58,0x80, + 0x93,0x8D,0x05,0x93,0xEB,0x18,0x30,0x25,0x55,0x5F,0x14,0x46,0x6D,0x10,0x5B,0x19, + 0x1B,0xB2,0x9C,0x46,0xD3,0x8D,0x15,0x46,0xC0,0x18,0x32,0x23,0xD3,0x5E,0x10,0x35, + 0x5B,0x10,0xC0,0x18,0x00,0xB2,0x01,0x90,0x08,0x01,0x02,0x46,0x4A,0x43,0xD2,0x11, + 0x51,0x43,0x4E,0x12,0x91,0x00,0x51,0x18,0x82,0x00,0x80,0x18,0x72,0x00,0x89,0x10, + 0x52,0x42,0x52,0x18,0x80,0x10,0x17,0x1A,0x01,0x23,0x9B,0x02,0xFF,0x18,0x63,0x46, + 0x00,0x97,0x5F,0x43,0x73,0x00,0xF3,0x18,0x49,0x00,0x5B,0x1A,0x01,0x21,0x09,0x03, + 0x59,0x18,0x04,0x91,0x2B,0x88,0x12,0x18,0x59,0x43,0xCB,0x19,0x01,0x20,0xA9,0x88, + 0x80,0x02,0x10,0x18,0x03,0x91,0x02,0x90,0x41,0x43,0xC8,0x18,0x29,0x89,0x2C,0x34, + 0x71,0x43,0x08,0x18,0x03,0x21,0xC9,0x02,0x8A,0x10,0x80,0x18,0xFF,0xF7,0xA8,0xFB, + 0x07,0x46,0x00,0x9A,0x01,0x98,0x04,0x99,0x42,0x43,0x68,0x88,0x41,0x43,0x89,0x18, + 0xEA,0x88,0x02,0x98,0x42,0x43,0x50,0x18,0x69,0x89,0x71,0x43,0x08,0x18,0x03,0x21, + 0xC9,0x02,0x8A,0x10,0x80,0x18,0xFF,0xF7,0x93,0xFB,0x03,0x99,0x05,0x9B,0x79,0x1A, + 0xCA,0x1A,0xA2,0x80,0x21,0x80,0x00,0x2F,0x00,0xDA,0x00,0x27,0x08,0x99,0x0F,0x80, + 0xE9,0x88,0x62,0x88,0x41,0x1A,0x8A,0x1A,0xE2,0x80,0x61,0x80,0x00,0x28,0x00,0xDA, + 0x00,0x20,0x08,0x99,0x48,0x80,0x09,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0xB5,0x87,0xB0, + 0x00,0x26,0x30,0x46,0x11,0x9A,0x0C,0xE0,0x38,0x21,0x08,0x9B,0x41,0x43,0xC9,0x18, + 0x89,0x78,0x00,0x29,0x03,0xD0,0x10,0x99,0x88,0x55,0x76,0x1C,0xF6,0xB2,0x40,0x1C, + 0xC0,0xB2,0x90,0x42,0xF0,0xD3,0x12,0x98,0x00,0x2E,0x06,0x70,0x08,0xD0,0x0A,0x98, + 0x00,0x28,0x05,0xD0,0xB0,0x42,0x00,0xD8,0x30,0x46,0x00,0x24,0x01,0x90,0x5E,0xE0, + 0x00,0x20,0x0B,0xB0,0xF0,0xBD,0x00,0x25,0x54,0xE0,0xB4,0x42,0x47,0xD2,0x0A,0x98, + 0x85,0x42,0x44,0xD2,0x09,0x98,0xE9,0x00,0x09,0x18,0x08,0x22,0x02,0xA8,0xFF,0xF7, + 0xD3,0xFA,0x68,0x46,0x43,0x89,0x02,0x89,0x10,0x98,0x38,0x21,0x00,0x5D,0x48,0x43, + 0x08,0x99,0x40,0x18,0xC1,0x8C,0x80,0x8C,0x01,0xF0,0xD8,0xFD,0x00,0x90,0x10,0x98, + 0x38,0x21,0x00,0x5D,0x48,0x43,0x08,0x99,0x40,0x18,0x81,0x78,0x02,0x29,0x28,0xD3, + 0x1E,0x4F,0x39,0x68,0x49,0x69,0x00,0x29,0x23,0xD0,0xC3,0x89,0x82,0x89,0xC1,0x8C, + 0x80,0x8C,0x01,0xF0,0xC3,0xFD,0x05,0x90,0x68,0x46,0x43,0x89,0x02,0x89,0x10,0x98, + 0x38,0x21,0x00,0x5D,0x48,0x43,0x08,0x99,0x40,0x18,0xC1,0x89,0x80,0x89,0x01,0xF0, + 0xB5,0xFD,0x04,0x90,0x38,0x68,0x00,0x9A,0x47,0x69,0x13,0x9B,0x04,0x99,0x05,0x98, + 0xB8,0x47,0x00,0x28,0x05,0xD1,0x13,0x99,0x04,0x98,0x88,0x42,0x01,0xDB,0x0C,0x48, + 0x00,0xE0,0x00,0x98,0x01,0x99,0x61,0x43,0x49,0x19,0x4A,0x00,0x07,0x99,0x6D,0x1C, + 0x88,0x52,0xED,0xB2,0x01,0x98,0x85,0x42,0xA7,0xD3,0x64,0x1C,0xE4,0xB2,0x84,0x42, + 0xA1,0xD3,0x12,0x98,0x06,0x70,0x01,0x98,0x9B,0xE7,0x00,0x00,0x38,0x00,0x00,0x20, + 0xFF,0x7F,0x00,0x00,0xFE,0xB5,0x4D,0x48,0x54,0x22,0xC0,0x6B,0x00,0x21,0x80,0x79, + 0x01,0x90,0x4B,0x48,0x02,0xF0,0x12,0xFC,0x00,0x25,0x06,0x20,0x48,0x4A,0x00,0x21, + 0x68,0x43,0x84,0x18,0x00,0x20,0x4B,0x00,0x46,0x4A,0x12,0x5C,0x16,0x09,0x8E,0x42, + 0x06,0xD1,0x17,0x07,0xE6,0x5C,0x3F,0x0F,0x01,0x22,0xBA,0x40,0x16,0x43,0xE6,0x54, + 0x40,0x1C,0x08,0x28,0xF0,0xD3,0x49,0x1C,0x03,0x29,0xEB,0xD3,0x6D,0x1C,0x0C,0x2D, + 0xE3,0xD3,0x3A,0x49,0x00,0x24,0xA0,0x31,0xCC,0x74,0x08,0x46,0x8C,0x74,0x20,0x38, + 0x00,0x90,0x00,0x23,0x37,0x4A,0xE5,0x18,0x52,0x5D,0x00,0x20,0x96,0x46,0x12,0x09, + 0x94,0x46,0x84,0x45,0x27,0xD1,0x72,0x46,0x15,0x07,0x2D,0x0F,0x01,0x22,0xAA,0x40, + 0x00,0x9D,0x8E,0x7C,0xAD,0x6A,0xB6,0x00,0xF6,0x18,0xAD,0x57,0x01,0x2D,0x02,0xD0, + 0x6D,0x1C,0x0B,0xD0,0x17,0xE0,0xCE,0x7C,0x06,0x25,0x6E,0x43,0x28,0x4D,0x76,0x19, + 0x45,0x00,0x77,0x5D,0x97,0x43,0x77,0x55,0x75,0x19,0x09,0xE0,0xCE,0x7C,0x06,0x25, + 0x6E,0x43,0x23,0x4D,0x75,0x19,0x46,0x00,0xAF,0x5D,0x17,0x43,0xAF,0x55,0xAD,0x19, + 0x6E,0x78,0x16,0x43,0x6E,0x70,0x40,0x1C,0x03,0x28,0xD2,0xD3,0x5B,0x1C,0x04,0x2B, + 0xC8,0xD3,0xC8,0x7C,0x40,0x1C,0xC8,0x74,0x88,0x7C,0x40,0x1C,0xC0,0xB2,0x88,0x74, + 0x04,0x28,0xBE,0xD1,0x00,0x20,0x88,0x74,0x01,0x98,0x24,0x1D,0x02,0x1B,0x52,0x1E, + 0x03,0x2A,0x00,0xD2,0x04,0x1F,0x84,0x42,0xB3,0xD1,0xCE,0x7C,0x0E,0x75,0x11,0x4F, + 0x00,0x21,0x00,0x20,0x3A,0x5C,0x13,0x09,0x8B,0x42,0x10,0xD1,0x15,0x07,0x06,0x22, + 0x33,0x46,0x53,0x43,0x0A,0x4A,0x2D,0x0F,0x9A,0x18,0x4B,0x00,0xD2,0x18,0x94,0x79, + 0x01,0x23,0xAB,0x40,0x1C,0x43,0x94,0x71,0x14,0x7B,0x9C,0x43,0x14,0x73,0x40,0x1C, + 0x08,0x28,0xE7,0xD3,0x49,0x1C,0x03,0x29,0xE3,0xD3,0xFE,0xBD,0xC4,0x00,0x00,0x20, + 0xAC,0x09,0x00,0x20,0x21,0x7B,0x00,0x00,0x70,0xB5,0x04,0x46,0x00,0x20,0x10,0x21, + 0x20,0x5E,0x61,0x5E,0x42,0x18,0x04,0x20,0x0C,0x21,0x20,0x5E,0x61,0x5E,0x40,0x18, + 0x82,0x42,0x01,0xDA,0x11,0x46,0x00,0xE0,0x01,0x46,0x01,0x29,0x01,0xDA,0x01,0x21, + 0x04,0xE0,0x82,0x42,0x01,0xDA,0x11,0x46,0x00,0xE0,0x01,0x46,0x82,0x42,0x00,0xDD, + 0x10,0x46,0x64,0x22,0x50,0x43,0xFF,0xF7,0x2B,0xFA,0x05,0x46,0x02,0x20,0x0E,0x21, + 0x20,0x5E,0x61,0x5E,0x0A,0x22,0x40,0x18,0x06,0x21,0x61,0x5E,0xA2,0x5E,0x8A,0x18, + 0x90,0x42,0x01,0xDA,0x01,0x46,0x00,0xE0,0x11,0x46,0x01,0x29,0x01,0xDA,0x01,0x21, + 0x04,0xE0,0x90,0x42,0x01,0xDA,0x01,0x46,0x00,0xE0,0x11,0x46,0x90,0x42,0x00,0xDC, + 0x10,0x46,0x8D,0x22,0x50,0x43,0xFF,0xF7,0x0B,0xFA,0x28,0x18,0x00,0xB2,0xFA,0x38, + 0xC1,0x0F,0x08,0x18,0x41,0x10,0x3C,0x20,0x40,0x1A,0x05,0x28,0x03,0xDB,0x3C,0x28, + 0x01,0xDD,0x3C,0x20,0x02,0xE0,0x05,0x28,0x00,0xDA,0x05,0x20,0xC0,0xB2,0x70,0xBD, + 0xF1,0xB5,0x8C,0xB0,0x00,0x20,0x06,0x90,0x4F,0x48,0x41,0x68,0x89,0x6A,0x00,0x29, + 0x7E,0xD0,0x00,0x21,0x08,0x46,0x05,0x91,0x85,0xE0,0x01,0x46,0x0E,0x20,0x41,0x43, + 0x4A,0x48,0x08,0x26,0x0D,0x18,0x0B,0x95,0xAE,0x5F,0x06,0x20,0x28,0x5E,0x77,0x10, + 0xC0,0x19,0x31,0x46,0xFF,0xF7,0xDC,0xF9,0xC4,0xB2,0x04,0x20,0x28,0x5E,0x31,0x46, + 0xC0,0x19,0xFF,0xF7,0xD5,0xF9,0xC0,0xB2,0x86,0x46,0x01,0x20,0x84,0x46,0x60,0x1E, + 0x41,0xB2,0x00,0x25,0x60,0x46,0x20,0x18,0x0A,0x90,0x51,0xE0,0x70,0x46,0x62,0x46, + 0x80,0x1A,0x72,0x44,0x40,0xB2,0x09,0x92,0x45,0xE0,0x00,0x29,0x01,0xDA,0x00,0x24, + 0x00,0xE0,0x0C,0x46,0x34,0x4A,0x52,0x68,0x93,0x7F,0x1E,0x46,0x5B,0x1E,0x08,0x93, + 0x9C,0x42,0x05,0xDA,0x00,0x29,0x01,0xDA,0x00,0x23,0x02,0xE0,0x0B,0x46,0x00,0xE0, + 0x73,0x1E,0xDC,0xB2,0x00,0x28,0x01,0xDA,0x00,0x27,0x00,0xE0,0x07,0x46,0xD2,0x7F, + 0x53,0x1E,0x07,0x93,0x9F,0x42,0x05,0xDA,0x00,0x28,0x01,0xDA,0x00,0x23,0x02,0xE0, + 0x03,0x46,0x00,0xE0,0x53,0x1E,0xDB,0xB2,0x00,0x29,0x01,0xDA,0x01,0x24,0x04,0xE0, + 0x08,0x9F,0x8F,0x42,0x01,0xDA,0xB6,0x1E,0xF4,0xB2,0x00,0x28,0x01,0xDA,0x01,0x23, + 0x04,0xE0,0x07,0x9E,0x86,0x42,0x01,0xDA,0x93,0x1E,0xDB,0xB2,0x62,0x43,0xD2,0x18, + 0x53,0x00,0x0C,0x9A,0x6C,0x46,0xD2,0x5A,0x6B,0x00,0x6D,0x1C,0xE2,0x52,0x40,0x1C, + 0x09,0x9A,0x6D,0xB2,0x40,0xB2,0x82,0x42,0xB7,0xDA,0x49,0x1C,0x0A,0x98,0x49,0xB2, + 0x88,0x42,0xAB,0xDA,0x10,0x48,0x40,0x68,0x81,0x6A,0x68,0x46,0x88,0x47,0x00,0xE0, + 0x17,0xE0,0x0B,0x99,0xC8,0x72,0x06,0x99,0x88,0x42,0x00,0xD9,0x06,0x90,0x05,0x98, + 0x40,0x1C,0xC0,0xB2,0x05,0x90,0x08,0x49,0x49,0x78,0x88,0x42,0x00,0xD2,0x74,0xE7, + 0x05,0x48,0x40,0x68,0x01,0x7C,0x4A,0x00,0x8A,0x18,0x06,0x99,0x51,0x18,0x89,0x08, + 0x01,0x74,0x0D,0xB0,0xF0,0xBD,0x00,0x00,0x30,0x00,0x00,0x20,0xA8,0x0B,0x00,0x20, + 0x70,0xB5,0x15,0x46,0x0A,0x46,0x12,0x49,0x00,0x24,0x4E,0x68,0xB1,0x7B,0x51,0x1A, + 0xF2,0x7B,0x51,0x43,0x0A,0xB2,0x00,0x2A,0x00,0xDA,0x00,0x22,0x82,0x42,0x01,0xDB, + 0x00,0x20,0x70,0xBD,0x92,0x02,0x01,0x46,0x10,0x46,0xFF,0xF7,0x39,0xF9,0x01,0x21, + 0x89,0x02,0x08,0x1A,0x00,0xB2,0x71,0x7B,0x04,0xE0,0x40,0x43,0x80,0x12,0x64,0x1C, + 0x00,0xB2,0xE4,0xB2,0xA1,0x42,0xF8,0xD8,0x68,0x43,0x80,0x12,0x00,0xB2,0x70,0xBD, + 0x30,0x00,0x00,0x20,0xF8,0xB5,0x48,0x22,0x00,0x21,0x2E,0x48,0x02,0xF0,0x4E,0xFA, + 0x2C,0x4C,0x2D,0x4E,0x00,0x21,0x00,0x20,0x2C,0x4A,0x12,0x5C,0x12,0x09,0x8A,0x42, + 0x24,0xD1,0x32,0x18,0x8B,0x00,0x40,0x32,0xE5,0x5C,0x12,0x79,0x15,0x43,0xE5,0x54, + 0x1B,0x19,0x9D,0x7B,0x15,0x43,0x9D,0x73,0xDD,0x7E,0x15,0x43,0xDD,0x76,0xC5,0x07, + 0x08,0xD0,0x1D,0x46,0x20,0x35,0xAF,0x79,0x17,0x43,0xAF,0x71,0xEF,0x7C,0x17,0x43, + 0xEF,0x74,0x07,0xE0,0x1D,0x46,0x20,0x35,0xAF,0x7C,0x17,0x43,0xAF,0x74,0xEF,0x79, + 0x17,0x43,0xEF,0x71,0x20,0x33,0xDD,0x7F,0x15,0x43,0xDD,0x77,0x40,0x1C,0xC0,0xB2, + 0x08,0x28,0xD1,0xD3,0x16,0x4F,0x00,0x22,0xB8,0x5C,0x00,0x09,0x88,0x42,0x17,0xD1, + 0xB0,0x18,0x8B,0x00,0x40,0x30,0xE5,0x5C,0x00,0x7B,0x05,0x43,0xE5,0x54,0x1B,0x19, + 0xDD,0x7B,0x05,0x43,0xDD,0x73,0x9D,0x7E,0x05,0x43,0x9D,0x76,0x20,0x33,0xDD,0x79, + 0x05,0x43,0xDD,0x71,0xDD,0x7C,0x05,0x43,0xDD,0x74,0xDD,0x7F,0x05,0x43,0xDD,0x77, + 0x52,0x1C,0xD2,0xB2,0x09,0x2A,0xDF,0xD3,0x49,0x1C,0xC9,0xB2,0x03,0x29,0xAA,0xD3, + 0xF8,0xBD,0x00,0x00,0x54,0x09,0x00,0x20,0x40,0x7B,0x00,0x00,0x21,0x7B,0x00,0x00, + 0x29,0x7B,0x00,0x00,0x08,0xB5,0x6A,0x46,0x00,0x90,0x13,0x88,0x0A,0x33,0x13,0x80, + 0x0A,0x46,0x00,0x99,0x01,0xF0,0xF4,0xFC,0x08,0xBD,0x40,0x1A,0x00,0xB2,0x00,0x28, + 0x02,0xDA,0xFF,0x30,0x69,0x30,0x00,0xB2,0x80,0xB2,0x70,0x47,0xF0,0xB5,0x6F,0x4E, + 0x8B,0xB0,0xF2,0x6B,0x35,0x46,0x10,0x79,0x01,0x90,0xD0,0x78,0x00,0x90,0x80,0x3D, + 0x13,0x78,0x69,0x6D,0x5B,0x00,0x68,0x6C,0x06,0x93,0xD3,0x7D,0x0A,0x93,0x1B,0x23, + 0xD3,0x56,0x09,0x93,0x00,0x23,0x2B,0x62,0x05,0x93,0xEB,0x61,0x04,0x93,0x54,0x78, + 0x64,0x08,0x08,0x94,0x52,0x24,0x14,0x5F,0x62,0x10,0x07,0x92,0xEA,0x1D,0xF9,0x32, + 0x02,0x92,0x13,0x77,0x6A,0x78,0x05,0x2A,0x22,0xD8,0x00,0x9F,0x01,0x9A,0x2B,0x46, + 0x57,0x43,0x00,0x22,0x20,0x33,0x19,0xE0,0x58,0x4C,0x80,0x3C,0x64,0x78,0x02,0x2C, + 0x01,0xD8,0x0C,0x88,0x05,0xE0,0x00,0x25,0x04,0x88,0x4D,0x5F,0x64,0x19,0xE4,0x03, + 0x24,0x0C,0x04,0x80,0x00,0x24,0x0C,0x5F,0x00,0x2C,0x03,0xDA,0xDC,0x7C,0x01,0x25, + 0x2C,0x43,0xDC,0x74,0x80,0x1C,0x89,0x1C,0x52,0x1C,0x92,0xB2,0xBA,0x42,0xE3,0xD3, + 0x4A,0x48,0x80,0x38,0x41,0x6C,0x03,0x91,0x00,0x25,0x44,0x6D,0x81,0xE0,0x00,0x20, + 0x02,0x9A,0x84,0x46,0x92,0x6B,0x01,0x46,0x50,0x55,0x03,0x46,0x45,0xE0,0x03,0x98, + 0x22,0x88,0x00,0x88,0x80,0x1A,0x02,0xB2,0x22,0x80,0x06,0x98,0x82,0x42,0x05,0xDA, + 0x49,0x1C,0x60,0x46,0x80,0x18,0x00,0xB2,0xC9,0xB2,0x84,0x46,0x08,0x98,0x82,0x42, + 0x1A,0xDD,0x0A,0x98,0x82,0x42,0x2A,0xDD,0xF0,0x6B,0xC0,0x79,0x00,0x28,0x03,0xD0, + 0x00,0x9F,0x7F,0x1E,0xBD,0x42,0x04,0xD0,0x01,0x27,0x05,0x98,0x9F,0x40,0x07,0x43, + 0x05,0x97,0x02,0x98,0x01,0x27,0x80,0x6B,0x47,0x55,0xF0,0x6B,0x00,0x78,0x90,0x42, + 0x15,0xDA,0x02,0x9A,0x17,0x77,0x12,0xE0,0x07,0x98,0x82,0x42,0x0F,0xDA,0x09,0x98, + 0x82,0x42,0x0C,0xDA,0xF0,0x6B,0xC0,0x79,0x00,0x28,0x03,0xD0,0x00,0x98,0x40,0x1E, + 0x85,0x42,0x04,0xD0,0x01,0x20,0x04,0x9A,0x98,0x40,0x10,0x43,0x04,0x90,0x03,0x98, + 0xA4,0x1C,0x80,0x1C,0x5B,0x1C,0x5B,0xB2,0x03,0x90,0x01,0x98,0x83,0x42,0xB6,0xDB, + 0xF0,0x6B,0x20,0x30,0x80,0x7C,0x00,0x28,0x29,0xD0,0x01,0x98,0x40,0x00,0x24,0x1A, + 0x02,0x29,0x04,0xD9,0x60,0x46,0xFE,0xF7,0xFB,0xFF,0x00,0xB2,0x00,0xE0,0x00,0x20, + 0x00,0x22,0x19,0xE0,0x16,0x49,0x00,0x28,0x61,0x5E,0x0B,0xDD,0x06,0x9B,0x99,0x42, + 0x0F,0xDA,0x43,0x1C,0x99,0x42,0x01,0xDD,0x09,0x1A,0x09,0xE0,0x00,0x29,0x08,0xDD, + 0x01,0x21,0x05,0xE0,0x81,0x42,0xF7,0xDB,0x00,0x29,0x02,0xDA,0x00,0x21,0xC9,0x43, + 0x21,0x80,0xA4,0x1C,0x52,0x1C,0x52,0xB2,0x01,0x99,0x8A,0x42,0xE2,0xDB,0x6D,0x1C, + 0x6D,0xB2,0x00,0x98,0x85,0x42,0x00,0xDA,0x79,0xE7,0x04,0x48,0x05,0x99,0x80,0x38, + 0x01,0x62,0x04,0x99,0xC1,0x61,0x0B,0xB0,0xF0,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20, + 0x00,0x00,0x00,0x00,0xF1,0xB5,0x00,0x25,0x84,0xB0,0x2E,0x46,0x7A,0xE0,0x28,0x46, + 0x14,0x22,0x50,0x43,0x3F,0x4A,0x07,0x46,0x84,0x18,0xE0,0x7C,0x00,0x09,0x6F,0xD0, + 0x3D,0x48,0x40,0x68,0x42,0x6A,0x00,0x2A,0x06,0xD0,0x20,0x7C,0x01,0x09,0x00,0x07, + 0x00,0x0F,0x90,0x47,0x00,0x28,0x27,0xD0,0x60,0x68,0x36,0x4A,0xA1,0x68,0x01,0x91, + 0xD1,0x59,0x00,0x02,0x00,0x91,0xFE,0xF7,0xA3,0xFF,0x02,0x46,0x32,0x48,0x80,0x32, + 0x47,0x68,0x38,0x8C,0x02,0x90,0x50,0x43,0xF9,0x7F,0xFE,0xF7,0x99,0xFF,0x01,0x99, + 0x03,0x90,0x08,0x02,0x00,0x99,0xFE,0xF7,0x93,0xFF,0x02,0x46,0x78,0x8C,0x01,0x90, + 0x80,0x32,0x50,0x43,0xB9,0x7F,0xFE,0xF7,0x8B,0xFF,0x03,0x99,0x00,0x12,0x09,0x12, + 0x00,0x29,0x06,0xDA,0x00,0x21,0x08,0xE0,0xE0,0x7C,0x00,0x07,0x00,0x0F,0xE0,0x74, + 0x36,0xE0,0x02,0x9A,0x8A,0x42,0x00,0xDA,0x11,0x46,0x00,0x28,0x01,0xDA,0x00,0x20, + 0x03,0xE0,0x01,0x9A,0x82,0x42,0x00,0xDA,0x10,0x46,0x04,0x9B,0xF2,0x00,0x99,0x52, + 0x04,0x99,0x76,0x1C,0x51,0x18,0x48,0x80,0x48,0x79,0x62,0x7C,0x00,0x09,0x12,0x07, + 0x00,0x01,0x12,0x0F,0x10,0x43,0x48,0x71,0x62,0x7C,0x00,0x07,0x12,0x09,0x00,0x0F, + 0x12,0x01,0x10,0x43,0x48,0x71,0x88,0x79,0xA2,0x7C,0x00,0x09,0x12,0x07,0x00,0x01, + 0x12,0x0F,0x10,0x43,0x88,0x71,0xA2,0x7C,0x00,0x07,0x12,0x09,0x00,0x0F,0x12,0x01, + 0x10,0x43,0x88,0x71,0x00,0x98,0xF6,0xB2,0x40,0x10,0x08,0x71,0x08,0x2E,0x05,0xD2, + 0x6D,0x1C,0xED,0xB2,0x04,0x49,0x08,0x78,0x85,0x42,0x80,0xD3,0x30,0x46,0x05,0xB0, + 0xF0,0xBD,0x00,0x00,0xE0,0x0A,0x00,0x20,0x30,0x00,0x00,0x20,0xF3,0xB5,0x85,0xB0, + 0x05,0x20,0x00,0x90,0x31,0x48,0x01,0x90,0xC0,0x6B,0x40,0x30,0x00,0x78,0x80,0x1E, + 0xC6,0xB2,0x3F,0x2E,0x00,0xD9,0x3F,0x26,0x00,0x20,0x80,0x25,0x2C,0x46,0x03,0x90, + 0x20,0x46,0x01,0x27,0x03,0xE0,0x80,0x1B,0x7F,0x1C,0xC0,0xB2,0xFF,0xB2,0xB0,0x42, + 0xF9,0xD8,0x3A,0x46,0x31,0x46,0x02,0x90,0x05,0xF0,0xA0,0xFB,0x06,0x98,0x80,0x47, + 0x04,0x90,0x06,0x98,0x80,0x47,0x04,0x99,0x40,0x18,0x01,0x99,0x00,0x04,0xC9,0x6B, + 0x40,0x0C,0x40,0x31,0xC9,0x88,0x81,0x42,0x01,0xD9,0xAC,0x43,0x01,0xE0,0x01,0x2D, + 0x02,0xD0,0x00,0x2D,0x07,0xD0,0x08,0xE0,0x0A,0x46,0x14,0x32,0x82,0x42,0x04,0xD2, + 0x64,0x1C,0xE4,0xB2,0x01,0xE0,0x01,0x22,0x03,0x92,0x6D,0x08,0x03,0x9A,0x2C,0x43, + 0x00,0x2A,0xCD,0xD0,0x01,0x9A,0xD2,0x6B,0x40,0x32,0xD2,0x88,0x52,0x08,0x82,0x42, + 0x02,0xD2,0x49,0x00,0x81,0x42,0x05,0xD8,0x00,0x99,0x49,0x1E,0x09,0x06,0x09,0x0E, + 0x00,0x91,0xB9,0xD1,0x00,0x99,0x05,0x22,0x51,0x1A,0x05,0x9A,0x11,0x70,0x05,0x99, + 0x4F,0x70,0x05,0x99,0x8E,0x70,0x05,0x9A,0x02,0x99,0xD1,0x70,0x05,0x99,0x08,0x71, + 0x01,0x0A,0x05,0x98,0x41,0x71,0x07,0xB0,0xF0,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20, + 0x70,0xB5,0x15,0x4C,0xE0,0x7C,0xC0,0x07,0x24,0xD0,0x3C,0x20,0x05,0xF0,0x86,0xFB, + 0x00,0x25,0xE5,0x75,0x02,0xF0,0xD4,0xF8,0x20,0x46,0x20,0x38,0x05,0x72,0x01,0x20, + 0x05,0xF0,0xD0,0xF8,0x02,0x20,0x05,0xF0,0xAD,0xFA,0x02,0xF0,0x43,0xFF,0x0B,0x48, + 0x81,0x7C,0x80,0x22,0x11,0x43,0x81,0x74,0x00,0xF0,0x12,0xF8,0x00,0x20,0x05,0xF0, + 0xA1,0xFA,0x02,0x20,0x05,0xF0,0x9E,0xFA,0x00,0x21,0x02,0x20,0x05,0xF0,0xBC,0xF9, + 0x02,0xF0,0x8C,0xF9,0x70,0xBD,0x00,0x00,0x64,0x00,0x00,0x20,0xE0,0x12,0x00,0x40, + 0xF8,0xB5,0x25,0x48,0x24,0x4F,0xC0,0x6B,0x80,0x3F,0x23,0x4D,0x86,0x79,0x39,0x7A, + 0xA0,0x35,0x34,0x46,0x01,0x29,0x38,0xD0,0x00,0x24,0xEC,0x74,0x1F,0x49,0x0A,0x7A, + 0x02,0x23,0x1A,0x43,0x0A,0x72,0x1E,0x49,0x08,0x22,0xCA,0x80,0x20,0x30,0xC0,0x78, + 0x40,0x1E,0xC0,0xB2,0x00,0x90,0x01,0x20,0x05,0xF0,0xAA,0xF9,0x19,0x49,0xAA,0x20, + 0x88,0x80,0xEA,0x7C,0xF9,0x6D,0x01,0x20,0x88,0x54,0xFF,0x20,0x14,0x49,0x02,0x30, + 0xC8,0x81,0x21,0x46,0x00,0x98,0x00,0xF0,0x27,0xF8,0x38,0x7A,0x01,0x28,0x0E,0xD0, + 0x00,0x2C,0x17,0xD0,0x28,0x7C,0x00,0x19,0xC4,0xB2,0xB4,0x42,0x07,0xD0,0x28,0x7C, + 0x01,0x19,0xB1,0x42,0x01,0xD9,0x30,0x1A,0xC4,0xB2,0xB4,0x42,0xDE,0xD3,0x07,0x49, + 0x08,0x7A,0xFD,0x22,0x10,0x40,0x08,0x72,0xF8,0xBD,0x76,0x1C,0x29,0x7D,0xF6,0xB2, + 0xE9,0x74,0xC3,0xE7,0x2C,0x7C,0xE8,0xE7,0xC4,0x00,0x00,0x20,0x00,0x03,0x00,0x40, + 0x00,0x10,0x00,0x40,0x00,0x02,0x00,0x40,0xF3,0xB5,0x95,0xB0,0x72,0x48,0x13,0x90, + 0xC0,0x6B,0x4C,0x21,0x09,0x5A,0x70,0x4D,0x0A,0x31,0x07,0x79,0x89,0xB2,0xA0,0x35, + 0x10,0x91,0x29,0x7C,0x11,0x91,0x6C,0x49,0x80,0x39,0x0A,0x7A,0x01,0x2A,0x02,0xD1, + 0xC7,0x79,0x01,0x20,0x11,0x90,0x00,0x20,0x0D,0x90,0x67,0x48,0xC0,0x30,0x0F,0x90, + 0x0D,0x98,0xA9,0xE0,0x02,0x20,0x0E,0x90,0x00,0x20,0x0C,0x90,0x13,0x98,0xE9,0x7C, + 0xC0,0x6B,0x00,0x79,0x48,0x43,0x60,0x49,0x80,0x39,0x89,0x6D,0x46,0x18,0x78,0x00, + 0x12,0x90,0x01,0x20,0x0B,0x90,0x00,0x20,0x0A,0x90,0xFF,0x21,0x05,0xA8,0x12,0x9A, + 0x01,0xF0,0x44,0xFF,0x3A,0x46,0x00,0x21,0x30,0x46,0x01,0xF0,0x3F,0xFF,0x00,0x24, + 0x14,0x94,0x0F,0x99,0xEA,0x7C,0x09,0x68,0x52,0x00,0x8C,0x52,0x6D,0xE0,0xE8,0x7C, + 0x00,0x21,0x05,0xF0,0x49,0xFA,0x50,0x48,0x80,0x38,0x00,0x7A,0x01,0x28,0x0B,0xD0, + 0xE8,0x7C,0x05,0xF0,0x23,0xF8,0x00,0x20,0x05,0xF0,0x30,0xFE,0x00,0x21,0x68,0x46, + 0x03,0xF0,0xA8,0xFC,0x00,0x20,0x2E,0xE0,0x00,0x21,0x01,0x20,0x16,0x9A,0x05,0xF0, + 0xFD,0xFA,0xF0,0xE7,0x0B,0x99,0x00,0x29,0x0A,0xD0,0x42,0x00,0x69,0x46,0x8A,0x5A, + 0x10,0x99,0x8A,0x42,0x04,0xD2,0x01,0x21,0x0A,0x9A,0x81,0x40,0x11,0x43,0x0A,0x91, + 0x01,0x21,0x81,0x40,0x8C,0x46,0x21,0x42,0x13,0xD1,0x41,0x00,0x6A,0x46,0x53,0x5A, + 0x10,0x9A,0x9A,0x1A,0x00,0xD5,0x52,0x42,0x05,0xAB,0x5B,0x5A,0x92,0xB2,0x93,0x42, + 0x02,0xD3,0x05,0xAB,0x5A,0x52,0x04,0xE0,0x31,0x5C,0x49,0x1E,0x31,0x54,0x61,0x46, + 0x0C,0x43,0x40,0x1C,0xC0,0xB2,0xB8,0x42,0xD4,0xD3,0x0B,0x98,0x00,0x28,0x07,0xD0, + 0x00,0x20,0x0B,0x90,0x0F,0x99,0xEA,0x7C,0x09,0x68,0x0A,0x98,0x52,0x00,0x88,0x52, + 0x01,0x21,0x0B,0x46,0xBB,0x40,0x5B,0x1E,0xA3,0x42,0x02,0xD1,0x01,0x20,0x0C,0x90, + 0x16,0xE0,0x00,0x20,0x0B,0x46,0x0B,0xE0,0x19,0x46,0x81,0x40,0x21,0x42,0x05,0xD1, + 0x31,0x5C,0x15,0x9A,0x91,0x42,0x0B,0xD2,0x49,0x1C,0x31,0x54,0x40,0x1C,0xC0,0xB2, + 0xB8,0x42,0xF1,0xD3,0x14,0x98,0x00,0x28,0x02,0xD1,0x0C,0x98,0x00,0x28,0x8E,0xD0, + 0x0E,0x98,0x40,0x1E,0x00,0x06,0x00,0x0E,0x0E,0x90,0x03,0xD0,0x0C,0x98,0x00,0x28, + 0x00,0xD1,0x6E,0xE7,0x15,0x49,0xAA,0x20,0x88,0x80,0xE8,0x7C,0x40,0x1C,0xE8,0x74, + 0x0D,0x98,0x40,0x1C,0xC0,0xB2,0x0D,0x90,0x11,0x99,0x88,0x42,0x00,0xD2,0x51,0xE7, + 0x0D,0x48,0x80,0x38,0x00,0x7A,0x01,0x28,0x01,0xD0,0x00,0x24,0x0E,0xE0,0x01,0x21, + 0x08,0x46,0x16,0x9A,0x05,0xF0,0x82,0xFA,0x0B,0xE0,0x16,0x98,0x01,0x21,0x00,0x19, + 0xC2,0xB2,0x08,0x46,0x05,0xF0,0x7A,0xFA,0x64,0x1C,0xE4,0xB2,0x28,0x7C,0xA0,0x42, + 0xF3,0xD8,0x00,0x20,0x17,0xB0,0xF0,0xBD,0xC4,0x00,0x00,0x20,0x00,0x02,0x00,0x40, + 0xF0,0xB5,0x4A,0x4F,0x00,0x23,0x91,0xB0,0x3C,0x46,0xFB,0x71,0x20,0x34,0x20,0x7D, + 0x21,0x7D,0x80,0x07,0xC0,0x0F,0x49,0x08,0x49,0x00,0x01,0x43,0x21,0x75,0x20,0x7D, + 0xFD,0x21,0x08,0x40,0x20,0x75,0x19,0x20,0x6D,0x46,0xA8,0x74,0x03,0x20,0x28,0x75, + 0x28,0x20,0xE8,0x74,0x0A,0x20,0xA8,0x75,0xE8,0x7E,0x18,0x22,0xC1,0x06,0xC9,0x0E, + 0x14,0x20,0x11,0x43,0xE8,0x75,0x0F,0x22,0xAA,0x76,0xFB,0x22,0x11,0x40,0x04,0x22, + 0x2A,0x76,0x3C,0x22,0x6A,0x76,0x02,0x22,0x11,0x43,0x49,0x08,0x28,0x82,0x49,0x00, + 0xE9,0x76,0x01,0x21,0x69,0x75,0x32,0x4D,0x09,0x95,0x0A,0x35,0x0A,0x95,0x3E,0x78, + 0x6D,0x46,0xAE,0x85,0x29,0x77,0x05,0x21,0x69,0x77,0xA8,0x77,0xEA,0x77,0x25,0x46, + 0xE0,0x35,0xE8,0x7F,0xFF,0x28,0x01,0xD1,0x14,0x20,0xE8,0x77,0x08,0xAA,0x10,0x70, + 0x28,0x48,0x0D,0x90,0x25,0x4E,0x28,0x48,0x80,0x36,0x0F,0x93,0x0E,0x90,0xF0,0x6B, + 0x81,0x79,0x91,0x73,0x41,0x79,0xD1,0x73,0x01,0x46,0x40,0x31,0x0B,0x89,0x6A,0x46, + 0x13,0x86,0x49,0x89,0x51,0x86,0x31,0x46,0x40,0x31,0x03,0x91,0x49,0x7E,0xBB,0x6F, + 0x3A,0x6E,0x01,0x93,0x00,0x92,0x02,0x91,0x42,0x79,0x81,0x79,0x7B,0x6D,0xF8,0x6C, + 0x00,0xF0,0x76,0xFD,0x03,0x99,0x48,0x7E,0x32,0x28,0x09,0xD9,0x69,0x46,0xC8,0x7E, + 0xC0,0x06,0xC0,0x0E,0x20,0x30,0xC8,0x76,0x02,0x20,0x48,0x75,0x1E,0x20,0xC8,0x74, + 0xF0,0x6B,0x31,0x69,0xC2,0x7A,0x70,0x69,0x10,0xAB,0x03,0x93,0x01,0x92,0x02,0x91, + 0x00,0x90,0xAA,0x6B,0x04,0xAB,0x79,0x6D,0xF8,0x6C,0x00,0xF0,0x5F,0xFC,0xF8,0x71, + 0x08,0xA9,0x09,0x78,0xE9,0x77,0x00,0x28,0x05,0xD0,0x20,0x7D,0x02,0x21,0x08,0x43, + 0x20,0x75,0x11,0xB0,0xF0,0xBD,0x14,0x20,0xE8,0x77,0xFA,0xE7,0x44,0x00,0x00,0x20, + 0xE0,0x7B,0x00,0x00,0xD1,0x19,0x00,0x00,0xF9,0x0C,0x00,0x00,0xF0,0xB5,0x6F,0x48, + 0x87,0xB0,0xC0,0x6B,0xC1,0x78,0x03,0x91,0x01,0x79,0x04,0x91,0x3A,0x21,0x09,0x5C, + 0x8E,0x46,0x3E,0x21,0x41,0x5E,0x06,0x91,0x68,0x49,0x82,0x7B,0x80,0x39,0x09,0x6A, + 0x01,0x91,0x66,0x49,0x80,0x39,0x89,0x69,0x00,0x91,0x64,0x49,0x60,0x39,0x0C,0x46, + 0xA0,0x34,0x05,0x91,0x00,0x2A,0x03,0xD0,0x00,0x9A,0x01,0x99,0x11,0x42,0x0C,0xD0, + 0x00,0x21,0xA1,0x76,0x5D,0x49,0x04,0x9B,0x80,0x39,0x03,0x9A,0x49,0x6D,0x5A,0x43, + 0x00,0x26,0x94,0x46,0x35,0x46,0x32,0x46,0x70,0xE0,0x58,0x4D,0x00,0x21,0x80,0x3D, + 0x2D,0x6E,0x76,0x46,0x0A,0x46,0xAC,0x46,0x77,0x42,0x13,0x46,0x0D,0x46,0x02,0x97, + 0x13,0xE0,0x66,0x46,0x00,0x27,0xF7,0x5F,0x77,0x45,0x01,0xDD,0x52,0x1C,0x08,0xE0, + 0x02,0x9E,0xB7,0x42,0x05,0xDA,0x06,0x9E,0x5B,0x1C,0xB7,0x42,0x01,0xDA,0x49,0x1C, + 0xC9,0xB2,0x66,0x46,0xB6,0x1C,0xB4,0x46,0x6D,0x1C,0x04,0x9F,0xBD,0x42,0xE8,0xD3, + 0x46,0x4D,0x80,0x3D,0xAD,0x6F,0x00,0x26,0x11,0xE0,0x00,0x27,0xEF,0x5F,0x77,0x45, + 0x01,0xDD,0x52,0x1C,0x08,0xE0,0x02,0x9E,0xB7,0x42,0x05,0xDA,0x06,0x9E,0x5B,0x1C, + 0xB7,0x42,0x01,0xDA,0x49,0x1C,0xC9,0xB2,0xAD,0x1C,0x66,0x46,0x76,0x1C,0x03,0x9F, + 0xB4,0x46,0xBE,0x42,0xE9,0xD3,0x39,0x4D,0x40,0x35,0xAD,0x7E,0x04,0x2A,0x01,0xD8, + 0x00,0x2B,0x07,0xD0,0x6D,0x1C,0xEA,0xB2,0xA2,0x76,0x00,0x29,0x06,0xD0,0x12,0x1D, + 0xA2,0x76,0x03,0xE0,0x00,0x2D,0xA5,0xD0,0x6D,0x1E,0xA5,0x76,0xA1,0x7E,0x32,0x29, + 0xA0,0xD9,0x00,0x21,0xA1,0x76,0x2D,0x4A,0x01,0x21,0x80,0x3A,0x51,0x70,0x05,0x9A, + 0xD2,0x7C,0x0A,0x43,0x05,0x99,0xCA,0x74,0x94,0xE7,0x00,0x23,0xCB,0x5E,0xC7,0x7D, + 0xBB,0x42,0x04,0xDD,0x07,0x78,0xBB,0x42,0x01,0xDA,0x76,0x1C,0x04,0xE0,0x1B,0x27, + 0xC7,0x57,0xBB,0x42,0x00,0xDA,0x6D,0x1C,0x89,0x1C,0x52,0x1C,0x63,0x46,0x62,0x45, + 0xEB,0xD3,0x00,0x21,0x02,0x91,0x80,0x7B,0x14,0x27,0x00,0x28,0x0E,0xD0,0x05,0x2D, + 0x03,0xD9,0x00,0x98,0x00,0x28,0x06,0xD0,0x01,0xE0,0x00,0x2D,0x06,0xD0,0x01,0x99, + 0x00,0x98,0x08,0x42,0x02,0xD1,0x01,0x20,0x28,0x27,0x02,0x90,0x98,0x00,0x05,0x21, + 0xFE,0xF7,0xFC,0xFB,0x11,0x49,0x40,0x31,0xC9,0x7E,0x86,0x42,0x0F,0xD2,0x85,0x42, + 0x0D,0xD2,0x02,0x9A,0x01,0x2A,0x0A,0xD0,0x40,0x08,0xB0,0x42,0x05,0xD9,0xA8,0x42, + 0x03,0xD9,0x00,0x29,0x01,0xD0,0x49,0x1E,0xE1,0x76,0x07,0xB0,0xF0,0xBD,0x49,0x1C, + 0xC8,0xB2,0xE0,0x76,0xB8,0x42,0xF8,0xD3,0x05,0x98,0xC0,0x7C,0x01,0x21,0x08,0x43, + 0x05,0x99,0xC8,0x74,0x00,0x20,0xE0,0x76,0xEF,0xE7,0x00,0x00,0xC4,0x00,0x00,0x20, + 0xF0,0xB5,0x8C,0x46,0x4E,0x49,0x88,0xB0,0xC9,0x6B,0x07,0x91,0x8D,0x79,0x4C,0x79, + 0x01,0x46,0x61,0x43,0x4A,0x00,0x61,0x46,0x4B,0x00,0x49,0x49,0xD2,0x18,0x80,0x39, + 0x49,0x6D,0x52,0x18,0x61,0x00,0x8E,0x46,0x56,0x1A,0x31,0x46,0x20,0x39,0xCF,0x8B, + 0x69,0x46,0x0F,0x80,0x37,0x88,0x4F,0x80,0x76,0x88,0x8E,0x80,0x11,0x46,0x20,0x39, + 0xCE,0x8B,0x69,0x46,0xCE,0x80,0x16,0x88,0x0E,0x81,0x56,0x88,0x4E,0x81,0x71,0x46, + 0x8F,0x18,0x05,0x97,0x20,0x3F,0xFE,0x8B,0x69,0x46,0x8E,0x81,0x71,0x46,0x52,0x5A, + 0x69,0x46,0xCA,0x81,0x05,0x9F,0x7A,0x88,0x0A,0x82,0x35,0x49,0x80,0x39,0x0A,0x6E, + 0x99,0x1E,0x56,0x5A,0x69,0x46,0x8E,0x82,0xD6,0x5E,0xCE,0x82,0x9B,0x1C,0xD2,0x5A, + 0x0A,0x83,0x62,0x46,0x00,0x21,0x6B,0x46,0x00,0x2A,0x2F,0xD0,0x64,0x1E,0xA4,0x45, + 0x03,0xD1,0x99,0x80,0x59,0x81,0x19,0x82,0x19,0x83,0x00,0x28,0x2B,0xD0,0x6A,0x1E, + 0x90,0x42,0x02,0xD1,0x99,0x81,0xD9,0x81,0x19,0x82,0x25,0x49,0x80,0x39,0x09,0x78, + 0x4C,0x08,0x00,0x22,0x11,0x46,0x4F,0x00,0xDF,0x5B,0x49,0x1C,0xBA,0x18,0xC9,0xB2, + 0x12,0xB2,0x09,0x29,0xF7,0xD3,0xA2,0x42,0x0D,0xDB,0x07,0x99,0x89,0x7B,0x00,0x29, + 0x2F,0xD0,0x1B,0x49,0x0A,0x22,0x40,0x31,0x4B,0x7E,0x80,0x31,0x00,0x2B,0x00,0xD0, + 0x0A,0x79,0x96,0x42,0x0B,0xDA,0x00,0x20,0x08,0xB0,0xF0,0xBD,0x19,0x80,0xD9,0x80, + 0x99,0x81,0x99,0x82,0xD1,0xE7,0x19,0x80,0x59,0x80,0x99,0x80,0xD5,0xE7,0x49,0x79, + 0x00,0x29,0x16,0xD0,0x0E,0x49,0x40,0x31,0x49,0x69,0x00,0x28,0x07,0xD0,0x6D,0x1E, + 0x42,0x1E,0xA8,0x42,0x0A,0xD1,0x8A,0x5C,0x00,0x2A,0x0E,0xD0,0x09,0xE0,0x08,0x78, + 0x00,0x28,0x06,0xD1,0x48,0x78,0x00,0x28,0xDE,0xD0,0x02,0xE0,0x8A,0x5C,0x00,0x2A, + 0x01,0xD0,0x01,0x20,0xD8,0xE7,0x42,0x1C,0xED,0xE7,0x08,0x5C,0xF3,0xE7,0x00,0x00, + 0xC4,0x00,0x00,0x20,0x1C,0xB5,0x05,0xA1,0x03,0xC9,0x01,0x91,0x00,0x90,0x05,0x4B, + 0x14,0x22,0x05,0x21,0x68,0x46,0x02,0xF0,0x6F,0xFF,0x1C,0xBD,0x08,0x13,0x21,0x28, + 0x38,0x00,0x00,0x00,0x14,0x0A,0x00,0x20,0x03,0x48,0x01,0x21,0x01,0x70,0x00,0x21, + 0x41,0x70,0x81,0x70,0x70,0x47,0x00,0x00,0xC0,0x0C,0x00,0x20,0xF0,0xB5,0x00,0x24, + 0x01,0x27,0x08,0x4E,0x0A,0xE0,0x05,0x88,0x95,0x42,0x01,0xD3,0x9D,0x42,0x02,0xD9, + 0xF5,0x7C,0x3D,0x43,0xF5,0x74,0x80,0x1C,0x64,0x1C,0xA4,0xB2,0x8C,0x42,0xF2,0xD3, + 0xF0,0xBD,0x00,0x00,0x64,0x00,0x00,0x20,0xF7,0xB5,0x9E,0xB0,0x00,0x20,0x0C,0x90, + 0xFE,0x48,0x14,0x46,0x40,0x68,0xC1,0x7F,0x06,0x91,0x80,0x7F,0x0E,0x90,0x11,0x46, + 0x1E,0x98,0x02,0xF0,0x15,0xF8,0x00,0x28,0x01,0xD0,0x01,0x20,0x0C,0x90,0x60,0xB2, + 0x60,0xE2,0xF7,0x49,0x40,0x00,0x08,0x5A,0x55,0xE2,0x00,0x21,0x04,0x91,0x05,0x91, + 0xF4,0xA1,0x06,0xC9,0x07,0x91,0x08,0x92,0xF4,0xA1,0x06,0xC9,0x09,0x91,0x81,0x04, + 0x46,0x06,0x4C,0x0E,0x06,0x98,0x0A,0x92,0x76,0x0E,0x60,0x43,0x80,0x19,0x1E,0x99, + 0x40,0x00,0x45,0x18,0x1F,0x99,0x6A,0x46,0x40,0x18,0x00,0x21,0x11,0x90,0x41,0x5E, + 0x0F,0x91,0x28,0x88,0x01,0x23,0x81,0x04,0x06,0x98,0x89,0x0C,0x40,0xB2,0x0D,0x91, + 0x14,0x90,0x10,0x72,0x06,0x98,0x40,0x42,0x40,0xB2,0x13,0x90,0x50,0x72,0x93,0x72, + 0x98,0x1E,0xD0,0x72,0x06,0x98,0x40,0x1E,0x10,0x73,0x06,0x9A,0xD7,0x43,0x6A,0x46, + 0x57,0x73,0x06,0x9F,0x7F,0x1C,0x97,0x73,0x06,0x9A,0x9B,0x1A,0x6A,0x46,0xD3,0x73, + 0x00,0x2C,0x51,0xD0,0x0E,0x9A,0x52,0x1E,0x94,0x42,0x04,0xD1,0x7F,0x22,0x6B,0x46, + 0x1A,0x72,0x1A,0x73,0x9A,0x73,0x00,0x2E,0x4C,0xD0,0x86,0x42,0x04,0xD1,0x7F,0x20, + 0x6A,0x46,0x90,0x72,0x90,0x73,0xD0,0x73,0x0C,0x98,0x00,0x28,0x48,0xD0,0xCB,0x48, + 0x00,0x27,0x00,0x78,0x00,0x28,0x05,0xD0,0x01,0x20,0x80,0x03,0x08,0x18,0x80,0x0B, + 0x80,0x03,0x28,0x80,0x00,0x20,0x02,0xA9,0x09,0x56,0x7F,0x29,0x27,0xD0,0x49,0x00, + 0x4A,0x19,0x94,0x46,0x12,0x88,0x00,0x92,0x92,0x0B,0x02,0x2A,0x1F,0xD0,0x11,0x9A, + 0x51,0x5E,0xBE,0x4A,0x52,0x68,0xD2,0x78,0x8A,0x42,0x18,0xDD,0x04,0x29,0x0E,0xDD, + 0x07,0xAA,0x12,0x5C,0x19,0xAB,0x12,0x19,0xDA,0x55,0x09,0xAA,0x12,0x5C,0x1B,0xAB, + 0x92,0x19,0xDA,0x55,0x7B,0x00,0x15,0xAA,0x7F,0x1C,0xD1,0x52,0xFF,0xB2,0x00,0x99, + 0x8A,0x04,0x01,0x21,0x92,0x0C,0xC9,0x03,0x52,0x18,0x61,0x46,0x0A,0x80,0x40,0x1C, + 0xC0,0xB2,0x08,0x28,0xCF,0xD3,0x4B,0xE0,0x7F,0x22,0x6B,0x46,0x5A,0x72,0x5A,0x73, + 0xDA,0x73,0xB0,0xE7,0x7F,0x20,0x6A,0x46,0xD0,0x72,0x10,0x73,0x50,0x73,0xB3,0xE7, + 0x00,0x27,0x10,0x97,0x10,0x99,0x02,0xA8,0x40,0x56,0x7F,0x28,0x32,0xD0,0x40,0x00, + 0x41,0x19,0x12,0x91,0x11,0x99,0x0A,0x5E,0x29,0x88,0x88,0x0B,0x84,0x46,0x03,0x28, + 0x04,0xD0,0x12,0x98,0x00,0x88,0x83,0x0B,0x01,0x2B,0x30,0xD0,0x12,0x98,0x00,0x88, + 0x81,0x0B,0x02,0x29,0x1E,0xD0,0x99,0x49,0x49,0x68,0xC9,0x78,0x91,0x42,0x19,0xDD, + 0x04,0x2A,0x10,0xDD,0x10,0x9B,0x07,0xA9,0xC9,0x5C,0x0B,0x19,0x19,0xA9,0xCB,0x55, + 0x10,0x9B,0x09,0xA9,0xC9,0x5C,0x1B,0xAB,0x89,0x19,0xD9,0x55,0x7B,0x00,0x15,0xA9, + 0x7F,0x1C,0xCA,0x52,0xFF,0xB2,0x81,0x04,0x01,0x20,0x89,0x0C,0xC0,0x03,0x09,0x18, + 0x12,0x98,0x01,0x80,0x10,0x98,0x40,0x1C,0xC0,0xB2,0x10,0x90,0x08,0x28,0xC1,0xD3, + 0x28,0x88,0x81,0x0B,0x7B,0xD0,0x80,0x0B,0x01,0x28,0x79,0xD0,0x3D,0xE1,0x8B,0x0B, + 0x35,0xD0,0x62,0x46,0x01,0x2A,0xED,0xD1,0x89,0x04,0x82,0x04,0x89,0x0C,0x92,0x0C, + 0x91,0x42,0xE7,0xD0,0x10,0x99,0x04,0x29,0xE4,0xD2,0xC0,0xB2,0x05,0x90,0x04,0x98, + 0x7B,0x4A,0x14,0x21,0x48,0x43,0x3C,0x32,0x80,0x18,0x00,0x7C,0x14,0x23,0x01,0x09, + 0x00,0x07,0x00,0x0F,0x71,0x1A,0x20,0x1A,0x49,0x43,0x40,0x43,0x08,0x18,0x01,0xB2, + 0x05,0x98,0x58,0x43,0x80,0x18,0x00,0x7C,0x02,0x09,0x00,0x07,0x00,0x0F,0xB2,0x1A, + 0x20,0x1A,0x52,0x43,0x40,0x43,0x10,0x18,0x00,0xB2,0x81,0x42,0x49,0xDA,0x03,0x20, + 0x01,0x90,0x00,0x96,0x23,0x46,0x1F,0x9A,0x0F,0x99,0x04,0x98,0x5C,0xE0,0x67,0x4B, + 0x5B,0x68,0x00,0x93,0xDB,0x7A,0x5B,0x09,0x2C,0xD1,0x10,0x9B,0x04,0x2B,0x29,0xD3, + 0x0F,0x9B,0x93,0x42,0x00,0xDA,0x1A,0x46,0x94,0x46,0x00,0x9A,0x13,0x79,0x04,0x22, + 0x9A,0x40,0x12,0xB2,0x01,0x92,0x10,0x9A,0xD2,0x07,0x01,0xD0,0x13,0x9A,0x00,0xE0, + 0x14,0x9A,0x10,0x9B,0x06,0x2B,0x02,0xD2,0x00,0x23,0xDB,0x43,0x00,0xE0,0x01,0x23, + 0x00,0x93,0x53,0x00,0x11,0x9A,0xD2,0x5E,0x63,0x46,0x9B,0x1A,0x01,0x9A,0x93,0x42, + 0x08,0xDB,0x00,0x9A,0x53,0x00,0x11,0x9A,0xD2,0x5E,0x63,0x46,0x9B,0x1A,0x01,0x9A, + 0x93,0x42,0x87,0xDA,0xC0,0xB2,0x04,0x90,0x89,0x04,0x01,0x20,0x89,0x0C,0x80,0x03, + 0x08,0x18,0x81,0x0B,0x04,0x98,0x89,0x03,0x01,0x43,0x29,0x80,0x7A,0xE7,0x3F,0xE0, + 0xA1,0xE0,0x81,0x42,0x06,0xDD,0x03,0x20,0x00,0x96,0x01,0x90,0x23,0x46,0x1F,0x9A, + 0x0F,0x99,0x10,0xE0,0x03,0x20,0x00,0x96,0x01,0x90,0x0F,0x98,0x23,0x46,0x41,0x10, + 0x1F,0x9A,0x04,0x98,0xFE,0xF7,0xCE,0xFA,0x03,0x20,0x00,0x96,0x01,0x90,0x0F,0x98, + 0x1F,0x9A,0x23,0x46,0x41,0x10,0x05,0x98,0xFE,0xF7,0xC4,0xFA,0x12,0x98,0x32,0x46, + 0x00,0x78,0x00,0x90,0x2B,0x78,0x21,0x46,0x1F,0x98,0xFE,0xF7,0x57,0xFB,0x00,0x28, + 0x1F,0xDB,0x28,0x88,0x03,0x21,0x89,0x03,0x08,0x43,0x28,0x80,0x05,0x9A,0x04,0x99, + 0x91,0x42,0x03,0xD2,0x80,0x0B,0x80,0x03,0xC9,0x01,0x03,0xE0,0x80,0x0B,0x80,0x03, + 0xD1,0x01,0x04,0x9A,0x11,0x43,0x89,0x04,0x89,0x0C,0x08,0x43,0x28,0x80,0x39,0xE7, + 0x26,0x4A,0x50,0x68,0x81,0x79,0x0A,0x29,0x00,0xD3,0x0A,0x21,0x10,0x78,0x81,0x42, + 0x03,0xD8,0x00,0x20,0xC0,0x43,0x21,0xB0,0xF0,0xBD,0x14,0x21,0x04,0x90,0x48,0x43, + 0x1F,0x49,0x22,0x07,0x3C,0x31,0x40,0x18,0x41,0x7C,0x12,0x0E,0x09,0x07,0x09,0x0F, + 0x11,0x43,0x0A,0x09,0x09,0x09,0x09,0x01,0x11,0x43,0x41,0x74,0x02,0x7C,0x09,0x07, + 0x12,0x09,0x09,0x0F,0x12,0x01,0x0A,0x43,0x02,0x74,0x81,0x7C,0x32,0x07,0x09,0x07, + 0x09,0x0F,0x12,0x0E,0x11,0x43,0x0A,0x09,0x09,0x09,0x09,0x01,0x11,0x43,0x81,0x74, + 0x02,0x7C,0x09,0x01,0x12,0x07,0x12,0x0F,0x0A,0x43,0x02,0x74,0x00,0x21,0x01,0x60, + 0x41,0x60,0x81,0x60,0x01,0x21,0xC1,0x81,0x0F,0x9A,0x82,0x81,0x28,0x88,0x23,0x46, + 0x82,0x04,0x92,0x0C,0x88,0x03,0x10,0x18,0x82,0x0B,0x04,0x98,0x92,0x03,0x02,0x43, + 0x2A,0x80,0x01,0x91,0x00,0x96,0x1F,0x9A,0x0F,0x99,0x0B,0xE0,0x30,0x00,0x00,0x20, + 0xA4,0x0A,0x00,0x20,0x01,0xFF,0x00,0x00,0x01,0xFF,0x01,0xFF,0x00,0x00,0x01,0xFF, + 0xFF,0xFF,0x01,0x01,0x04,0x98,0xFE,0xF7,0x45,0xFA,0x35,0x48,0x34,0x49,0x00,0x78, + 0x40,0x1C,0x08,0x70,0x21,0xE0,0x04,0x98,0x14,0x21,0x48,0x43,0x31,0x49,0x40,0x18, + 0x0C,0x21,0x10,0x90,0x41,0x5E,0x0F,0x98,0x81,0x42,0x08,0xDA,0x20,0x07,0x00,0x0F, + 0x31,0x01,0x08,0x43,0x10,0x99,0x08,0x74,0x10,0x99,0x0F,0x98,0x88,0x81,0x01,0x20, + 0x01,0x90,0x00,0x96,0x23,0x46,0x1F,0x9A,0x0F,0x99,0x04,0x98,0xFE,0xF7,0x22,0xFA, + 0x10,0x98,0x10,0x99,0xC0,0x89,0x40,0x1C,0xC8,0x81,0x00,0x24,0x30,0xE0,0x19,0xA8, + 0x00,0x57,0x0F,0x90,0x62,0x00,0x15,0xA9,0x89,0x5E,0x2A,0x88,0x1B,0xA8,0x00,0x57, + 0x92,0x0B,0x03,0x2A,0x02,0xD0,0x01,0x2A,0x16,0xD0,0x1F,0xE0,0x49,0x10,0xC6,0xB2, + 0x10,0x91,0x00,0x96,0x02,0x21,0x0F,0x98,0x01,0x91,0xC3,0xB2,0x1F,0x9A,0x10,0x99, + 0x04,0x98,0xFE,0xF7,0xFF,0xF9,0x02,0x20,0x01,0x90,0x00,0x96,0x0F,0x98,0x1F,0x9A, + 0xC3,0xB2,0x10,0x99,0x05,0x98,0x07,0xE0,0xC0,0xB2,0x00,0x90,0x0F,0x98,0x02,0x22, + 0x01,0x92,0xC3,0xB2,0x1F,0x9A,0x04,0x98,0xFE,0xF7,0xEC,0xF9,0x64,0x1C,0xE4,0xB2, + 0xBC,0x42,0xCC,0xD3,0x0D,0x98,0x08,0x49,0x88,0x42,0x00,0xD0,0xA5,0xE5,0x0B,0x98, + 0x40,0x1E,0x40,0xB2,0x0B,0x90,0x00,0x28,0x00,0xDB,0x9A,0xE5,0x00,0x20,0x42,0xE7, + 0x30,0x00,0x00,0x20,0xE0,0x0A,0x00,0x20,0xFF,0x3F,0x00,0x00,0x06,0x4A,0x10,0xB5, + 0x80,0x32,0xD3,0x6B,0x04,0x49,0xDA,0x78,0x1B,0x79,0x48,0x6D,0x09,0x6D,0x5A,0x43, + 0x01,0xF0,0xA4,0xF9,0x10,0xBD,0x00,0x00,0x44,0x00,0x00,0x20,0xFF,0xB5,0x81,0xB0, + 0x20,0x4D,0x06,0x46,0x0D,0x9C,0x00,0x20,0x6B,0x60,0x17,0x46,0x20,0x70,0x01,0xF0, + 0x3B,0xFA,0x3A,0x46,0x30,0x46,0x02,0x99,0x02,0xF0,0x28,0xFC,0x02,0x46,0x30,0x46, + 0x02,0x99,0xFF,0xF7,0x59,0xFD,0x00,0x28,0x01,0xDA,0x01,0x20,0x19,0xE0,0x28,0x78, + 0x00,0x28,0x04,0xD0,0x68,0x68,0xC0,0x7A,0x41,0x09,0x02,0xD0,0x06,0xE0,0x02,0x20, + 0x0F,0xE0,0x80,0x07,0x02,0xD5,0x02,0x98,0xFE,0xF7,0x5A,0xFE,0x68,0x68,0xC0,0x7A, + 0xC0,0x07,0x0A,0xD0,0x30,0x46,0x02,0x99,0x01,0xF0,0x84,0xFC,0x00,0x28,0x04,0xD0, + 0x03,0x20,0x20,0x70,0x00,0x20,0x05,0xB0,0xF0,0xBD,0x30,0x46,0x0B,0x9B,0x0A,0x9A, + 0x02,0x99,0x01,0xF0,0x97,0xFD,0x02,0x98,0x02,0xF0,0x22,0xF8,0x0C,0x98,0xFF,0xF7, + 0x71,0xF8,0xF0,0xE7,0x30,0x00,0x00,0x20,0xFF,0xB5,0xD3,0xB0,0x00,0x20,0x48,0xA9, + 0x08,0x77,0x34,0x48,0x1D,0x46,0x02,0x60,0x17,0x78,0x0A,0x2F,0x00,0xD3,0x0A,0x27, + 0x00,0x24,0x11,0xE0,0x38,0x20,0x26,0x46,0x46,0x43,0x70,0x19,0x81,0x78,0x00,0x29, + 0x08,0xD1,0xA9,0x57,0x49,0x1C,0x05,0xD0,0x38,0x21,0xFE,0xF7,0x0B,0xF8,0x00,0x20, + 0xC0,0x43,0xA8,0x55,0x64,0x1C,0xE4,0xB2,0xBC,0x42,0xEB,0xD3,0xFF,0x22,0x0C,0x21, + 0x4C,0xA8,0xFD,0xF7,0xDA,0xFF,0xFF,0x22,0x0A,0x21,0x50,0xA8,0xFD,0xF7,0xD5,0xFF, + 0x20,0x48,0x4F,0xA9,0x00,0x68,0x50,0xAA,0xC0,0x89,0x03,0x90,0x00,0x92,0x02,0x91, + 0x01,0x97,0x29,0x46,0x04,0xA8,0x54,0x9B,0x53,0x9A,0xFE,0xF7,0x7F,0xFC,0x48,0xA9, + 0x0B,0x7F,0x00,0x2B,0x0F,0xD0,0x54,0x99,0x00,0x29,0x0C,0xD0,0x01,0x2B,0x01,0xD1, + 0x01,0x29,0x1E,0xD0,0x00,0x22,0xD2,0x43,0x01,0x92,0x00,0x91,0x02,0x46,0x4C,0xA9, + 0x04,0xA8,0x00,0xF0,0x23,0xF8,0x4C,0xA8,0x00,0x90,0x50,0xAB,0x01,0x97,0x28,0x46, + 0x54,0x9A,0x53,0x99,0x05,0xF0,0x80,0xF9,0x28,0x46,0x00,0xF0,0x01,0xFB,0x39,0x46, + 0x28,0x46,0x04,0xF0,0x5D,0xFB,0x39,0x46,0x28,0x46,0x02,0xF0,0xD1,0xFD,0x57,0xB0, + 0xF0,0xBD,0x68,0x46,0x00,0x8A,0x04,0x49,0x88,0x42,0xE4,0xD0,0x00,0x20,0x48,0xA9, + 0x08,0x74,0xE0,0xE7,0x38,0x00,0x00,0x20,0xFF,0x7F,0x00,0x00,0xFF,0xB5,0x0E,0x46, + 0x04,0x46,0x15,0x46,0x00,0x20,0x11,0x46,0x9A,0xB0,0x69,0x43,0x8C,0x46,0x23,0x9F, + 0x05,0xE0,0x41,0x00,0x63,0x5A,0x18,0x4A,0xD2,0x1A,0x62,0x52,0x40,0x1C,0x84,0x45, + 0xF7,0xDC,0x16,0x48,0x0F,0xA9,0x05,0x70,0x44,0x60,0x0A,0xA8,0x01,0x91,0x00,0x90, + 0x05,0xAB,0x17,0xAA,0x14,0xA9,0x02,0xA8,0x04,0xF0,0xB6,0xFD,0x00,0x20,0xFF,0x21, + 0x01,0xE0,0x31,0x54,0x40,0x1C,0xB8,0x42,0xFB,0xDB,0x00,0x20,0x02,0xAB,0x0E,0xE0, + 0x19,0x56,0x00,0x29,0x0A,0xDB,0x1D,0x9A,0x91,0x42,0x07,0xDA,0x69,0x43,0x09,0x18, + 0x49,0x00,0x61,0x5A,0x00,0x29,0x01,0xD0,0x19,0x5C,0x31,0x54,0x40,0x1C,0xB8,0x42, + 0xEE,0xDB,0x1E,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0x7F,0x00,0x00,0x3C,0x00,0x00,0x20, + 0xF0,0xB5,0x91,0xB0,0x0A,0x91,0x6B,0x49,0x17,0x9D,0xC9,0x6B,0x16,0x9C,0x89,0x7B, + 0x17,0x46,0x00,0x29,0x7E,0xD0,0x0A,0x9A,0x1E,0x46,0x7A,0x43,0x0B,0x90,0x19,0x46, + 0x0F,0x92,0x01,0xF0,0x93,0xF8,0x00,0x20,0x0A,0xE0,0x41,0x00,0x6A,0x5E,0x02,0x2A, + 0x01,0xDA,0x02,0x22,0x00,0xE0,0x6A,0x5A,0x05,0xAB,0x40,0x1C,0x5A,0x52,0xC0,0xB2, + 0x0A,0x99,0x88,0x42,0xF1,0xD3,0x00,0x20,0x02,0x22,0x0B,0xE0,0x41,0x00,0x63,0x5E, + 0x02,0x2B,0x02,0xDA,0x6B,0x46,0x5A,0x52,0x02,0xE0,0x63,0x5A,0x6D,0x46,0x6B,0x52, + 0x40,0x1C,0xC0,0xB2,0xB8,0x42,0xF1,0xD3,0x00,0x25,0x97,0xE0,0x18,0x98,0x32,0x28, + 0x04,0xD2,0x69,0x00,0x05,0xA8,0x40,0x5A,0x14,0x28,0x7D,0xD9,0x28,0x46,0x78,0x43, + 0x00,0xB2,0x00,0x24,0x09,0x90,0x84,0xE0,0x00,0x20,0x18,0x9A,0x01,0x46,0x84,0x46, + 0x0D,0x90,0x32,0x2A,0x0A,0xD2,0x63,0x00,0x6A,0x46,0xD2,0x5A,0x14,0x2A,0x76,0xD9, + 0x09,0x9A,0x12,0x19,0x52,0x00,0xB2,0x5E,0x1E,0x2A,0x70,0xDB,0x6A,0x1E,0x09,0xD4, + 0x09,0x98,0x6A,0x00,0xC0,0x1B,0x00,0x19,0x40,0x00,0x05,0xA9,0x51,0x18,0x20,0x39, + 0x30,0x5E,0xC9,0x8B,0x09,0x9A,0x6B,0x00,0x12,0x19,0x52,0x00,0x0C,0x92,0xB2,0x5E, + 0x10,0x92,0x10,0x18,0x05,0xAA,0xD2,0x5A,0x0E,0x92,0x51,0x18,0x8E,0x46,0x0A,0x9A, + 0x69,0x1C,0x91,0x42,0x0B,0xD2,0x09,0x99,0xC9,0x19,0x09,0x19,0x49,0x00,0x71,0x5E, + 0x08,0x18,0x05,0xA9,0x59,0x18,0x4A,0x88,0x71,0x46,0x51,0x18,0x8E,0x46,0x61,0x1E, + 0x0D,0xD4,0x0C,0x99,0x8A,0x19,0x20,0x3A,0x1E,0x21,0x51,0x5E,0x0D,0x91,0x62,0x00, + 0x69,0x46,0x00,0xE0,0x4B,0xE0,0x51,0x18,0x20,0x39,0xC9,0x8B,0x8C,0x46,0x0D,0x9A, + 0x10,0x99,0x6B,0x46,0x89,0x18,0x62,0x00,0x0D,0x92,0x9A,0x5A,0x10,0x92,0x94,0x44, + 0x62,0x1C,0xBA,0x42,0x09,0xD2,0x0C,0x9A,0x02,0x23,0x92,0x19,0xD3,0x5E,0x0D,0x9A, + 0x59,0x18,0x6B,0x46,0xD2,0x18,0x52,0x88,0x94,0x44,0x00,0x28,0x00,0xDA,0x00,0x20, + 0x00,0x29,0x00,0xDA,0x00,0x21,0x62,0x46,0x93,0x08,0x72,0x46,0x92,0x08,0x94,0x46, + 0x0D,0x93,0x0D,0x9A,0x0E,0x9B,0x50,0x43,0x43,0x43,0x62,0x46,0x10,0x98,0x51,0x43, + 0x48,0x43,0x18,0x18,0x40,0x08,0x01,0xE0,0x0E,0xE0,0x08,0xE0,0x0D,0x9B,0x5A,0x43, + 0x91,0x00,0xFD,0xF7,0xB3,0xFE,0x0C,0x9A,0x0B,0x99,0x40,0x1C,0x88,0x52,0x64,0x1C, + 0xE4,0xB2,0xBC,0x42,0x00,0xD2,0x77,0xE7,0x6D,0x1C,0xED,0xB2,0x0A,0x98,0x85,0x42, + 0x00,0xD2,0x63,0xE7,0x30,0x46,0x0F,0x9A,0x0B,0x99,0x00,0xF0,0xCF,0xFF,0x11,0xB0, + 0xF0,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20,0x10,0xB5,0x0A,0x48,0x81,0x78,0x0A,0x48, + 0x00,0x29,0x81,0x88,0x08,0xD0,0xFF,0x22,0x12,0x01,0x11,0x43,0x81,0x80,0x05,0x48, + 0x01,0x21,0x40,0x38,0x01,0x70,0x10,0xBD,0x11,0x22,0x11,0x43,0x81,0x80,0x02,0xF0, + 0xD1,0xFE,0x10,0xBD,0x64,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0xF7,0xB5,0x06,0x46, + 0x1A,0x48,0x82,0xB0,0xC1,0x8A,0x01,0x91,0xFF,0x21,0xC1,0x82,0x18,0x48,0x00,0x90, + 0x1D,0xE0,0x04,0x98,0x80,0x47,0x30,0x70,0x00,0x0A,0x16,0x4D,0x70,0x70,0x28,0x7C, + 0x13,0x4C,0x01,0x27,0x60,0x34,0xE1,0x6B,0x4A,0x7C,0x39,0x46,0x91,0x40,0x88,0x43, + 0x28,0x74,0x28,0x21,0x03,0x98,0x00,0xF0,0x2D,0xF8,0x28,0x7C,0xE1,0x6B,0x49,0x7C, + 0x8F,0x40,0x38,0x43,0x28,0x74,0x0C,0x49,0xA0,0x20,0x88,0x80,0x00,0x98,0x40,0x7D, + 0x0A,0x28,0x05,0xD1,0x06,0x48,0xA0,0x30,0x40,0x68,0x80,0x78,0x0A,0x28,0xD8,0xD0, + 0x02,0x49,0x01,0x98,0xC8,0x82,0x05,0xB0,0xF0,0xBD,0x00,0x00,0x00,0x10,0x00,0x40, + 0x64,0x00,0x00,0x20,0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0x04,0x48,0x02,0x69, + 0x04,0x21,0x0A,0x43,0x02,0x61,0x30,0xBF,0x02,0x69,0x8A,0x43,0x02,0x61,0x70,0x47, + 0x00,0xED,0x00,0xE0,0x1C,0xB5,0x00,0x23,0x6A,0x46,0x13,0x80,0x0D,0xE0,0x6A,0x46, + 0x93,0x80,0x02,0xE0,0xA2,0x88,0x52,0x1C,0xA2,0x80,0x6A,0x46,0x92,0x88,0x6C,0x46, + 0x8A,0x42,0xF7,0xD3,0x22,0x88,0x52,0x1C,0x22,0x80,0x6A,0x46,0x12,0x88,0x82,0x42, + 0xED,0xD3,0x1C,0xBD,0xF0,0xB5,0x2E,0x4D,0xFF,0x27,0x68,0x7A,0x2D,0x4C,0x85,0xB0, + 0x01,0x28,0x0E,0xD0,0xFF,0xF7,0xF0,0xFA,0xE0,0x79,0xFF,0x28,0x05,0xD0,0x00,0x28, + 0x49,0xD0,0x40,0x1E,0x38,0x40,0xE0,0x71,0x45,0xD0,0x68,0x7A,0x00,0x28,0x45,0xD0, + 0x3D,0xE0,0x23,0x4B,0x01,0x22,0x00,0x20,0x80,0x33,0xDD,0x6B,0x59,0x69,0xEE,0x7A, + 0x0A,0xE0,0x38,0x23,0x43,0x43,0xCB,0x56,0x00,0x2B,0x03,0xDD,0x38,0x22,0x42,0x43, + 0x8A,0x5C,0x03,0xE0,0x40,0x1C,0xC0,0xB2,0x86,0x42,0xF2,0xD8,0x01,0x2A,0x06,0xD0, + 0x02,0x2A,0x04,0xD0,0x00,0xF0,0x94,0xFC,0xF1,0x28,0x15,0xD0,0x21,0xE0,0x00,0x22, + 0x00,0x92,0x01,0x92,0x02,0x92,0x38,0x22,0x50,0x43,0x20,0x30,0x08,0x18,0x01,0x88, + 0x6A,0x46,0x91,0x81,0x40,0x88,0xD0,0x81,0x40,0x35,0x6B,0x89,0x2A,0x89,0x14,0x21, + 0x03,0x98,0x04,0xF0,0x99,0xFE,0x0A,0xE0,0xE1,0x79,0xFF,0x29,0x05,0xD0,0x00,0x29, + 0x07,0xD0,0xE7,0x71,0xF1,0x20,0x05,0xB0,0xF0,0xBD,0x0A,0x20,0xE0,0x71,0x00,0x20, + 0xF9,0xE7,0xE7,0x71,0xF7,0xE7,0xE7,0x71,0xF0,0x20,0xF4,0xE7,0xFF,0x20,0xF2,0xE7, + 0x44,0x00,0x00,0x20,0x84,0x01,0x00,0x20,0xF0,0xB5,0x29,0x4E,0x30,0x46,0x80,0x30, + 0x32,0x46,0xC0,0x6B,0x14,0x32,0x3C,0xCA,0x84,0x46,0x81,0x7B,0x30,0x46,0x20,0x30, + 0x00,0x29,0x02,0xD0,0x11,0x46,0x19,0x43,0x03,0xD1,0x00,0x2C,0x01,0xD1,0x00,0x2D, + 0x02,0xD0,0x03,0x21,0x01,0x71,0x02,0xE0,0x01,0x79,0x00,0x29,0x02,0xD0,0xC9,0xB2, + 0x49,0x1E,0x01,0x71,0x61,0x46,0x89,0x7B,0x00,0x29,0x2F,0xD0,0x00,0x21,0x1F,0x46, + 0x2F,0x42,0x15,0xD1,0x2A,0x42,0x01,0xD0,0x01,0x21,0x0B,0xE0,0x15,0x46,0x25,0x42, + 0x01,0xD0,0x02,0x21,0x06,0xE0,0x00,0x2A,0x01,0xD0,0x0F,0x21,0x02,0xE0,0x23,0x42, + 0x06,0xD0,0x04,0x21,0x82,0x7D,0x01,0x23,0x8A,0x42,0x04,0xD0,0xF3,0x84,0x07,0xE0, + 0x00,0x22,0xF2,0x84,0x11,0xE0,0xF2,0x8C,0x19,0x24,0x64,0x01,0xA2,0x42,0x0C,0xD2, + 0xF2,0x8C,0x64,0x46,0x52,0x1C,0x92,0xB2,0xF2,0x84,0x24,0x7E,0xA2,0x42,0x04,0xD9, + 0xC2,0x7C,0x1A,0x43,0xC2,0x74,0x73,0x70,0xEA,0xE7,0x81,0x75,0xF0,0xBD,0x00,0x00, + 0x44,0x00,0x00,0x20,0x10,0xB5,0x04,0x48,0xC0,0x6B,0x20,0x30,0x40,0x7E,0x00,0x28, + 0x01,0xD0,0x02,0xF0,0x97,0xF9,0x10,0xBD,0xC4,0x00,0x00,0x20,0x70,0xB5,0x85,0x1A, + 0x00,0x2D,0x00,0xDC,0x15,0x1A,0xC8,0x1A,0x00,0x28,0x00,0xDC,0x58,0x1A,0x85,0x42, + 0x02,0xDA,0x45,0x40,0x68,0x40,0x45,0x40,0x01,0x2D,0x03,0xDD,0x40,0x43,0x06,0x46, + 0xA8,0x42,0x01,0xDC,0xA8,0xB2,0x70,0xBD,0x29,0x46,0xFD,0xF7,0x49,0xFD,0x40,0x10, + 0x44,0x19,0x6D,0x43,0xAE,0x19,0x25,0x46,0x29,0x46,0x30,0x46,0xFD,0xF7,0x40,0xFD, + 0x01,0x19,0x48,0x10,0xC9,0x07,0xC9,0x0F,0x44,0x18,0xAC,0x42,0x01,0xDD,0x60,0x1B, + 0x00,0xE0,0x28,0x1B,0x20,0x28,0xEE,0xDC,0xA0,0xB2,0x70,0xBD,0xF0,0xB5,0x08,0x4C, + 0x05,0x9F,0xA5,0x88,0x10,0x26,0x35,0x43,0xA5,0x80,0xE0,0x80,0x21,0x81,0x62,0x81, + 0xA3,0x81,0x67,0x80,0x06,0x98,0x20,0x80,0xA0,0x88,0xC0,0x06,0xFC,0xD5,0xF0,0xBD, + 0x00,0x11,0x00,0x40,0x06,0x4B,0xD8,0x80,0x59,0x81,0x98,0x88,0x10,0x21,0x08,0x43, + 0x98,0x80,0x5A,0x80,0x21,0x20,0x18,0x80,0x98,0x88,0xC0,0x06,0xFC,0xD5,0x70,0x47, + 0x00,0x11,0x00,0x40,0x10,0xB5,0x16,0x48,0x16,0x4C,0xC1,0x6B,0x11,0x23,0x88,0x7A, + 0x63,0x74,0x20,0x31,0x4A,0x7A,0x12,0x01,0xD2,0x1C,0x22,0x74,0x12,0x4A,0x02,0x28, + 0x04,0xD9,0x04,0x01,0x80,0x1E,0x04,0x43,0x54,0x72,0x01,0xE0,0x20,0x20,0x50,0x72, + 0xC8,0x7D,0x89,0x7D,0x80,0x00,0x09,0x01,0x08,0x43,0x41,0x21,0x08,0x43,0x10,0x72, + 0x0A,0x48,0x83,0x80,0x01,0x80,0x00,0x21,0x01,0x20,0x03,0xF0,0xFD,0xFF,0x02,0x20, + 0x04,0xF0,0xD8,0xF8,0x02,0x48,0x00,0x21,0x60,0x38,0xC1,0x75,0x10,0xBD,0x00,0x00, + 0xC4,0x00,0x00,0x20,0xE0,0x12,0x00,0x40,0x00,0x03,0x00,0x40,0x00,0x10,0x00,0x40, + 0xF1,0xB5,0x85,0xB0,0x00,0x27,0x78,0x1C,0xC6,0xB2,0x04,0x90,0x32,0xE0,0x38,0x20, + 0x05,0x99,0x78,0x43,0x45,0x18,0x68,0x79,0x01,0x28,0x29,0xD9,0x38,0x20,0x70,0x43, + 0x44,0x18,0x60,0x79,0x01,0x28,0x23,0xD9,0xA1,0x89,0x68,0x46,0x01,0x80,0xE1,0x89, + 0x41,0x80,0x21,0x8C,0x81,0x80,0x61,0x8C,0xC1,0x80,0xA9,0x89,0x01,0x81,0xE9,0x89, + 0x41,0x81,0x29,0x8C,0x81,0x81,0x69,0x8C,0xC1,0x81,0x00,0x9B,0x01,0x9A,0x02,0x99, + 0x03,0x98,0x01,0xF0,0xCD,0xFB,0x00,0x28,0x0A,0xD0,0xA8,0x89,0x6A,0x46,0x10,0x80, + 0xE9,0x89,0x51,0x80,0xA2,0x89,0xAA,0x81,0xE2,0x89,0xEA,0x81,0xA0,0x81,0xE1,0x81, + 0x76,0x1C,0xF6,0xB2,0x06,0x2E,0xCA,0xD3,0x04,0x98,0xC7,0xB2,0x05,0x2F,0xC2,0xD3, + 0x06,0xB0,0xF0,0xBD,0xFF,0xB5,0x07,0x46,0x3D,0x48,0x85,0xB0,0x81,0x6A,0x01,0x91, + 0x01,0x46,0x80,0x39,0x09,0x7A,0x01,0x29,0x01,0xD1,0x40,0x6B,0x01,0x90,0x39,0x49, + 0x00,0x20,0xC8,0x81,0x65,0xE0,0x00,0x20,0x04,0x90,0x02,0x98,0x04,0x25,0x80,0x00, + 0x00,0x90,0x02,0x98,0x01,0x24,0x46,0x00,0x01,0x9A,0x00,0x99,0x03,0x94,0x80,0x20, + 0x51,0x58,0x20,0x43,0x20,0x39,0xC8,0x77,0x01,0x22,0x80,0x21,0x38,0x46,0x02,0xF0, + 0xDF,0xFE,0xB9,0x5F,0x19,0x20,0x40,0x01,0x81,0x42,0x09,0xDA,0xAC,0x42,0x0F,0xDD, + 0x00,0x2D,0x00,0xDD,0x6D,0x10,0x00,0x2D,0x0A,0xD0,0x60,0x1B,0xC4,0xB2,0xE3,0xE7, + 0x60,0x19,0xC4,0xB2,0x0E,0x98,0x84,0x42,0xDE,0xD3,0x04,0x98,0x00,0x28,0x22,0xD0, + 0x03,0x98,0x80,0x21,0x08,0x43,0x01,0x9A,0x00,0x99,0x51,0x58,0x20,0x39,0xC8,0x77, + 0x01,0x22,0x80,0x21,0x38,0x46,0x02,0xF0,0xBB,0xFE,0xBD,0x5F,0x01,0x22,0x80,0x21, + 0x38,0x46,0x02,0xF0,0xB5,0xFE,0xBC,0x5F,0x01,0x22,0x80,0x21,0x38,0x46,0x02,0xF0, + 0xAF,0xFE,0xAC,0x42,0x02,0xDD,0x28,0x46,0x25,0x46,0x04,0x46,0xB8,0x5F,0xA0,0x42, + 0x05,0xDC,0xBC,0x53,0x06,0xE0,0x01,0x20,0x0E,0x9C,0x04,0x90,0xB4,0xE7,0xA8,0x42, + 0x00,0xDB,0xBD,0x53,0x03,0x98,0x28,0x21,0x80,0x06,0x80,0x0E,0x48,0x43,0xB9,0x5B, + 0x40,0x18,0x06,0x99,0x08,0x80,0x06,0x98,0x80,0x1C,0x06,0x90,0x02,0x98,0x40,0x1C, + 0xC0,0xB2,0x02,0x90,0x07,0x99,0x88,0x42,0x95,0xD3,0x09,0xB0,0xF0,0xBD,0x00,0x00, + 0xC4,0x00,0x00,0x20,0x00,0x10,0x00,0x40,0x14,0x49,0xCA,0x6B,0x40,0x32,0x12,0x7B, + 0x02,0x70,0xCA,0x6B,0x20,0x32,0x52,0x7A,0x42,0x70,0xC9,0x6B,0x89,0x7A,0x81,0x70, + 0x0F,0x49,0x8A,0x7C,0x92,0x06,0x92,0x0E,0xC2,0x70,0x89,0x7C,0x00,0x21,0x01,0x71, + 0x0C,0x49,0xCA,0x88,0x52,0x05,0x52,0x0E,0x42,0x71,0xCA,0x88,0x12,0x07,0x12,0x0F, + 0x82,0x71,0xCA,0x89,0xC2,0x71,0x4A,0x89,0x52,0x06,0x52,0x0E,0x02,0x72,0x0A,0x89, + 0x12,0x0A,0x42,0x72,0x09,0x89,0x81,0x72,0x70,0x47,0x00,0x00,0xC4,0x00,0x00,0x20, + 0xE0,0x12,0x00,0x40,0x00,0x10,0x00,0x40,0x07,0x49,0x09,0x7A,0x01,0x70,0x06,0x49, + 0x80,0x39,0x49,0x7E,0x41,0x70,0x04,0x49,0x60,0x39,0x09,0x79,0x81,0x70,0x03,0x49, + 0x09,0x78,0xC1,0x70,0x70,0x47,0x00,0x00,0x84,0x01,0x00,0x20,0x44,0x00,0x00,0x20, + 0x10,0xB5,0x06,0x48,0x05,0x4B,0xC0,0x6B,0x80,0x3B,0x82,0x79,0x40,0x79,0x59,0x6D, + 0x42,0x43,0x98,0x6C,0x00,0xF0,0xEA,0xFC,0x10,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20, + 0xF8,0xB5,0x0F,0x46,0x06,0x46,0x00,0x92,0x00,0xF0,0x58,0xF9,0x05,0x1E,0x00,0xDC, + 0x68,0x42,0x80,0xB2,0x01,0xF0,0xC8,0xFF,0x04,0x46,0x00,0x2D,0x02,0xDA,0xB4,0x20, + 0x00,0x1B,0x84,0xB2,0x39,0x46,0x30,0x46,0x00,0x9A,0x01,0xF0,0xAB,0xF8,0x00,0x28, + 0x05,0xD0,0x00,0x2C,0x03,0xD0,0xFF,0x20,0x69,0x30,0x00,0x1B,0x84,0xB2,0x20,0x46, + 0xF8,0xBD,0x00,0x00,0xFF,0xB5,0x8F,0xB0,0x9E,0x46,0x68,0x46,0x01,0x70,0x00,0x23, + 0x70,0x46,0x03,0x70,0x14,0x20,0x41,0x43,0x37,0x48,0x01,0x22,0x09,0x18,0x52,0x1E, + 0xD2,0xB2,0x68,0x46,0x80,0x5C,0x14,0x23,0x84,0x46,0x58,0x43,0x32,0x4B,0xC0,0x18, + 0xC3,0x7C,0x1C,0x07,0x24,0x0F,0x02,0x2C,0x0D,0xD0,0x1B,0x09,0x1B,0x01,0x9B,0x1C, + 0xC3,0x74,0x73,0x46,0x1C,0x78,0x11,0x9B,0x60,0x46,0x18,0x55,0x70,0x46,0x00,0x78, + 0x73,0x46,0x40,0x1C,0x18,0x70,0x29,0x48,0x00,0x25,0x40,0x78,0x0E,0x90,0x44,0xE0, + 0x0E,0x20,0x2E,0x46,0x46,0x43,0x24,0x48,0xC8,0x30,0x37,0x18,0xB8,0x7A,0x04,0x07, + 0x24,0x0F,0x64,0x45,0x01,0xD1,0x04,0x09,0x02,0xE0,0x00,0x09,0x60,0x45,0x31,0xD1, + 0x00,0x2C,0x2F,0xDB,0x38,0x7B,0x01,0x28,0x2C,0xD1,0x20,0x46,0x14,0x23,0x58,0x43, + 0x19,0x4B,0xC0,0x18,0xC3,0x7C,0x1B,0x07,0x24,0xD1,0x17,0x4F,0xC3,0x89,0xC8,0x37, + 0xBE,0x5B,0x0C,0x27,0x9B,0x19,0xC3,0x81,0x0C,0x26,0xCF,0x5F,0x86,0x5F,0xB7,0x42, + 0x0F,0xDA,0x8E,0x81,0x0B,0x7C,0x07,0x7C,0x1E,0x07,0x3F,0x09,0x36,0x0F,0x3F,0x01, + 0x3E,0x43,0x0E,0x74,0x07,0x7C,0x36,0x09,0x36,0x01,0x3F,0x07,0x3F,0x0F,0x3E,0x43, + 0x0E,0x74,0x6B,0x46,0x9C,0x54,0xC3,0x7C,0x52,0x1C,0x1B,0x09,0x1B,0x01,0x5B,0x1C, + 0xD2,0xB2,0xC3,0x74,0x6D,0x1C,0x0E,0x98,0xED,0xB2,0x85,0x42,0xB8,0xD3,0x00,0x2A, + 0x95,0xD1,0x13,0xB0,0xF0,0xBD,0x00,0x00,0xE0,0x0A,0x00,0x20,0x30,0x00,0x00,0x20, + 0xFF,0xB5,0x83,0xB0,0x05,0x46,0x01,0x20,0x05,0x99,0x0E,0x9E,0x1F,0x46,0x48,0x55, + 0x00,0x24,0x16,0xE0,0x38,0x5D,0x00,0x28,0x12,0xD1,0x0C,0x98,0x6A,0x00,0x83,0x5E, + 0x0D,0x9A,0x60,0x00,0x12,0x5E,0x69,0x43,0x9A,0x18,0x14,0x4B,0x09,0x19,0x5B,0x68, + 0x49,0x00,0x59,0x5A,0x51,0x1A,0x0B,0xD0,0x32,0x5E,0x8A,0x42,0x00,0xDD,0x31,0x52, + 0x64,0x1C,0x0E,0x48,0x01,0x78,0x8C,0x42,0xE4,0xDB,0x00,0x20,0x07,0xB0,0xF0,0xBD, + 0x01,0x20,0x38,0x55,0x04,0x98,0x00,0x57,0x41,0x1C,0x0B,0xD0,0x0C,0x99,0x0D,0x9A, + 0x00,0x91,0x01,0x92,0x3B,0x46,0x02,0x96,0x05,0x9A,0x04,0x99,0xFF,0xF7,0xC8,0xFF, + 0x00,0x28,0xE5,0xD0,0x04,0x98,0x05,0x55,0x01,0x20,0xE7,0xE7,0x3C,0x00,0x00,0x20, + 0xFF,0xB5,0xA3,0xB0,0x98,0x00,0x2D,0x9F,0x2C,0x9D,0x91,0x00,0xAB,0x00,0x00,0x90, + 0xBA,0x00,0x01,0xA8,0x0E,0xC0,0x2B,0x4D,0x00,0x26,0x68,0x68,0x34,0x46,0xC3,0x7F, + 0x1E,0x22,0x04,0xA9,0x13,0xA8,0x00,0xF0,0x8C,0xFB,0x01,0x90,0x68,0x68,0x01,0x7A, + 0x01,0x98,0x81,0x42,0x44,0xD8,0x68,0x46,0x00,0x8A,0x00,0x90,0x10,0xA8,0x83,0x89, + 0x08,0x22,0x21,0x49,0x24,0x98,0x00,0xF0,0xC9,0xF8,0x07,0x46,0x01,0x25,0x34,0xE0, + 0x68,0x00,0x04,0xA9,0x09,0x5A,0x00,0x91,0x13,0xA9,0x0B,0x5A,0x08,0x22,0x1A,0x49, + 0x24,0x98,0x00,0xF0,0xBB,0xF8,0x00,0x2C,0x0B,0xD0,0x7D,0x23,0x2E,0x9A,0x7D,0x21, + 0xDB,0x00,0xC9,0x00,0xD2,0x18,0x41,0x43,0x7A,0x43,0x91,0x42,0x01,0xD9,0x76,0x1C, + 0xF6,0xB2,0x7D,0x23,0x2E,0x9A,0x7D,0x21,0xDB,0x00,0xC9,0x00,0x9A,0x1A,0x41,0x43, + 0x7A,0x43,0x91,0x42,0x01,0xD2,0x64,0x1C,0xE4,0xB2,0x07,0x46,0x09,0x48,0x31,0x19, + 0x40,0x68,0x00,0x7A,0x81,0x42,0x06,0xD3,0x01,0x2E,0x04,0xD9,0x01,0x2C,0x02,0xD9, + 0x00,0x20,0x27,0xB0,0xF0,0xBD,0x6D,0x1C,0xED,0xB2,0x01,0x98,0x85,0x42,0xC7,0xD3, + 0x01,0x20,0xF6,0xE7,0x30,0x00,0x00,0x20,0xF4,0x7B,0x00,0x00,0x10,0xB5,0x09,0x49, + 0x00,0x20,0x49,0x7C,0x00,0x29,0x01,0xD0,0xFF,0xF7,0x4C,0xFC,0x06,0x49,0x0A,0x46, + 0x08,0x72,0x40,0x3A,0x92,0x7F,0x05,0x2A,0x02,0xD9,0x80,0x22,0x10,0x43,0x08,0x72, + 0x10,0xBD,0x00,0x00,0x64,0x00,0x00,0x20,0x84,0x01,0x00,0x20,0xF7,0xB5,0x84,0xB0, + 0x68,0x46,0x40,0x8B,0x00,0x90,0x68,0x46,0x00,0x8B,0x01,0x90,0x68,0x46,0xC7,0x8A, + 0x84,0x8A,0x39,0x46,0x20,0x46,0x00,0x9B,0x01,0x9A,0xFF,0xF7,0xEF,0xFC,0x02,0x90, + 0x68,0x46,0x46,0x8A,0x05,0x8A,0x3B,0x46,0x22,0x46,0x31,0x46,0x28,0x46,0xFF,0xF7, + 0xE5,0xFC,0x04,0x46,0x31,0x46,0x28,0x46,0x00,0x9B,0x01,0x9A,0xFF,0xF7,0xDE,0xFC, + 0x00,0x2C,0x12,0xD0,0x00,0x28,0x10,0xD0,0x21,0x46,0x02,0x46,0x61,0x43,0x42,0x43, + 0x8A,0x18,0x02,0x99,0x49,0x43,0x51,0x1A,0x8A,0x02,0x21,0x46,0x41,0x43,0x10,0x46, + 0xFD,0xF7,0x2E,0xFA,0x00,0xB2,0x07,0xB0,0xF0,0xBD,0x00,0x20,0xC0,0x43,0xFA,0xE7, + 0x01,0x46,0xFF,0x22,0x0A,0x39,0x56,0x32,0x91,0x42,0x01,0xD3,0x01,0x20,0x70,0x47, + 0x50,0x28,0x01,0xD8,0x02,0x20,0x70,0x47,0x64,0x28,0x01,0xD2,0x03,0x20,0x70,0x47, + 0xAA,0x28,0x01,0xD8,0x04,0x20,0x70,0x47,0xBE,0x28,0x01,0xD2,0x05,0x20,0x70,0x47, + 0xFF,0x21,0x05,0x31,0x88,0x42,0x01,0xD8,0x06,0x20,0x70,0x47,0xFF,0x21,0x19,0x31, + 0x88,0x42,0x01,0xD2,0x07,0x20,0x70,0x47,0x08,0x20,0x70,0x47,0x06,0x49,0x49,0x68, + 0xCA,0x78,0x80,0x1A,0x0A,0x79,0x89,0x78,0x10,0x41,0x00,0xB2,0x4A,0x1E,0x82,0x42, + 0x00,0xDA,0x10,0x46,0x40,0xB2,0x70,0x47,0x30,0x00,0x00,0x20,0xFF,0xB5,0x47,0x48, + 0x8B,0xB0,0x40,0x68,0x8E,0x46,0xC4,0x7F,0x08,0x94,0xA4,0x00,0x0A,0x94,0x80,0x7F, + 0x80,0x00,0x09,0x90,0x00,0x20,0x84,0x46,0x00,0x90,0x50,0x42,0x42,0xB2,0x18,0xB2, + 0x06,0x90,0x14,0x98,0x07,0x92,0x00,0xB2,0x05,0x90,0x68,0xE0,0x07,0x99,0x62,0xE0, + 0x04,0x25,0x10,0x46,0x08,0x43,0x14,0xD0,0x00,0x2A,0x19,0xD0,0x14,0x98,0x00,0x29, + 0x1F,0xD0,0x80,0x18,0x6E,0x46,0xB0,0x80,0x5F,0x18,0xB7,0x81,0xF0,0x80,0x5C,0x1A, + 0xF4,0x81,0x14,0x98,0x80,0x1A,0x30,0x81,0x37,0x82,0x70,0x81,0x74,0x82,0x00,0x24, + 0x42,0xE0,0x6C,0x46,0x05,0x98,0xA0,0x80,0x06,0x98,0xA0,0x81,0x01,0x25,0xF6,0xE7, + 0x6C,0x46,0x05,0x98,0xA0,0x80,0x58,0x18,0xA0,0x81,0x05,0x98,0xE0,0x80,0x58,0x1A, + 0x08,0xE0,0x80,0x18,0x6C,0x46,0xA0,0x80,0x06,0x98,0xA0,0x81,0x14,0x98,0x80,0x1A, + 0xE0,0x80,0x06,0x98,0xE0,0x81,0x02,0x25,0xE1,0xE7,0x67,0x00,0x03,0xA8,0xC6,0x5F, + 0x00,0x2E,0x1F,0xDB,0x0A,0x98,0x86,0x42,0x1C,0xDA,0x01,0xA8,0xC7,0x5F,0x00,0x2F, + 0x18,0xDB,0x09,0x98,0x87,0x42,0x15,0xDA,0xB0,0x07,0x13,0xD1,0xB8,0x07,0x11,0xD1, + 0x08,0x98,0x47,0x43,0xB8,0x19,0x80,0x10,0x76,0x46,0x00,0xB2,0x37,0x88,0x46,0x00, + 0x0B,0x98,0x80,0x5F,0x00,0x28,0x00,0xDA,0x00,0x20,0x78,0x43,0x84,0x44,0x00,0x98, + 0xC0,0x19,0x00,0x90,0x64,0x1C,0x24,0xB2,0xAC,0x42,0xD6,0xDB,0x70,0x46,0x80,0x1C, + 0x49,0x1C,0x86,0x46,0x49,0xB2,0x00,0x29,0x9A,0xDD,0x52,0x1C,0x52,0xB2,0x00,0x2A, + 0x94,0xDD,0x00,0x98,0x00,0x28,0x04,0xD0,0x01,0x46,0x60,0x46,0xFD,0xF7,0x5E,0xF9, + 0x84,0x46,0x60,0x46,0x00,0xB2,0x0F,0xB0,0xF0,0xBD,0x00,0x00,0x30,0x00,0x00,0x20, + 0xF0,0xB5,0x00,0x24,0xE5,0xB0,0x25,0x46,0xFE,0x49,0x6A,0x46,0x88,0x88,0x10,0x84, + 0x1C,0x90,0xC8,0x88,0x50,0x84,0x1B,0x90,0x08,0x46,0x7C,0x30,0x1E,0x90,0x03,0x88, + 0x93,0x84,0x40,0x88,0xD0,0x84,0x48,0x78,0x03,0x28,0x2F,0xD3,0x00,0x26,0x28,0xE0, + 0xB1,0x00,0x0F,0x18,0xB9,0x89,0x10,0xA8,0x01,0x85,0xF9,0x89,0x41,0x85,0x39,0x89, + 0x81,0x84,0x79,0x89,0xC1,0x84,0x1A,0x99,0x19,0x98,0xFE,0xF7,0x7B,0xF8,0x1D,0x90, + 0x39,0x89,0x10,0xA8,0x01,0x85,0x79,0x89,0x41,0x85,0xB9,0x88,0x81,0x84,0xF9,0x88, + 0xC1,0x84,0x1A,0x99,0x19,0x98,0xFE,0xF7,0x6D,0xF8,0x1D,0x99,0xFE,0xF7,0x75,0xF8, + 0x73,0x00,0x27,0xA9,0xC8,0x52,0xFF,0xF7,0xFB,0xFE,0x4D,0xA9,0x76,0x1C,0xC8,0x52, + 0xB6,0xB2,0xE0,0x48,0x41,0x78,0x89,0x1E,0xB1,0x42,0xD1,0xDC,0xDD,0x4A,0x00,0x20, + 0x52,0x78,0x19,0x92,0x69,0x46,0x92,0x1E,0x12,0xE0,0x00,0x23,0xDB,0x43,0x0B,0x54, + 0x00,0x26,0x43,0x00,0x0A,0xAF,0xFE,0x52,0x1F,0xAF,0x3E,0x54,0x76,0x1E,0x5C,0xAF, + 0x3E,0x54,0x00,0x26,0x36,0xAF,0xFE,0x52,0x45,0xAB,0x1E,0x54,0x40,0x1C,0x80,0xB2, + 0x82,0x42,0xEA,0xDC,0x00,0x20,0x5D,0xE0,0x46,0x00,0x4D,0xAB,0x9B,0x5B,0x9C,0x46, + 0x05,0x2B,0x7B,0xD0,0x27,0xAF,0xBB,0x5B,0xB4,0x2B,0x22,0xD2,0x66,0x46,0xB6,0x1E, + 0x02,0x2E,0x18,0xD8,0x00,0x2C,0x04,0xD0,0x0E,0x19,0x20,0x3E,0xF6,0x7F,0x01,0x2E, + 0x0B,0xD1,0x64,0x1C,0xE4,0xB2,0x0F,0x19,0x02,0x26,0x20,0x3F,0xFE,0x77,0x1F,0xAE, + 0x36,0x19,0x20,0x3E,0xF7,0x7F,0x7F,0x1C,0xF7,0x77,0x1F,0xAE,0x36,0x19,0x20,0x3E, + 0xF7,0x7F,0x7F,0x1C,0xF7,0x77,0x0E,0x19,0x20,0x3E,0xF6,0x7F,0x02,0x2E,0x28,0xD0, + 0x2E,0xE0,0xFF,0x27,0x69,0x37,0xFB,0x1A,0x9B,0xB2,0x27,0xAF,0xBB,0x53,0x66,0x46, + 0xB6,0x1F,0x02,0x2E,0x18,0xD8,0x00,0x2C,0x04,0xD0,0x0E,0x19,0x20,0x3E,0xF6,0x7F, + 0x02,0x2E,0x0B,0xD1,0x64,0x1C,0xE4,0xB2,0x0F,0x19,0x01,0x26,0x20,0x3F,0xFE,0x77, + 0x1F,0xAE,0x36,0x19,0x20,0x3E,0xF7,0x7F,0x7F,0x1C,0xF7,0x77,0x1F,0xAE,0x36,0x19, + 0x20,0x3E,0xF7,0x7F,0x7F,0x1C,0xF7,0x77,0x0E,0x19,0x20,0x3E,0xF6,0x7F,0x01,0x2E, + 0x06,0xD1,0x67,0x00,0x0A,0xAE,0xBE,0x19,0x40,0x3E,0xF7,0x8F,0xFB,0x18,0xF3,0x87, + 0x40,0x1C,0x80,0xB2,0x82,0x42,0x9F,0xDC,0x00,0x20,0x19,0xE0,0x1F,0xA9,0x0B,0x5C, + 0x04,0x2B,0x04,0xD8,0x46,0x00,0x0A,0xAB,0x9B,0x5B,0x3C,0x2B,0x0E,0xD3,0x0B,0x5C, + 0x45,0xA9,0x4B,0x55,0x43,0x00,0x0A,0xA9,0xCB,0x5A,0x6E,0x00,0x36,0xA9,0x8B,0x53, + 0x69,0x46,0x0B,0x5C,0x5C,0xA9,0x4B,0x55,0x6D,0x1C,0xED,0xB2,0x40,0x1C,0x80,0xB2, + 0xA0,0x42,0xE3,0xD3,0x00,0x23,0x18,0x46,0x19,0x46,0x2C,0xE0,0x44,0xE0,0x5C,0xAE, + 0x74,0x56,0xA4,0x46,0x9C,0x42,0x10,0xD0,0x73,0x5C,0x45,0xAC,0x66,0x5C,0x1F,0xAC, + 0x26,0x54,0x4E,0x00,0x36,0xAC,0xA6,0x5B,0x47,0x00,0x0A,0xAC,0xE6,0x53,0x64,0x46, + 0x6E,0x46,0x34,0x54,0x40,0x1C,0xC0,0xB2,0x13,0xE0,0x1F,0xAC,0x24,0x18,0x20,0x3C, + 0x45,0xAE,0xE7,0x7F,0x76,0x5C,0xBE,0x19,0xE6,0x77,0x46,0x00,0x0A,0xAC,0x34,0x19, + 0x40,0x3C,0xA4,0x46,0xE6,0x8F,0x4F,0x00,0x36,0xAC,0xE4,0x5B,0x36,0x19,0x64,0x46, + 0xE6,0x87,0x49,0x1C,0x89,0xB2,0xA9,0x42,0xD1,0xD3,0x19,0x99,0x75,0x4F,0x02,0x29, + 0x06,0xD8,0xB8,0x78,0x00,0x1F,0x4C,0x28,0x0E,0xD2,0xF1,0x20,0x65,0xB0,0xF0,0xBD, + 0x00,0x28,0x0A,0xD0,0xFF,0x21,0x0F,0x31,0x01,0x28,0x2D,0xD0,0x02,0x28,0x74,0xD0, + 0x03,0x28,0x73,0xD0,0x04,0x28,0x72,0xD0,0xF1,0xE0,0x1E,0x98,0x6A,0x46,0x01,0x88, + 0x91,0x84,0x40,0x88,0xD0,0x84,0xB8,0x88,0x10,0x84,0xF8,0x88,0x50,0x84,0x09,0x99, + 0x08,0x98,0xFD,0xF7,0x67,0xFF,0x01,0x46,0xFF,0x22,0x2D,0x39,0x10,0x32,0x91,0x42, + 0x01,0xD3,0xA0,0x20,0xDA,0xE7,0x01,0x46,0x2E,0x39,0x59,0x29,0x01,0xD2,0xA1,0x20, + 0xD4,0xE7,0x01,0x46,0x88,0x39,0x59,0x29,0x01,0xD2,0xA2,0x20,0xCE,0xE7,0xE2,0x38, + 0x59,0x28,0x72,0xD2,0xA3,0x20,0xC9,0xE7,0x56,0x4C,0x80,0x34,0xA0,0x88,0xE3,0x88, + 0xC0,0x18,0x40,0x08,0x10,0xAB,0x98,0x84,0x20,0x88,0x63,0x88,0xC0,0x18,0x40,0x08, + 0x10,0xAB,0xD8,0x84,0x6B,0x46,0x18,0x8D,0xFF,0x23,0xC3,0x33,0x98,0x42,0x5C,0xD8, + 0x88,0x42,0x29,0xD9,0x09,0x9A,0x08,0x99,0x19,0x98,0xFF,0xF7,0x31,0xFC,0x05,0x46, + 0x68,0x46,0xC3,0x8C,0x82,0x8C,0x41,0x8C,0x00,0x8C,0xFF,0xF7,0x87,0xFA,0x1E,0x28, + 0x18,0xD3,0x28,0x46,0xFF,0x21,0x1E,0x38,0x2E,0x31,0x88,0x42,0x12,0xD2,0xB4,0x2D, + 0x2E,0xD8,0xE1,0x88,0xA0,0x88,0x09,0x1A,0x89,0x10,0x09,0x18,0x1C,0x98,0x81,0x42, + 0x08,0xDD,0x21,0x88,0x1B,0x98,0x88,0x42,0x04,0xD9,0x61,0x88,0x88,0x42,0x01,0xD2, + 0x65,0x20,0x8B,0xE7,0x6F,0x20,0x89,0xE7,0x3C,0x28,0x2E,0xD9,0x00,0x21,0xFF,0x26, + 0x0C,0x46,0x08,0x46,0x69,0x36,0x27,0xAD,0x0E,0xE0,0x38,0xE0,0x51,0xE0,0x70,0xE0, + 0x43,0x00,0xEB,0x5A,0xB4,0x2B,0x00,0xD9,0xF3,0x1A,0x9B,0xB2,0x8B,0x42,0x01,0xD9, + 0x04,0x46,0x19,0x46,0x40,0x1C,0x80,0xB2,0x82,0x42,0xF1,0xDC,0x5A,0x29,0x01,0xD2, + 0x63,0x20,0x6B,0xE7,0xA0,0x00,0xC0,0x19,0x01,0x89,0x6A,0x46,0x11,0x84,0x40,0x89, + 0x50,0x84,0x19,0x99,0x08,0x98,0xFD,0xF7,0xE5,0xFE,0x01,0x46,0xFF,0x22,0x2D,0x39, + 0x10,0x32,0x91,0x42,0x02,0xD3,0x3C,0x20,0x58,0xE7,0x58,0xE0,0x01,0x46,0x2E,0x39, + 0x59,0x29,0x01,0xD2,0x76,0x20,0x51,0xE7,0x01,0x46,0x88,0x39,0x59,0x29,0x01,0xD2, + 0x3E,0x20,0x4B,0xE7,0xE2,0x38,0x59,0x28,0x49,0xD2,0x5E,0x20,0x46,0xE7,0x6A,0x46, + 0x00,0x20,0x10,0x56,0x01,0x28,0x08,0xD1,0x12,0x8D,0x8A,0x42,0x05,0xD2,0x6A,0x46, + 0x52,0x8D,0x8A,0x42,0x01,0xD2,0x73,0x20,0x38,0xE7,0x02,0x28,0x37,0xD1,0x68,0x46, + 0x00,0x8D,0x88,0x42,0x33,0xD2,0x68,0x46,0x40,0x8D,0x88,0x42,0x2F,0xD2,0x7A,0x20, + 0x2C,0xE7,0x69,0x46,0x00,0x20,0x08,0x56,0x01,0x28,0x0F,0xD1,0x09,0x8D,0xDC,0x29, + 0x0C,0xD2,0x69,0x46,0x49,0x8D,0xDC,0x29,0x08,0xD2,0x69,0x46,0x89,0x8D,0xDC,0x29, + 0x04,0xD2,0x01,0xE0,0xC0,0x0C,0x00,0x20,0x77,0x20,0x17,0xE7,0x02,0x28,0x16,0xD1, + 0x68,0x46,0x00,0x8D,0x0D,0xE0,0x68,0x46,0x80,0x8D,0xDC,0x28,0x0F,0xD2,0x6D,0x20, + 0x0C,0xE7,0x68,0x46,0x00,0x78,0x01,0x28,0x09,0xD1,0x68,0x46,0x00,0x8D,0x5A,0x28, + 0x05,0xD9,0xDC,0x28,0x03,0xD2,0x68,0x46,0x40,0x8D,0xDC,0x28,0xEB,0xD3,0x00,0x20, + 0xFC,0xE6,0xFF,0xB5,0x83,0xB0,0x0C,0xAC,0x0F,0xCC,0x00,0x25,0xFF,0xF7,0xD6,0xF9, + 0x00,0x90,0x00,0x20,0x07,0x46,0x04,0x46,0x01,0x90,0x00,0x98,0x00,0x28,0x2E,0xD0, + 0x26,0xE0,0x0C,0x99,0x0E,0x98,0x40,0x1A,0x68,0x43,0x00,0x99,0xFC,0xF7,0x28,0xFF, + 0x0C,0x99,0x40,0x18,0x06,0xB2,0x0D,0x99,0x0F,0x98,0x40,0x1A,0x68,0x43,0x00,0x99, + 0xFC,0xF7,0x1E,0xFF,0x0D,0x99,0x40,0x18,0x00,0xB2,0x00,0x2C,0x04,0xD0,0x01,0x99, + 0xB1,0x42,0x01,0xD1,0x87,0x42,0x09,0xD0,0x61,0x00,0x03,0x9A,0x64,0x1C,0x56,0x52, + 0x04,0x9A,0x87,0xB2,0x50,0x52,0xB1,0xB2,0xA4,0xB2,0x01,0x91,0x6D,0x1C,0xAD,0xB2, + 0x00,0x98,0x85,0x42,0x02,0xD8,0x05,0x98,0x84,0x42,0xD2,0xD3,0xE0,0xB2,0x07,0xB0, + 0xF0,0xBD,0x00,0x00,0x06,0x49,0x8A,0x7D,0x06,0x48,0xC0,0x6B,0x43,0x7A,0x9A,0x43, + 0x8A,0x75,0x40,0x7A,0x48,0x76,0x03,0x48,0x01,0x21,0x60,0x38,0x81,0x74,0x70,0x47, + 0x00,0x03,0x00,0x40,0xC4,0x00,0x00,0x20,0x03,0x49,0x02,0x48,0xC8,0x60,0xBF,0xF3, + 0x40,0x8F,0xFE,0xE7,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0,0x03,0xE0,0x0B,0x78, + 0x49,0x1C,0x03,0x70,0x40,0x1C,0x52,0x1E,0xF9,0xD2,0x70,0x47,0x03,0xE0,0x0B,0x88, + 0x89,0x1C,0x03,0x80,0x80,0x1C,0x52,0x1E,0xF9,0xD2,0x70,0x47,0x01,0xE0,0x01,0x70, + 0x40,0x1C,0x52,0x1E,0xFB,0xD2,0x70,0x47,0xF8,0xB5,0x45,0x4C,0xE0,0x79,0xC0,0x07, + 0x1E,0xD0,0x44,0x4D,0x01,0x20,0xA8,0x70,0xE0,0x79,0x00,0x06,0x14,0xD5,0x60,0x88, + 0xD1,0x21,0x09,0x02,0x41,0x1A,0x20,0x29,0x04,0xD8,0xC0,0xB2,0x03,0xF0,0x10,0xFC, + 0x02,0x20,0x06,0xE0,0x3C,0x49,0x88,0x42,0x04,0xD1,0x3C,0x49,0x03,0xF0,0x20,0xF9, + 0x03,0x20,0xA8,0x70,0x10,0x20,0xE0,0x71,0x39,0x49,0xA0,0x20,0x88,0x80,0xF8,0xBD, + 0xA3,0x79,0x34,0x4F,0xCF,0x20,0xE0,0x3F,0x3E,0x46,0x03,0x40,0x39,0x46,0xC0,0x36, + 0x20,0x31,0x34,0x4A,0x35,0x68,0xF8,0x68,0x01,0x2B,0x21,0xD0,0x05,0x2B,0x08,0xD0, + 0x00,0x26,0x09,0x2B,0x01,0xD0,0xA6,0x71,0xF8,0xBD,0xBE,0x72,0x63,0x88,0xDB,0x07, + 0x04,0xD0,0x90,0x42,0x04,0xD1,0xA5,0x20,0x60,0x80,0x0E,0xE0,0x10,0x20,0x0D,0xE0, + 0x4B,0x7D,0x24,0x49,0x28,0x5C,0xE0,0x39,0xC9,0x68,0x49,0x1C,0x00,0x2B,0x60,0x80, + 0xF9,0x60,0x02,0xD1,0x37,0x29,0x00,0xD3,0xFA,0x60,0x14,0x20,0xA0,0x71,0xF8,0xBD, + 0xBB,0x7A,0x02,0x2B,0x29,0xD2,0x00,0x2B,0x0C,0xD0,0x63,0x88,0x00,0x02,0xC0,0x18, + 0x85,0xB2,0xD1,0x20,0x00,0x02,0x28,0x1A,0x20,0x28,0x05,0xD8,0xE8,0xB2,0x03,0xF0, + 0xBF,0xFB,0x21,0xE0,0x60,0x88,0x14,0xE0,0x48,0x7D,0x00,0x28,0x0C,0xD0,0x13,0x49, + 0x28,0x46,0x03,0xF0,0xCD,0xF8,0x41,0x20,0x40,0x02,0x28,0x1A,0xFF,0x28,0x13,0xD8, + 0x71,0x68,0x0A,0x31,0x31,0x60,0x04,0xE0,0x0D,0x20,0x00,0x03,0x28,0x1A,0x50,0x28, + 0x01,0xD8,0xF8,0x60,0x08,0xE0,0xFA,0x60,0x06,0xE0,0x90,0x42,0x04,0xD0,0x61,0x88, + 0x29,0x54,0xF8,0x68,0x40,0x1C,0xF4,0xE7,0xB8,0x7A,0x40,0x1C,0xB8,0x72,0xB5,0xE7, + 0x00,0x20,0x00,0x40,0x24,0x01,0x00,0x20,0xF4,0xD1,0x00,0x00,0xEB,0x08,0x00,0x20, + 0x00,0x02,0x00,0x40,0xFF,0xFF,0x00,0x00,0x30,0xB5,0x0D,0x49,0x0D,0x4A,0x00,0x20, + 0x43,0x00,0x40,0x1C,0x80,0xB2,0xD1,0x52,0x1E,0x28,0xF9,0xD3,0x00,0x23,0x0A,0x4C, + 0x08,0x4D,0x23,0x70,0x18,0x46,0x3C,0x35,0x14,0x21,0x41,0x43,0x49,0x19,0x00,0x22, + 0x40,0x1C,0x8B,0x81,0x80,0xB2,0xCA,0x74,0x0A,0x28,0xF5,0xD3,0x63,0x70,0x30,0xBD, + 0xFF,0x3F,0x00,0x00,0xA4,0x0A,0x00,0x20,0x30,0x00,0x00,0x20,0x00,0x23,0x02,0xE0, + 0xC1,0x54,0x5B,0x1C,0x9B,0xB2,0x93,0x42,0xFA,0xD3,0x70,0x47,0x01,0x20,0x80,0x07, + 0x01,0x89,0x04,0x22,0x11,0x43,0x01,0x81,0x02,0x89,0x08,0x21,0x0A,0x43,0x02,0x81, + 0x42,0x89,0x80,0x23,0x1A,0x43,0x42,0x81,0x42,0x89,0x8A,0x43,0x42,0x81,0x41,0x89, + 0x71,0x22,0x11,0x43,0x41,0x81,0x81,0x89,0x09,0x09,0x09,0x01,0x81,0x81,0x70,0x47, + 0x10,0xB5,0x12,0x4A,0x10,0x48,0x50,0x80,0x11,0x48,0x00,0x78,0x03,0x02,0x11,0x48, + 0xC1,0x6B,0x08,0x46,0x20,0x30,0x84,0x78,0x23,0x43,0x13,0x81,0x40,0x31,0x89,0x8A, + 0xD1,0x80,0xC1,0x78,0xFF,0x31,0xFF,0x31,0x02,0x31,0x51,0x81,0x42,0x79,0x01,0x79, + 0x12,0x01,0x80,0x79,0x11,0x43,0xC0,0x00,0x80,0x22,0x10,0x43,0x01,0x43,0x06,0x48, + 0x81,0x74,0x03,0xF0,0x17,0xF8,0x10,0xBD,0x82,0x10,0x00,0x00,0x00,0x10,0x00,0x40, + 0xDC,0x7B,0x00,0x00,0xC4,0x00,0x00,0x20,0xE0,0x12,0x00,0x40,0x70,0xB5,0x01,0x21, + 0x89,0x07,0x88,0x89,0x00,0x07,0x00,0x0F,0x88,0x81,0x20,0x48,0xC2,0x6B,0x90,0x7F, + 0x00,0x28,0x34,0xD0,0x02,0x28,0x88,0x89,0x34,0xD0,0x30,0x23,0x18,0x43,0x88,0x81, + 0x1B,0x4D,0xC1,0x20,0x68,0x70,0x13,0x46,0x20,0x33,0x1C,0x78,0xD2,0x7F,0x20,0x01, + 0x18,0x4E,0x10,0x43,0x30,0x83,0x01,0x26,0x30,0x46,0xA0,0x40,0x96,0x40,0x16,0x4A, + 0x30,0x43,0x94,0x7C,0x04,0x43,0x94,0x74,0x54,0x7C,0x04,0x43,0x54,0x74,0x5C,0x78, + 0x01,0x2C,0x54,0x7D,0x18,0xD0,0x84,0x43,0x54,0x75,0x14,0x7D,0x04,0x43,0x14,0x75, + 0xD4,0x7C,0x20,0x43,0xD0,0x74,0x48,0x89,0x40,0x22,0x10,0x43,0x48,0x81,0x00,0x20, + 0x68,0x71,0x59,0x7C,0x80,0x22,0x11,0x43,0x29,0x70,0xE8,0x71,0x70,0xBD,0x88,0x89, + 0xE0,0x23,0xCB,0xE7,0x10,0x23,0xC9,0xE7,0x04,0x43,0xE5,0xE7,0xC4,0x00,0x00,0x20, + 0x00,0x20,0x00,0x40,0x20,0x11,0x00,0x40,0x00,0x03,0x00,0x40,0x10,0xB5,0x01,0x21, + 0x03,0x20,0xFC,0xF7,0x83,0xFE,0x02,0x21,0x05,0x20,0xFC,0xF7,0x7F,0xFE,0x03,0x21, + 0x04,0x20,0xFC,0xF7,0x7B,0xFE,0x05,0x20,0xFC,0xF7,0x6C,0xFE,0x03,0x20,0xFC,0xF7, + 0x69,0xFE,0x04,0x20,0xFC,0xF7,0x66,0xFE,0x62,0xB6,0x10,0xBD,0x30,0xB5,0x0E,0x48, + 0x03,0x7C,0x0E,0x49,0x01,0x22,0xC9,0x6B,0x14,0x46,0x4D,0x7C,0xAC,0x40,0x23,0x43, + 0x03,0x74,0x43,0x7D,0x4D,0x7C,0x14,0x46,0xAC,0x40,0xA3,0x43,0x43,0x75,0x03,0x7D, + 0x4D,0x7C,0x14,0x46,0xAC,0x40,0x23,0x43,0x03,0x75,0xC3,0x7C,0x49,0x7C,0x8A,0x40, + 0x13,0x43,0xC3,0x74,0x30,0xBD,0x00,0x00,0x00,0x03,0x00,0x40,0xC4,0x00,0x00,0x20, + 0x10,0xB5,0x0C,0x48,0x04,0x21,0x01,0x74,0x01,0x46,0x08,0x31,0x04,0x20,0x01,0xF0, + 0xA1,0xF9,0x08,0x4A,0x04,0x20,0x0C,0x32,0x51,0x1D,0x01,0xF0,0xB1,0xF9,0x05,0x4C, + 0x10,0x22,0x20,0x3C,0x04,0x48,0xE1,0x6A,0xFF,0xF7,0x40,0xFE,0x02,0x48,0xE0,0x63, + 0x10,0xBD,0x00,0x00,0x64,0x01,0x00,0x20,0x9C,0x09,0x00,0x20,0x10,0xB5,0x16,0x48, + 0xC1,0x7C,0x49,0x08,0x49,0x00,0xC1,0x74,0x01,0x7D,0x49,0x08,0x49,0x00,0x01,0x75, + 0x01,0x7D,0xFD,0x22,0x11,0x40,0x01,0x75,0x01,0x7D,0xFB,0x22,0x11,0x40,0x01,0x75, + 0x02,0x46,0x00,0x21,0x20,0x3A,0x11,0x72,0xD1,0x71,0x51,0x72,0x01,0x71,0xD1,0x84, + 0x81,0x75,0x41,0x71,0x01,0x23,0x83,0x74,0xD1,0x70,0x60,0x30,0xC0,0x6B,0x28,0x24, + 0x24,0x5C,0x94,0x71,0x53,0x70,0x00,0x78,0x10,0x70,0xD0,0x1D,0xF9,0x30,0x81,0x77, + 0xFF,0x21,0xC1,0x77,0x10,0xBD,0x00,0x00,0x64,0x00,0x00,0x20,0xF0,0xB5,0x84,0x4C, + 0x85,0xB0,0x82,0x48,0xE0,0x63,0x25,0x46,0x82,0x48,0x40,0x35,0x00,0x26,0x28,0x60, + 0x20,0x30,0x06,0x70,0x06,0x71,0x80,0x48,0x06,0x80,0x20,0x46,0x7F,0x49,0x80,0x38, + 0x81,0x63,0x0A,0x31,0xC1,0x63,0x0A,0x31,0x8C,0x46,0x01,0x64,0x64,0x31,0x41,0x64, + 0xC8,0x31,0x81,0x64,0xC8,0x31,0xC1,0x64,0xC8,0x31,0x04,0x91,0x01,0x65,0xC8,0x31, + 0x41,0x65,0xC8,0x31,0x81,0x65,0x8C,0x31,0xC1,0x65,0x0E,0x31,0x03,0x91,0x01,0x66, + 0x14,0x31,0x41,0x66,0x14,0x31,0x02,0x91,0x81,0x66,0x14,0x31,0xC1,0x66,0x14,0x31, + 0x01,0x67,0x0A,0x31,0x41,0x67,0x2E,0x77,0x0A,0x31,0x01,0x91,0x81,0x67,0x14,0x31, + 0xC1,0x67,0x08,0x46,0x14,0x30,0x00,0x90,0x20,0x60,0x14,0x30,0x60,0x60,0x14,0x30, + 0xA0,0x60,0x0A,0x30,0xE0,0x60,0x0A,0x30,0x20,0x61,0x40,0x30,0x60,0x61,0x64,0x48, + 0x60,0x62,0x08,0x38,0x20,0x62,0x14,0x30,0xA0,0x62,0x24,0x30,0xE0,0x62,0x5C,0x38, + 0xE0,0x61,0x20,0x38,0xA0,0x61,0x5F,0x48,0xA0,0x63,0x00,0x1F,0x60,0x63,0x00,0x1F, + 0x00,0x21,0x20,0x63,0x11,0xE0,0x38,0x23,0x0A,0x46,0x5A,0x43,0x67,0x69,0x93,0x1C, + 0xFE,0x54,0x00,0x23,0x67,0x69,0xDB,0x43,0xBB,0x54,0x53,0x1C,0x67,0x69,0x52,0x1D, + 0xFE,0x54,0x60,0x69,0x49,0x1C,0x86,0x54,0xC9,0xB2,0xE0,0x6B,0xC0,0x7A,0x88,0x42, + 0xE9,0xD8,0x64,0x22,0x00,0x21,0x60,0x46,0xFF,0xF7,0xA0,0xFD,0xC8,0x22,0x00,0x21, + 0x04,0x98,0xFF,0xF7,0x9B,0xFD,0x14,0x22,0x00,0x21,0x02,0x98,0xFF,0xF7,0x96,0xFD, + 0x14,0x22,0x00,0x21,0x03,0x98,0xFF,0xF7,0x91,0xFD,0x14,0x22,0x00,0x21,0x00,0x98, + 0xFF,0xF7,0x8C,0xFD,0x14,0x22,0x00,0x21,0x01,0x98,0xFF,0xF7,0x87,0xFD,0x3C,0x4F, + 0x08,0x22,0x80,0x3F,0x01,0x21,0xF8,0x6D,0xFF,0xF7,0x80,0xFD,0x48,0x22,0x00,0x21, + 0xB8,0x6D,0xFF,0xF7,0x7B,0xFD,0x09,0x22,0x00,0x21,0xF8,0x6B,0xFF,0xF7,0x76,0xFD, + 0x09,0x22,0x00,0x21,0xB8,0x6B,0xFF,0xF7,0x71,0xFD,0x38,0x46,0x20,0x30,0x46,0x75, + 0x86,0x73,0x06,0x72,0x46,0x74,0x3E,0x74,0x01,0x20,0x78,0x74,0xF8,0x1D,0x32,0x49, + 0xF9,0x30,0xC1,0x60,0x31,0x49,0x01,0x61,0x31,0x49,0x41,0x61,0x31,0x49,0x81,0x61, + 0x01,0x46,0x20,0x31,0x00,0x91,0x8E,0x70,0x46,0x62,0x00,0x99,0x4E,0x70,0x46,0x77, + 0x06,0x77,0x6E,0x77,0xAE,0x77,0xEE,0x77,0xE0,0x37,0x3E,0x70,0x7E,0x70,0xBE,0x70, + 0x20,0x49,0x09,0x39,0xA9,0x60,0x20,0x49,0x89,0x1C,0xE9,0x60,0x26,0x49,0x29,0x61, + 0x1D,0x49,0x0A,0x31,0x69,0x61,0x08,0x31,0x81,0x63,0xE0,0x6B,0x23,0x49,0xC2,0x78, + 0x19,0x48,0x80,0x1C,0xFF,0xF7,0x2A,0xFD,0xE0,0x6B,0x21,0x49,0x02,0x79,0x15,0x48, + 0x09,0x38,0xFF,0xF7,0x23,0xFD,0xFF,0x20,0x3C,0x46,0x60,0x34,0xE0,0x71,0xFE,0x70, + 0x0F,0x20,0xA0,0x71,0x19,0x20,0x20,0x71,0x01,0x20,0x60,0x71,0x0D,0x48,0x18,0x22, + 0x00,0x21,0x51,0x30,0xFF,0xF7,0x22,0xFD,0x01,0xF0,0x94,0xF8,0x09,0x48,0x51,0x30, + 0x20,0x60,0x00,0x99,0x0E,0x74,0xFF,0xF7,0xB3,0xFE,0xFD,0xF7,0xFB,0xF8,0xFD,0xF7, + 0xC1,0xFA,0x02,0xF0,0x23,0xFE,0x05,0xB0,0xF0,0xBD,0x00,0x00,0xB8,0x7A,0x00,0x00, + 0xC4,0x00,0x00,0x20,0xEB,0x08,0x00,0x20,0x02,0x00,0x00,0x20,0x90,0x01,0x00,0x20, + 0x8C,0x7B,0x00,0x00,0x3C,0x7B,0x00,0x00,0x25,0x66,0x00,0x00,0xD5,0x4A,0x00,0x00, + 0x69,0x76,0x00,0x00,0x89,0x56,0x00,0x00,0x00,0x00,0x00,0x20,0x19,0x7B,0x00,0x00, + 0x10,0x7B,0x00,0x00,0xF0,0xB5,0x61,0x49,0x97,0xB0,0x08,0x78,0x00,0x25,0x13,0x90, + 0x40,0x1E,0x15,0x90,0xA5,0xE0,0x00,0x24,0xFF,0x20,0x86,0x46,0x12,0x90,0xA4,0x46, + 0x11,0x94,0x20,0x46,0x23,0x46,0x03,0xE0,0x0E,0xA9,0x0B,0x54,0x40,0x1C,0xC0,0xB2, + 0x13,0x99,0x88,0x42,0xF8,0xD3,0x14,0x21,0x55,0x4B,0x68,0x46,0x69,0x43,0x05,0x70, + 0xC9,0x18,0xC9,0x7C,0x01,0x20,0x09,0x07,0x7E,0xD1,0x50,0x49,0x49,0x78,0x14,0x91, + 0x40,0x1E,0xC0,0xB2,0x69,0x46,0x0B,0x5C,0x14,0x21,0x4D,0x4A,0x59,0x43,0x89,0x18, + 0xCF,0x7C,0x3A,0x07,0x12,0x0F,0x02,0x2A,0x26,0xD0,0xCA,0x89,0x01,0x26,0x12,0x19, + 0x94,0xB2,0x0E,0xAA,0xD6,0x54,0x3A,0x09,0x12,0x01,0x92,0x1C,0xCA,0x74,0x8A,0x7C, + 0x12,0x9E,0x17,0x46,0x12,0x07,0x12,0x0F,0xB2,0x42,0x00,0xD9,0x32,0x46,0x12,0x92, + 0x11,0x9E,0x3A,0x09,0xB2,0x42,0x00,0xD2,0x32,0x46,0x11,0x92,0x4E,0x7C,0x72,0x46, + 0x31,0x07,0x09,0x0F,0x71,0x45,0x00,0xD9,0x11,0x46,0x8E,0x46,0x31,0x09,0x62,0x46, + 0x61,0x45,0x00,0xD2,0x11,0x46,0x8C,0x46,0x00,0x22,0x25,0xE0,0x11,0x46,0x0E,0x26, + 0x71,0x43,0x33,0x4E,0xC8,0x36,0x89,0x19,0x8E,0x7A,0x31,0x07,0x09,0x0F,0x99,0x42, + 0x01,0xD1,0x31,0x09,0x02,0xE0,0x36,0x09,0x9E,0x42,0x13,0xD1,0x00,0x29,0x11,0xDB, + 0x14,0x27,0x0E,0x46,0x7E,0x43,0x2A,0x4F,0xF6,0x19,0x16,0x96,0xF6,0x7C,0x37,0x07, + 0x08,0xD1,0x6F,0x46,0x39,0x54,0x31,0x09,0x40,0x1C,0x09,0x01,0x16,0x9E,0x49,0x1C, + 0xC0,0xB2,0xF1,0x74,0x52,0x1C,0xD2,0xB2,0x14,0x99,0x8A,0x42,0xD6,0xD3,0x37,0x28, + 0x21,0xD2,0x00,0x28,0x9C,0xD1,0x1E,0x4F,0x0E,0xAB,0xC8,0x37,0x11,0xE0,0x0E,0x21, + 0x41,0x43,0xCA,0x19,0x92,0x7A,0x16,0x07,0x36,0x0F,0x9E,0x5D,0x01,0x2E,0x06,0xD1, + 0x12,0x09,0x9A,0x5C,0x01,0x2A,0x02,0xD1,0x79,0x5A,0x09,0x19,0x8C,0xB2,0x40,0x1C, + 0xC0,0xB2,0x14,0x99,0x88,0x42,0x00,0xE0,0x08,0xE0,0xE8,0xD3,0x0F,0x48,0x40,0x68, + 0x00,0x88,0xA0,0x42,0x02,0xD8,0x01,0x20,0x17,0xB0,0xF0,0xBD,0x6D,0x1C,0x15,0x98, + 0xED,0xB2,0x85,0x42,0x00,0xDA,0x56,0xE7,0x00,0x20,0x09,0x4A,0x08,0xE0,0x14,0x21, + 0x41,0x43,0x89,0x18,0xCB,0x7C,0x1B,0x09,0x1B,0x01,0x40,0x1C,0xCB,0x74,0xC0,0xB2, + 0x13,0x99,0x88,0x42,0xF3,0xD3,0x00,0x20,0xE6,0xE7,0x00,0x00,0x30,0x00,0x00,0x20, + 0xE0,0x0A,0x00,0x20,0x17,0xB5,0x6C,0x46,0xA1,0x88,0x20,0x88,0x63,0x89,0x0A,0x1A, + 0x61,0x88,0x5B,0x1A,0x5A,0x43,0xE3,0x88,0x59,0x1A,0x23,0x89,0x18,0x1A,0x41,0x43, + 0x50,0x1A,0x00,0x28,0x01,0xDD,0x01,0x20,0x1E,0xBD,0x00,0x20,0x1E,0xBD,0x00,0x00, + 0xF3,0xB5,0x1D,0x4D,0x85,0xB0,0x68,0x68,0x0E,0x46,0xC4,0x6A,0x00,0x2C,0x27,0xD0, + 0x03,0xAB,0x02,0xAA,0x01,0xA9,0x68,0x46,0xA0,0x47,0x00,0x28,0x21,0xD0,0x17,0x49, + 0x70,0x00,0x08,0x5A,0x69,0x46,0x0D,0x7B,0x0C,0x78,0x0B,0x79,0x0E,0x7A,0x5B,0x1C, + 0x64,0x1E,0x6D,0x1C,0x76,0x1E,0x19,0xE0,0x0F,0x4A,0x81,0x04,0x52,0x68,0x49,0x0E, + 0xD2,0x7F,0x40,0x06,0x40,0x0E,0x4A,0x43,0x12,0x18,0x57,0x00,0x05,0x9A,0xBA,0x18, + 0xB1,0x42,0x05,0xDB,0xA9,0x42,0x03,0xDC,0xA0,0x42,0x01,0xDB,0x98,0x42,0x02,0xDD, + 0x00,0x20,0x07,0xB0,0xF0,0xBD,0x10,0x88,0x80,0x04,0x80,0x0C,0x04,0x49,0x88,0x42, + 0xE2,0xD1,0x01,0x20,0xF5,0xE7,0x00,0x00,0x30,0x00,0x00,0x20,0xA4,0x0A,0x00,0x20, + 0xFF,0x3F,0x00,0x00,0xFF,0xB5,0x91,0xB0,0x00,0x20,0xBF,0x4B,0x05,0x90,0x5C,0x78, + 0xA0,0x42,0x7D,0xD2,0x0E,0x21,0x48,0x43,0xBC,0x4A,0x0D,0x90,0x80,0x18,0x03,0x90, + 0x80,0x7A,0x14,0x24,0x01,0x07,0x09,0x0F,0x0C,0x91,0x61,0x43,0x14,0x46,0xC8,0x3C, + 0x09,0x19,0x04,0x91,0x89,0x89,0x00,0x09,0x07,0x91,0x0B,0x90,0x14,0x21,0x48,0x43, + 0x05,0x19,0x0C,0x20,0x28,0x5E,0x07,0x99,0x88,0x42,0x01,0xDA,0xA8,0x89,0x07,0x90, + 0x5C,0x68,0xE0,0x7A,0x40,0x09,0x7D,0xD1,0x03,0x99,0x08,0x73,0x0A,0x90,0xE0,0x7A, + 0x06,0x90,0x00,0x07,0x52,0xD5,0x13,0x98,0x00,0x28,0x4F,0xD0,0x00,0x20,0x07,0x46, + 0x00,0x90,0x06,0x46,0x08,0x90,0x43,0xE0,0x38,0x20,0x13,0x99,0x70,0x43,0x40,0x18, + 0x01,0x90,0x40,0x78,0x00,0x28,0x39,0xD0,0x01,0x98,0xE1,0x7F,0x80,0x8C,0x48,0x43, + 0x21,0x8C,0xFC,0xF7,0x53,0xFA,0xC0,0xB2,0x02,0x90,0x01,0x98,0xA1,0x7F,0xC0,0x8C, + 0x48,0x43,0x61,0x8C,0xFC,0xF7,0x4A,0xFA,0x00,0x99,0xC0,0xB2,0x00,0x29,0x10,0xD1, + 0x04,0x99,0x02,0x9A,0x09,0x7C,0x0B,0x09,0xD2,0x1A,0x52,0x1C,0x02,0x2A,0x08,0xD8, + 0x09,0x07,0x09,0x0F,0x41,0x1A,0x49,0x1C,0x02,0x29,0x02,0xD8,0x01,0x20,0x00,0x90, + 0x12,0xE0,0x00,0x2F,0x0D,0xD1,0x29,0x7C,0x02,0x9A,0x0B,0x09,0xD2,0x1A,0x52,0x1C, + 0x02,0x2A,0x06,0xD8,0x09,0x07,0x09,0x0F,0x40,0x1A,0x40,0x1C,0x02,0x28,0x00,0xD8, + 0x01,0x27,0x00,0x98,0x00,0x28,0x01,0xD0,0x00,0x2F,0x7D,0xD1,0x76,0x1C,0xF6,0xB2, + 0x14,0x98,0x86,0x42,0xB8,0xD3,0x08,0x98,0x00,0x28,0xF6,0xD1,0x06,0x98,0x00,0xE0, + 0xC9,0xE0,0xC0,0x06,0x71,0xD5,0x13,0x98,0x00,0x28,0x6E,0xD0,0x04,0x98,0x6B,0x7C, + 0x46,0x7C,0x19,0x07,0x30,0x07,0x00,0x0F,0x09,0x0F,0x88,0x42,0x00,0xD3,0x08,0x46, + 0x09,0x90,0x30,0x09,0x19,0x09,0x88,0x42,0x00,0xD8,0x08,0x46,0x08,0x90,0x04,0x98, + 0xAB,0x7C,0x86,0x7C,0x19,0x07,0x30,0x07,0x00,0x0F,0x09,0x0F,0x88,0x42,0x00,0xD3, + 0x08,0x46,0x00,0xE0,0x86,0xE0,0x02,0x90,0x30,0x09,0x19,0x09,0x88,0x42,0x00,0xD8, + 0x08,0x46,0x00,0x90,0x00,0x20,0x67,0xE0,0x60,0x46,0x38,0x21,0x48,0x43,0x13,0x99, + 0x00,0x22,0x40,0x18,0x41,0x78,0x00,0x29,0x5B,0xD0,0x20,0x30,0x41,0x7A,0x80,0x7A, + 0x0F,0x09,0x06,0x09,0x09,0x07,0x00,0x07,0x09,0x0F,0x00,0x0F,0x01,0x96,0x7B,0x1A, + 0x36,0x1A,0x5B,0x1C,0x76,0x1C,0x73,0x43,0xE6,0x79,0x9B,0xB2,0x9E,0x42,0x48,0xD8, + 0x09,0x9B,0x99,0x42,0x00,0xD2,0x19,0x46,0x08,0x9E,0x3B,0x46,0xB7,0x42,0x00,0xD9, + 0x33,0x46,0x0E,0x93,0x02,0x9B,0x98,0x42,0x00,0xD2,0x18,0x46,0x0F,0x90,0x01,0x9B, + 0x00,0x98,0x83,0x42,0x00,0xD8,0x18,0x46,0x01,0x90,0x1F,0xE0,0x0F,0x98,0x18,0xE0, + 0xE3,0x7F,0x4B,0x43,0x1B,0x18,0x5E,0x00,0x11,0x9B,0x9B,0x5B,0x9E,0x0B,0x0E,0xD0, + 0x9E,0x04,0x77,0x0E,0x0C,0x9E,0xB7,0x42,0x04,0xD0,0x5E,0x06,0x0B,0x9B,0x76,0x0E, + 0x9E,0x42,0x04,0xD1,0x52,0x1C,0x01,0xE0,0x37,0xE0,0x24,0xE0,0x92,0xB2,0x40,0x1C, + 0xC0,0xB2,0x01,0x9B,0x98,0x42,0xE3,0xD9,0x49,0x1C,0xC9,0xB2,0x0E,0x98,0x81,0x42, + 0xDC,0xD9,0x00,0x2A,0x0D,0xD0,0x04,0x99,0xEB,0x89,0xC9,0x89,0x3B,0x48,0xCB,0x18, + 0x0D,0x99,0x40,0x5A,0x18,0x18,0x80,0xB2,0x41,0x00,0x40,0x18,0x80,0x08,0x90,0x42, + 0x32,0xD3,0x60,0x46,0x40,0x1C,0xC0,0xB2,0x84,0x46,0x14,0x98,0x84,0x45,0x93,0xD3, + 0x0A,0x98,0x00,0x28,0x2B,0xD1,0x06,0x98,0x40,0x07,0x0F,0xD5,0xA0,0x7A,0x21,0x79, + 0x88,0x40,0x03,0x99,0x49,0x88,0x4A,0x00,0x12,0x99,0x8A,0x5E,0x07,0x99,0x89,0x1A, + 0x88,0x42,0x03,0xDD,0x03,0x99,0x01,0x20,0x08,0x73,0x18,0xE0,0x06,0x98,0x80,0x07, + 0x15,0xD5,0x28,0x7C,0x21,0x7C,0x02,0x09,0x00,0x07,0x00,0x0F,0x00,0x90,0x04,0x98, + 0x01,0x92,0x02,0x91,0x00,0x7C,0x12,0x99,0x02,0x07,0x03,0x09,0x12,0x0F,0x11,0x98, + 0xFE,0xF7,0x7E,0xFE,0x00,0x28,0x02,0xD0,0x03,0x98,0x01,0x21,0x01,0x73,0x05,0x98, + 0x40,0x1C,0xC0,0xB2,0xB1,0xE6,0x00,0x20,0x29,0xE0,0x0E,0x21,0x02,0x46,0x4A,0x43, + 0x16,0x49,0x51,0x18,0x0A,0x7B,0x00,0x2A,0x1F,0xD0,0x8D,0x7A,0x13,0x4F,0x2A,0x07, + 0xC8,0x3F,0x12,0x0F,0x14,0x23,0x2D,0x09,0x14,0x26,0x5A,0x43,0x75,0x43,0xD3,0x19, + 0xEE,0x19,0x0C,0x22,0x0C,0x25,0x9A,0x5E,0x75,0x5F,0x49,0x88,0xAA,0x42,0x06,0xDD, + 0x4A,0x00,0x12,0x99,0x89,0x5E,0xA9,0x42,0x07,0xDD,0xB1,0x81,0x05,0xE0,0x4D,0x00, + 0x12,0x99,0x49,0x5F,0x91,0x42,0x00,0xDD,0x99,0x81,0x40,0x1C,0xC0,0xB2,0xA0,0x42, + 0xD3,0xD3,0x15,0xB0,0xF0,0xBD,0x00,0x00,0x30,0x00,0x00,0x20,0xA8,0x0B,0x00,0x20, + 0xF0,0xB5,0x1E,0x4E,0x34,0x46,0x80,0x34,0xE3,0x6B,0x70,0x6C,0x1A,0x79,0x99,0x79, + 0x40,0x33,0x51,0x43,0x9A,0x8A,0x9B,0x89,0xDB,0x08,0x5A,0x43,0x23,0x46,0xA0,0x33, + 0x1B,0x7C,0x00,0x2B,0x04,0xD0,0xDB,0x07,0x00,0xD1,0x52,0x08,0x55,0x08,0x00,0xE0, + 0x00,0x25,0x53,0x08,0x9A,0x18,0x93,0xB2,0xAA,0xB2,0xFD,0xF7,0xDF,0xFD,0xE1,0x6B, + 0x88,0x7B,0x00,0x28,0x19,0xD0,0x0A,0x46,0x40,0x32,0x10,0x8A,0xD2,0x89,0x09,0x79, + 0x12,0x09,0x50,0x43,0x42,0x08,0x15,0x18,0x87,0x08,0xAB,0xB2,0xBA,0xB2,0xF0,0x6E, + 0xFD,0xF7,0xCC,0xFD,0xE1,0x6B,0x39,0x20,0x40,0x5C,0x00,0x28,0x05,0xD0,0xAB,0xB2, + 0xBA,0xB2,0xC9,0x78,0x60,0x68,0xFD,0xF7,0xC1,0xFD,0xF0,0xBD,0x44,0x00,0x00,0x20, + 0xFF,0xB5,0x83,0xB0,0x68,0x46,0x81,0x89,0x00,0x8A,0x86,0x46,0x71,0x45,0x01,0xD9, + 0x0A,0x46,0x00,0xE0,0x02,0x46,0x6B,0x46,0x98,0x8A,0x1B,0x8B,0x9C,0x46,0x60,0x45, + 0x00,0xD2,0x03,0x46,0x9A,0x42,0x4D,0xD3,0x6A,0x46,0xD3,0x89,0x52,0x8A,0x00,0x92, + 0x93,0x42,0x01,0xD9,0x1C,0x46,0x00,0xE0,0x14,0x46,0x6D,0x46,0xEA,0x8A,0x6D,0x8B, + 0x01,0x95,0xAA,0x42,0x00,0xD2,0x15,0x46,0xAC,0x42,0x3B,0xD3,0x74,0x46,0x71,0x45, + 0x00,0xD2,0x0C,0x46,0x65,0x46,0x60,0x45,0x00,0xD9,0x05,0x46,0xAC,0x42,0x31,0xD8, + 0x00,0x9C,0xA3,0x42,0x00,0xD2,0x1C,0x46,0x01,0x9D,0xAA,0x42,0x00,0xD9,0x15,0x46, + 0xAC,0x42,0x27,0xD8,0x01,0x9C,0x9E,0x1A,0xA7,0x1A,0x64,0x46,0x24,0x1A,0x0D,0x1A, + 0x66,0x43,0x7D,0x43,0x02,0x94,0xAD,0x1B,0x74,0x46,0x26,0x1A,0x00,0x9C,0x7E,0x43, + 0xA7,0x1A,0x02,0x9C,0x67,0x43,0xF4,0x1B,0x65,0x43,0x00,0x2D,0x12,0xDC,0x44,0x1A, + 0x00,0x98,0xD5,0x1A,0x72,0x46,0xC0,0x1A,0x52,0x1A,0x44,0x43,0x55,0x43,0x64,0x1B, + 0x65,0x46,0x69,0x1A,0x41,0x43,0x01,0x98,0xC0,0x1A,0x50,0x43,0x08,0x1A,0x44,0x43, + 0x00,0x2C,0x02,0xDD,0x00,0x20,0x07,0xB0,0xF0,0xBD,0x01,0x20,0xFB,0xE7,0x70,0xB5, + 0x1E,0x46,0x14,0x46,0x05,0x00,0x04,0xD0,0x00,0x2C,0x02,0xD0,0xE8,0x00,0xA0,0x42, + 0x05,0xDA,0x9A,0x42,0x01,0xDA,0x01,0x20,0x70,0xBD,0x00,0x20,0x70,0xBD,0x28,0x46, + 0x49,0x43,0x68,0x43,0x09,0x1A,0x10,0x46,0x60,0x43,0x08,0x1A,0x29,0x46,0xC0,0x01, + 0x61,0x43,0xFC,0xF7,0x5D,0xF8,0x80,0x38,0x42,0x00,0x01,0xD5,0x00,0x22,0x04,0xE0, + 0xFF,0x20,0x01,0x30,0x82,0x42,0x00,0xDD,0x02,0x46,0x70,0x19,0x50,0x43,0x00,0x12, + 0x80,0x19,0x84,0x42,0xE1,0xDC,0xDE,0xE7,0xF0,0xB5,0x18,0x4A,0xBC,0x23,0x9D,0x58, + 0x20,0x32,0x94,0x7B,0x00,0x29,0x12,0xD0,0x14,0x4E,0x00,0x23,0xB6,0x8D,0x0B,0xE0, + 0xC7,0x5C,0xB7,0x42,0x06,0xD1,0x28,0x7D,0x50,0x72,0x7F,0x2C,0x01,0xD2,0x64,0x1C, + 0x94,0x73,0xF0,0xBD,0x5B,0x1C,0xDB,0xB2,0x8B,0x42,0xF1,0xD3,0xF0,0xBD,0xE8,0x7C, + 0x00,0x21,0x84,0x42,0x01,0xD2,0x11,0x72,0xF0,0xBD,0x50,0x7A,0x01,0x28,0xFA,0xD9, + 0x80,0x21,0x0C,0x43,0x40,0x1E,0xC0,0xB2,0x94,0x73,0x50,0x72,0x01,0x28,0xF3,0xD1, + 0x10,0x7A,0x80,0x08,0x80,0x00,0x10,0x72,0xF0,0xBD,0x00,0x00,0x44,0x00,0x00,0x20, + 0xF1,0xB5,0x84,0xB0,0x00,0x25,0x92,0xE0,0x00,0x20,0x69,0x46,0x08,0x73,0x14,0x20, + 0x2E,0x46,0x4A,0x4F,0x46,0x43,0xF4,0x19,0xE0,0x7C,0x01,0x07,0x7E,0xD1,0x00,0x07, + 0x00,0x0F,0x10,0x30,0xE0,0x74,0x03,0xAB,0x6A,0x46,0x29,0x46,0x04,0x98,0xFE,0xF7, + 0x61,0xFC,0x01,0x21,0x63,0xE0,0x68,0x46,0x43,0x5C,0x14,0x20,0x3F,0x4A,0x43,0x43, + 0x9C,0x46,0x98,0x18,0xE7,0x89,0xC3,0x89,0xFF,0x18,0xE7,0x81,0x67,0x68,0x43,0x68, + 0xFF,0x18,0x67,0x60,0xA7,0x68,0x83,0x68,0xFF,0x18,0xA7,0x60,0x63,0x46,0x97,0x59, + 0xD3,0x58,0xFB,0x18,0x93,0x51,0x67,0x7C,0x43,0x7C,0x3A,0x07,0x1B,0x07,0x12,0x0F, + 0x1B,0x0F,0x9A,0x42,0x00,0xD2,0x13,0x46,0x3A,0x09,0x12,0x01,0x13,0x43,0x63,0x74, + 0x47,0x7C,0x1A,0x09,0x3F,0x09,0xBA,0x42,0x00,0xD8,0x3A,0x46,0x1B,0x07,0x12,0x01, + 0x1B,0x0F,0x1A,0x43,0x62,0x74,0xA3,0x7C,0x82,0x7C,0x1F,0x07,0x12,0x07,0x3F,0x0F, + 0x12,0x0F,0x97,0x42,0x00,0xD3,0x17,0x46,0x1A,0x09,0x12,0x01,0x17,0x43,0xA7,0x74, + 0x83,0x7C,0x3A,0x09,0x1B,0x09,0x9A,0x42,0x00,0xD8,0x1A,0x46,0x3B,0x07,0x12,0x01, + 0x1B,0x0F,0x1A,0x43,0xA2,0x74,0x0C,0x23,0x0C,0x22,0xE3,0x5E,0x82,0x5E,0x93,0x42, + 0x0F,0xDA,0xA2,0x81,0x22,0x7C,0x03,0x7C,0x12,0x07,0x1B,0x09,0x12,0x0F,0x1B,0x01, + 0x1A,0x43,0x22,0x74,0x03,0x7C,0x12,0x09,0x12,0x01,0x1B,0x07,0x1B,0x0F,0x1A,0x43, + 0x22,0x74,0xC2,0x7C,0x12,0x07,0x12,0x0F,0x49,0x1C,0xC2,0x74,0xC9,0xB2,0x68,0x46, + 0x00,0x7B,0x81,0x42,0x97,0xD3,0x0E,0x48,0x0C,0x21,0x40,0x68,0x61,0x5E,0x82,0x8B, + 0x91,0x42,0x06,0xDB,0x0E,0x21,0x61,0x5E,0x40,0x79,0x00,0xE0,0x05,0xE0,0x81,0x42, + 0x03,0xDA,0xE0,0x7C,0x00,0x07,0x00,0x0F,0xE0,0x74,0x6D,0x1C,0xED,0xB2,0x04,0x48, + 0x00,0x78,0x85,0x42,0x00,0xD2,0x67,0xE7,0x05,0xB0,0xF0,0xBD,0xE0,0x0A,0x00,0x20, + 0x30,0x00,0x00,0x20,0xF0,0xB5,0x99,0xB0,0xFC,0x48,0x16,0x90,0xC0,0x6B,0xFB,0x4C, + 0x05,0x79,0xC1,0x78,0x80,0x3C,0x0B,0x94,0x14,0x91,0xE0,0x34,0xE1,0x79,0x04,0x91, + 0x40,0x7B,0x00,0x26,0x00,0x28,0x34,0xD0,0x20,0x46,0x40,0x30,0x13,0x90,0x00,0x7C, + 0x00,0x28,0x3C,0xD0,0x13,0x98,0x00,0x7D,0x80,0x1C,0xC0,0xB2,0x02,0xF0,0x7E,0xF9, + 0x01,0x21,0x00,0x20,0x02,0xF0,0x98,0xFB,0xED,0x48,0x81,0x8A,0x6B,0x46,0x99,0x82, + 0xEC,0x49,0x8A,0x7C,0xDA,0x82,0xC2,0x88,0x1A,0x83,0xC2,0x89,0x5A,0x83,0x4A,0x7C, + 0xDA,0x83,0x0A,0x7C,0x1A,0x84,0x11,0x22,0x4A,0x74,0x13,0x22,0x0A,0x74,0xE6,0x4A, + 0x42,0x80,0x08,0x22,0xC2,0x80,0x00,0x22,0xC2,0x81,0xA3,0x20,0x88,0x74,0xDF,0x48, + 0x22,0x79,0x80,0x38,0xC6,0x1D,0xC0,0x30,0xF9,0x36,0x15,0x90,0x00,0x2A,0x11,0xD0, + 0x2A,0xE0,0x14,0x98,0x00,0x21,0x45,0x43,0xD8,0x48,0x6A,0x00,0x80,0x38,0x40,0x6D, + 0xFF,0xF7,0x54,0xF8,0x26,0x71,0x26,0x72,0x66,0x72,0x19,0xB0,0xF0,0xBD,0x14,0x98, + 0x40,0x1C,0xC2,0xE7,0x07,0x46,0x00,0x6B,0x00,0x78,0x01,0x90,0xCF,0x48,0x80,0x38, + 0x41,0x6D,0xA8,0x00,0x0B,0x18,0x68,0x00,0x0A,0x18,0xF0,0x68,0x00,0x90,0x01,0x98, + 0x01,0xF0,0x14,0xF9,0xB9,0x6B,0x1E,0x28,0x08,0x80,0x05,0xD2,0x00,0x20,0x20,0x72, + 0x60,0x72,0x70,0x60,0x01,0x98,0x55,0xE1,0x00,0x20,0x0D,0x90,0x0A,0x90,0x09,0x90, + 0xC2,0x48,0xA9,0x00,0x80,0x38,0x40,0x6D,0x10,0x90,0x41,0x18,0x0E,0x91,0x69,0x00, + 0x41,0x18,0x00,0x20,0x0F,0x91,0x0C,0x90,0x60,0x79,0xC0,0x4F,0x00,0x28,0x07,0xD0, + 0xA1,0x79,0x00,0x29,0x04,0xD0,0x70,0x68,0xFB,0xF7,0xE0,0xFE,0xC8,0xB2,0x0C,0x90, + 0x04,0x99,0x0C,0x98,0x15,0x9E,0x48,0x43,0x17,0x90,0x31,0x6B,0x08,0x18,0x00,0x25, + 0x11,0x90,0x6E,0xE0,0x0B,0x99,0x11,0x98,0xFF,0x31,0x01,0x31,0x40,0x5D,0xC9,0x68, + 0x00,0x91,0x0E,0x9B,0x0F,0x9A,0x10,0x99,0x01,0xF0,0xD8,0xF8,0x6B,0x00,0x01,0xA9, + 0xC8,0x52,0x17,0x98,0xF1,0x6B,0x40,0x00,0xC0,0x18,0x8E,0x46,0x09,0x5E,0x00,0x91, + 0x01,0xA9,0xCA,0x5A,0x71,0x46,0x0A,0x52,0x84,0x46,0x01,0xA8,0xC0,0x5E,0x00,0x99, + 0x41,0x1A,0x00,0xD5,0x49,0x42,0x40,0x18,0x00,0xB2,0x01,0xA9,0xC8,0x52,0xB2,0x6B, + 0x61,0x46,0x51,0x5A,0x42,0x1A,0x19,0x2A,0x05,0xDD,0x42,0x00,0x80,0x18,0x08,0x18, + 0x80,0x10,0x01,0xA9,0x04,0xE0,0x4A,0x00,0x8A,0x18,0x10,0x18,0x01,0xA9,0x80,0x10, + 0xC8,0x52,0xB2,0x6B,0xC9,0x5A,0x60,0x46,0x11,0x52,0x01,0xA8,0xC0,0x5E,0xB8,0x42, + 0x01,0xDA,0x07,0x46,0x0D,0x95,0x09,0x99,0x88,0x42,0x01,0xDD,0x0A,0x95,0x09,0x90, + 0x28,0x2F,0x1C,0xDA,0x20,0x79,0x00,0x28,0x19,0xD1,0x20,0x7A,0xA8,0x42,0x16,0xD1, + 0x61,0x7A,0x0C,0x98,0x81,0x42,0x12,0xD1,0x0B,0x98,0xFF,0x30,0x01,0x30,0x41,0x68, + 0x49,0x1E,0x41,0x60,0x25,0x72,0x0C,0x98,0x60,0x72,0x69,0x46,0x04,0x20,0x08,0x5E, + 0x1E,0x28,0x03,0xDA,0x20,0x79,0x00,0x28,0x00,0xD1,0x20,0x72,0x9B,0xE0,0x15,0x98, + 0x40,0x68,0x80,0x7A,0xCA,0x28,0x0D,0xD0,0x60,0x79,0x00,0x28,0x07,0xD0,0x6D,0x1C, + 0xED,0xB2,0x04,0x98,0x85,0x42,0x8D,0xD3,0x04,0x28,0x04,0xD0,0x1F,0xE0,0x25,0x72, + 0x00,0x20,0x60,0x72,0x87,0xE0,0x0A,0x98,0x03,0x28,0x02,0xD0,0x00,0x28,0x0B,0xD0, + 0x15,0xE0,0x6A,0x46,0x06,0x20,0x04,0x21,0x10,0x5E,0x51,0x5E,0x88,0x42,0x01,0xDA, + 0x01,0x20,0x0B,0xE0,0x00,0x20,0x09,0xE0,0x6A,0x46,0x08,0x20,0x0A,0x21,0x10,0x5E, + 0x51,0x5E,0x88,0x42,0x01,0xDA,0x02,0x20,0x00,0xE0,0x03,0x20,0x0D,0x90,0xF2,0x6A, + 0x0C,0x99,0x0D,0x98,0x50,0x54,0x65,0x7A,0x0A,0x95,0x20,0x7A,0x00,0x90,0x0D,0x90, + 0xA2,0x79,0x0C,0x99,0x65,0x4F,0x00,0x20,0x0C,0x92,0x13,0xE0,0xF2,0x6A,0x12,0x5C, + 0xFF,0x2A,0x0C,0xD0,0x04,0x9B,0x52,0x00,0x43,0x43,0x5B,0x00,0x9A,0x18,0xB3,0x6B, + 0x94,0x46,0x9A,0x5A,0xBA,0x42,0x02,0xDA,0x61,0x46,0x5F,0x5E,0x01,0x46,0x40,0x1C, + 0x0C,0x9A,0xC0,0xB2,0x82,0x42,0xE9,0xD8,0x58,0x48,0x87,0x42,0x03,0xD0,0xF0,0x6A, + 0x0D,0x46,0x40,0x5C,0x0D,0x90,0x0B,0x98,0xFF,0x30,0x01,0x30,0x84,0x46,0x80,0x68, + 0x0C,0x90,0x00,0x28,0x24,0xD0,0x0D,0x99,0x00,0x98,0x88,0x42,0x02,0xD1,0x0A,0x98, + 0xA8,0x42,0x1B,0xD0,0x04,0x99,0x0A,0x98,0xB3,0x6B,0x48,0x43,0x41,0x00,0x00,0x98, + 0x40,0x00,0x08,0x18,0x19,0x5A,0x04,0x98,0x68,0x43,0x42,0x00,0x0D,0x98,0x40,0x00, + 0x10,0x18,0x18,0x5A,0x1E,0x30,0x81,0x42,0x0C,0x98,0x14,0xD9,0x40,0x1C,0x61,0x46, + 0x88,0x60,0x06,0x28,0x14,0xD3,0x0D,0x98,0x20,0x72,0x65,0x72,0x01,0x20,0x0D,0xE0, + 0xA1,0x72,0xF0,0x6A,0x43,0x5C,0xE3,0x72,0x61,0x72,0x41,0x5C,0x21,0x72,0x01,0x20, + 0x61,0x46,0x88,0x60,0x07,0xE0,0x01,0x28,0x02,0xD9,0x40,0x1E,0x61,0x46,0x88,0x60, + 0x0D,0x98,0xE0,0x72,0xA5,0x72,0x09,0x98,0x50,0x28,0x0C,0xDD,0x1E,0x20,0x20,0x71, + 0x09,0x99,0xFF,0x22,0xC9,0x19,0x5F,0x32,0x91,0x42,0x19,0xDD,0x0B,0x99,0xFF,0x31, + 0x01,0x31,0x48,0x80,0x14,0xE0,0x0B,0x98,0xFF,0x30,0x01,0x30,0x41,0x88,0x00,0x29, + 0x01,0xD0,0x49,0x1E,0x41,0x80,0x09,0x99,0x1E,0x29,0x09,0xDA,0x21,0x79,0x00,0x29, + 0x06,0xD0,0x49,0x1E,0x09,0x06,0x09,0x0E,0x21,0x71,0x01,0xD1,0x00,0x69,0x80,0x47, + 0xA7,0x82,0x09,0x98,0xE0,0x82,0x60,0x7A,0x04,0x99,0x32,0x6B,0x48,0x43,0x21,0x7A, + 0x10,0x18,0x40,0x5C,0x16,0x99,0x00,0x02,0xC9,0x6B,0x20,0x31,0x89,0x78,0x08,0x43, + 0x17,0x49,0x08,0x81,0x6A,0x46,0x90,0x8A,0x88,0x82,0x16,0x48,0xD2,0x8A,0x82,0x74, + 0x6A,0x46,0x12,0x8B,0xCA,0x80,0x6A,0x46,0x52,0x8B,0xCA,0x81,0x6A,0x46,0xD2,0x8B, + 0x42,0x74,0x6A,0x46,0x12,0x8C,0x02,0x74,0x11,0x4A,0x4A,0x80,0x81,0x7C,0x49,0x06, + 0x49,0x0E,0x81,0x74,0x0B,0x9C,0xFF,0x34,0x01,0x34,0xE0,0x68,0x80,0x47,0x13,0x98, + 0x00,0x7C,0x00,0x28,0x16,0xD0,0x13,0x98,0x00,0x7D,0x40,0x1C,0xC0,0xB2,0x01,0xF0, + 0xA5,0xFF,0x60,0x68,0x40,0x1C,0x60,0x60,0x57,0xE6,0x00,0x00,0xC4,0x00,0x00,0x20, + 0x00,0x10,0x00,0x40,0xE0,0x12,0x00,0x40,0x82,0x11,0x00,0x00,0xFF,0x7F,0x00,0x00, + 0x82,0x10,0x00,0x00,0x14,0x98,0xEA,0xE7,0xFE,0xB5,0x07,0x46,0x01,0xF0,0xA6,0xFF, + 0x00,0x20,0x02,0xF0,0x57,0xF9,0x02,0xF0,0xC1,0xFB,0x44,0x49,0x38,0x46,0xFC,0xF7, + 0x25,0xFE,0x0A,0x20,0x02,0xF0,0x1A,0xFA,0x00,0x25,0x2C,0x46,0x00,0xF0,0x8C,0xF8, + 0x40,0x19,0x64,0x1C,0xA4,0xB2,0x85,0xB2,0x08,0x2C,0xF7,0xD3,0xED,0x08,0xBD,0x71, + 0x28,0x0A,0xF8,0x71,0x28,0x46,0x23,0x30,0xC0,0x08,0x38,0x72,0x28,0x46,0x23,0x38, + 0xC0,0x10,0x78,0x72,0x7D,0x21,0x35,0x4A,0xC9,0x00,0x38,0x1D,0xFD,0xF7,0xB6,0xFE, + 0x14,0x20,0x02,0xF0,0xFB,0xF9,0x32,0x48,0x00,0x24,0x01,0x46,0xE0,0x31,0xFF,0x30, + 0x21,0x30,0x26,0x46,0x01,0x91,0x00,0x90,0x01,0x99,0x00,0x20,0x88,0x70,0x2D,0x49, + 0x01,0x20,0xC8,0x71,0xFD,0xF7,0xE2,0xFE,0x2B,0x49,0x45,0x20,0x08,0x80,0x29,0x49, + 0x10,0x20,0xC8,0x71,0x00,0xF0,0x58,0xF8,0x01,0x46,0x40,0x1B,0x00,0xB2,0x76,0x1C, + 0x02,0x46,0x18,0x32,0xB6,0xB2,0x30,0x2A,0x11,0xD8,0x22,0x18,0x14,0xB2,0xB2,0x07, + 0x0D,0xD1,0x78,0x2C,0x03,0xDD,0x6D,0x1C,0xAD,0xB2,0x78,0x3C,0x06,0xE0,0x95,0x22, + 0xD2,0x43,0x94,0x42,0x03,0xDA,0x6D,0x1E,0xAD,0xB2,0x96,0x34,0x24,0xB2,0x23,0x30, + 0x46,0x28,0x09,0xD8,0x19,0x48,0x86,0x42,0x0A,0xD3,0x00,0x98,0x02,0x22,0x42,0x70, + 0x17,0x4A,0x01,0x20,0x50,0x77,0x0D,0xE0,0x00,0x9A,0x01,0x20,0x50,0x70,0x09,0xE0, + 0x01,0x98,0x80,0x78,0x00,0x28,0xBF,0xD0,0x00,0x98,0x03,0x22,0x42,0x70,0x01,0x9A, + 0x00,0x20,0x90,0x70,0xB9,0x72,0x08,0x0A,0xF8,0x72,0x00,0x98,0x0D,0x49,0x40,0x78, + 0x38,0x73,0x00,0x20,0x88,0x72,0x00,0x99,0x88,0x70,0x0A,0x20,0x02,0xF0,0x9E,0xF9, + 0xFE,0xF7,0xEE,0xFE,0x01,0x20,0x01,0xF0,0xED,0xFE,0xFE,0xBD,0xF9,0x47,0x00,0x00, + 0x44,0x00,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x10,0x00,0x40,0xC4,0x09,0x00,0x00, + 0x44,0x01,0x00,0x20,0x00,0x03,0x00,0x40,0x0B,0x48,0x0C,0x49,0x82,0x6A,0x01,0x20, + 0x88,0x72,0x09,0x48,0x00,0x21,0x60,0x30,0x01,0x70,0x09,0x49,0x11,0x23,0x8B,0x80, + 0x43,0x23,0x0B,0x80,0x00,0xE0,0x30,0xBF,0x01,0x78,0x00,0x29,0xFB,0xD0,0x10,0x68, + 0x40,0x1C,0x00,0x88,0x70,0x47,0x00,0x00,0xC4,0x00,0x00,0x20,0x00,0x03,0x00,0x40, + 0x00,0x10,0x00,0x40,0x70,0xB5,0x28,0x48,0x80,0x23,0x03,0x72,0xD8,0x05,0x41,0x88, + 0x04,0x22,0x91,0x43,0x41,0x80,0x26,0x49,0x24,0x48,0x48,0x80,0x25,0x4A,0xD0,0x6B, + 0x04,0x46,0x41,0x30,0x45,0x78,0x06,0x78,0x28,0x02,0x30,0x43,0x40,0xBA,0x08,0x81, + 0x20,0x46,0x40,0x30,0x04,0x78,0xFF,0x34,0xFF,0x34,0x02,0x34,0x4C,0x81,0xC5,0x78, + 0x04,0x79,0x2D,0x01,0x1D,0x43,0x1C,0x4B,0x2C,0x43,0x9C,0x74,0x23,0x24,0x1C,0x74, + 0x18,0x24,0x5C,0x74,0xFF,0x23,0x02,0x33,0xCB,0x81,0x40,0x79,0xC8,0x80,0x10,0x46, + 0x00,0x21,0x60,0x38,0x14,0x4B,0xC1,0x75,0x08,0x46,0xE0,0x3B,0x84,0x00,0xE4,0x18, + 0x21,0x70,0x40,0x1C,0xC0,0xB2,0x0A,0x28,0xF8,0xD3,0x00,0x20,0x20,0x23,0x91,0x6A, + 0x03,0xE0,0x10,0xC9,0x23,0x70,0x40,0x1C,0xC0,0xB2,0xD4,0x6B,0x24,0x79,0x84,0x42, + 0xF7,0xD8,0x02,0x20,0x02,0xF0,0x56,0xF8,0x02,0x20,0x01,0xF0,0x73,0xFE,0x05,0x48, + 0x01,0x21,0xA0,0x30,0x81,0x70,0x70,0xBD,0x00,0x03,0x00,0x40,0x83,0x10,0x00,0x00, + 0x00,0x10,0x00,0x40,0xC4,0x00,0x00,0x20,0xE0,0x12,0x00,0x40,0x02,0xF0,0xBA,0xFA, + 0x05,0x4C,0x60,0x7D,0x00,0x28,0x04,0xD0,0x06,0x28,0xFA,0xD1,0x02,0xF0,0xD2,0xFF, + 0xF7,0xE7,0x03,0xF0,0x8D,0xF8,0xF4,0xE7,0x64,0x00,0x00,0x20,0xF7,0xB5,0x0C,0x46, + 0x27,0x49,0x00,0x27,0x49,0x68,0x03,0x46,0x8D,0x7F,0xC9,0x7F,0x23,0x4A,0x4D,0x43, + 0x39,0x46,0x03,0xE0,0x49,0x1C,0x02,0x80,0x89,0xB2,0x80,0x1C,0xA9,0x42,0xF9,0xD3, + 0x00,0x26,0x33,0xE0,0x02,0x9A,0x00,0x2A,0x02,0xD0,0x92,0x5D,0x00,0x2A,0x01,0xD0, + 0x00,0x25,0x24,0xE0,0xC0,0x7F,0x40,0x00,0xC3,0x18,0x04,0x19,0x24,0xE0,0x00,0x20, + 0x20,0x5E,0xC9,0x78,0x88,0x42,0x16,0xDB,0xFE,0xF7,0x18,0xFA,0xC0,0xB2,0xB8,0x42, + 0x00,0xD9,0x07,0x46,0x13,0x49,0x40,0x00,0x09,0x5A,0x10,0x4A,0x91,0x42,0x06,0xD0, + 0x1A,0x88,0x89,0x04,0x92,0x0B,0x92,0x03,0x89,0x0C,0x0A,0x43,0x1A,0x80,0xF1,0x01, + 0x0C,0x4A,0x29,0x43,0x11,0x52,0x6D,0x1C,0x9B,0x1C,0xED,0xB2,0xA4,0x1C,0x08,0x48, + 0x41,0x68,0xC8,0x7F,0xA8,0x42,0xDA,0xD8,0x76,0x1C,0xF6,0xB2,0x04,0x49,0x48,0x68, + 0x82,0x7F,0xB2,0x42,0xC6,0xD8,0x38,0x46,0xFE,0xBD,0x00,0x00,0xFF,0x3F,0x00,0x00, + 0x30,0x00,0x00,0x20,0xA4,0x0A,0x00,0x20,0x70,0xB5,0x01,0x22,0xD2,0x02,0x11,0x1A, + 0x00,0x29,0x00,0xDC,0x81,0x1A,0x8D,0xB2,0x09,0x4E,0x01,0x21,0x4A,0x00,0xB4,0x5A, + 0x23,0x1A,0x00,0x2B,0x00,0xDC,0x03,0x1B,0x9A,0xB2,0xAA,0x42,0x04,0xD2,0x49,0x1C, + 0xC9,0xB2,0x15,0x46,0x5A,0x29,0xF1,0xD9,0x49,0x1E,0xC8,0xB2,0x70,0xBD,0x00,0x00, + 0x96,0x7C,0x00,0x00,0x10,0xB5,0x03,0x48,0x40,0x88,0x00,0x28,0x01,0xD0,0x00,0xF0, + 0x03,0xFF,0x10,0xBD,0x44,0x01,0x00,0x20,0x70,0x47,0x00,0x00,0x70,0xB5,0x17,0x49, + 0x08,0x7D,0x0C,0x46,0x83,0x07,0x20,0x3C,0xBC,0x20,0x00,0x59,0x00,0x25,0xA2,0x79, + 0x20,0x30,0x00,0x2B,0x02,0xDB,0x0B,0x7A,0xDB,0x09,0x0B,0xD0,0xA5,0x80,0xE5,0x70, + 0xC3,0x79,0x9A,0x42,0x05,0xD1,0x00,0x7A,0x98,0x42,0x02,0xD0,0xA0,0x71,0x01,0x20, + 0x88,0x74,0x70,0xBD,0xE1,0x78,0x0A,0x4E,0x49,0x1C,0xCB,0xB2,0xE3,0x70,0xA1,0x88, + 0xB1,0x42,0x01,0xD2,0x49,0x1C,0xA1,0x80,0x01,0x7B,0x8B,0x42,0xF1,0xD1,0x01,0x7A, + 0x8A,0x42,0xEE,0xD1,0xC0,0x79,0xA0,0x71,0xE5,0x70,0x70,0xBD,0x64,0x00,0x00,0x20, + 0x60,0xEA,0x00,0x00,0x01,0x22,0x03,0x28,0x05,0xD0,0x04,0x28,0x05,0xD0,0x08,0x28, + 0x06,0xD0,0x00,0x22,0x07,0xE0,0x05,0x48,0x04,0xE0,0x04,0x48,0x09,0x30,0x01,0xE0, + 0x02,0x48,0x19,0x30,0x08,0x60,0x10,0x46,0x70,0x47,0x00,0x00,0x4C,0x7D,0x00,0x00, + 0x10,0xB5,0x01,0x24,0x03,0x28,0x05,0xD0,0x04,0x28,0x06,0xD0,0x08,0x28,0x08,0xD0, + 0x00,0x24,0x0B,0xE0,0x06,0x4B,0x02,0x20,0x06,0xE0,0x05,0x4B,0x09,0x33,0x04,0x20, + 0x02,0xE0,0x03,0x4B,0x19,0x33,0x08,0x20,0x08,0x70,0x13,0x60,0x20,0x46,0x10,0xBD, + 0xA5,0x7D,0x00,0x00,0x10,0xB5,0x19,0x4C,0x00,0x20,0x20,0x71,0x01,0x21,0x61,0x71, + 0xA0,0x82,0x21,0x46,0xE0,0x82,0x20,0x31,0x48,0x80,0x48,0x60,0x88,0x60,0xA0,0x72, + 0xE0,0x72,0x20,0x72,0x60,0x72,0x02,0x22,0xFF,0x21,0x11,0x48,0xFE,0xF7,0x76,0xFC, + 0x08,0x22,0x00,0x21,0x0F,0x48,0xFE,0xF7,0x71,0xFC,0x08,0x22,0x00,0x21,0x0E,0x48, + 0xFE,0xF7,0x6C,0xFC,0x08,0x22,0x01,0x21,0x0C,0x48,0xFE,0xF7,0x67,0xFC,0x20,0x46, + 0x07,0x49,0x20,0x38,0xC1,0x62,0x07,0x49,0x81,0x63,0x07,0x49,0xC1,0x63,0x08,0x49, + 0x01,0x63,0x02,0x20,0xA0,0x71,0xE0,0x71,0x10,0xBD,0x00,0x00,0x24,0x01,0x00,0x20, + 0x1C,0x00,0x00,0x20,0x1E,0x00,0x00,0x20,0x26,0x00,0x00,0x20,0x0C,0x00,0x00,0x20, + 0xDC,0x7B,0x00,0x00,0xFE,0xB5,0x75,0x48,0x04,0x46,0x41,0x78,0x20,0x46,0xFF,0x30, + 0x25,0x46,0x41,0x30,0xE0,0x35,0x20,0x34,0x01,0x90,0x05,0x29,0x1A,0xD9,0x80,0x79, + 0x00,0x28,0x17,0xD1,0x6E,0x48,0x00,0x88,0x00,0x28,0x13,0xD1,0xA8,0x70,0x6D,0x4E, + 0x01,0x27,0x07,0xE0,0xF7,0x71,0xFD,0xF7,0xB9,0xFC,0x10,0x20,0xF0,0x71,0xA8,0x78, + 0x00,0x28,0x02,0xD1,0xA0,0x7C,0x00,0x28,0xF4,0xD0,0x67,0x49,0x45,0x20,0x08,0x80, + 0x00,0xE0,0x30,0xBF,0xA0,0x7C,0x00,0x28,0xFB,0xD0,0x61,0x48,0x01,0x88,0x00,0x29, + 0x02,0xD0,0x01,0x88,0x49,0x1E,0x01,0x80,0x5C,0x4F,0xC0,0x37,0x78,0x7F,0x01,0x28, + 0x0D,0xD0,0x00,0x20,0x3E,0x46,0x40,0x36,0x70,0x77,0x78,0x7F,0x79,0x68,0x88,0x74, + 0x79,0x7F,0x30,0x46,0x80,0x38,0x02,0x90,0x02,0x29,0x11,0xD0,0x3F,0xE0,0x57,0x48, + 0x01,0x78,0x10,0x22,0x11,0x43,0x01,0x70,0x00,0x21,0xC1,0x71,0xFF,0x22,0x42,0x75, + 0x02,0x75,0xC1,0x74,0x01,0x74,0x81,0x74,0x41,0x74,0xFD,0xF7,0x7F,0xFC,0xFC,0xE7, + 0x4A,0x4B,0x64,0x20,0x9A,0x88,0x4E,0x49,0x00,0x91,0x00,0x2A,0x02,0xD0,0xD9,0x8C, + 0x00,0x29,0x03,0xD0,0x00,0x9A,0x00,0x21,0x51,0x70,0x10,0xE0,0x00,0x99,0x49,0x78, + 0x02,0x29,0x00,0xD1,0x02,0x20,0x71,0x6A,0x05,0x29,0x01,0xD8,0x02,0x28,0x04,0xD1, + 0x02,0x99,0xC9,0x6B,0x20,0x31,0xC9,0x79,0x99,0x71,0x71,0x6A,0x49,0x1C,0x71,0x62, + 0x71,0x6A,0x81,0x42,0x02,0xD2,0x60,0x7D,0x0A,0x28,0x08,0xD1,0x01,0x98,0x80,0x79, + 0x00,0x28,0x15,0xD0,0x00,0x99,0x00,0x20,0x48,0x70,0x00,0x20,0x70,0x62,0x78,0x7F, + 0xFB,0x21,0x00,0x28,0x31,0xD0,0xE8,0x78,0x01,0x28,0x18,0xD0,0xE8,0x78,0x02,0x28, + 0x24,0xD0,0xE8,0x78,0x08,0x28,0x28,0xD2,0xE8,0x78,0x40,0x1C,0xE8,0x70,0x21,0xE0, + 0x2A,0x48,0x40,0x6D,0xFF,0xF7,0x18,0xFD,0x00,0x98,0x40,0x78,0x01,0x28,0xE4,0xD1, + 0x02,0x98,0xC0,0x6B,0x20,0x30,0x01,0x7A,0x24,0x48,0x81,0x71,0xDD,0xE7,0x23,0x48, + 0x42,0x7A,0x00,0x2A,0x02,0xD1,0x80,0x88,0x04,0x28,0x04,0xD2,0x20,0x7D,0x08,0x40, + 0x20,0x75,0x02,0x20,0x00,0xE0,0x08,0x20,0xE8,0x70,0x06,0xE0,0x1B,0x48,0x40,0x7A, + 0x00,0x28,0x07,0xD0,0x20,0x7D,0x08,0x40,0x20,0x75,0x78,0x68,0x82,0x7A,0xCA,0x2A, + 0x02,0xD0,0x0A,0xE0,0x03,0x20,0xD1,0xE7,0x02,0x7C,0x01,0x2A,0x05,0xD1,0x00,0x22, + 0x02,0x74,0xE0,0x7C,0x01,0x22,0x10,0x43,0xE0,0x74,0x01,0x98,0x80,0x79,0x00,0x28, + 0x02,0xD0,0x01,0x9A,0x40,0x1E,0x90,0x71,0x20,0x7D,0x40,0x07,0x08,0xD5,0x0F,0x48, + 0x03,0x7C,0x02,0x9A,0xD2,0x6B,0x55,0x7C,0x01,0x22,0xAA,0x40,0x93,0x43,0x03,0x74, + 0x20,0x7D,0x22,0x7D,0x40,0x07,0xC0,0x0F,0xC0,0x00,0xF7,0x23,0x1A,0x40,0x02,0x43, + 0x22,0x75,0x20,0x7D,0x08,0x40,0x20,0x75,0xFE,0xBD,0x00,0x00,0x44,0x00,0x00,0x20, + 0x02,0x00,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x10,0x00,0x40,0x00,0x03,0x00,0x40, + 0x64,0x01,0x00,0x20,0x00,0xB5,0x01,0x20,0x80,0x07,0x42,0x88,0x04,0x21,0x8A,0x43, + 0x42,0x80,0x0C,0x48,0x02,0x88,0x0A,0x43,0x02,0x80,0x0B,0x48,0x01,0x7A,0xC9,0x08, + 0xC9,0x00,0x01,0x72,0x00,0x21,0x81,0x72,0x08,0x48,0x01,0x74,0x81,0x7C,0x49,0x06, + 0x49,0x0E,0x81,0x74,0x01,0x20,0x01,0xF0,0x1D,0xFC,0x00,0x21,0x08,0x46,0x01,0xF0, + 0x1B,0xFD,0x00,0xBD,0x00,0x10,0x00,0x40,0x00,0x03,0x00,0x40,0xE0,0x12,0x00,0x40, + 0xF3,0xB5,0x87,0xB0,0x00,0x26,0x9B,0xE0,0x38,0x20,0x07,0x99,0x70,0x43,0x44,0x18, + 0xA0,0x78,0x00,0x28,0x7E,0xD0,0x01,0x28,0x12,0xD0,0x03,0x28,0x04,0xD3,0x4B,0x48, + 0x00,0x68,0xC0,0x79,0x00,0x28,0x10,0xD0,0xA0,0x89,0x21,0x8A,0x40,0x18,0xA1,0x8A, + 0x40,0x1A,0x05,0xB2,0xE0,0x89,0x61,0x8A,0x40,0x18,0xE1,0x8A,0x40,0x1A,0x19,0xE0, + 0x0C,0x25,0x0E,0x20,0x65,0x5F,0x20,0x5E,0x15,0xE0,0x21,0x8A,0xA0,0x89,0x49,0x00, + 0x41,0x18,0xA0,0x8A,0x42,0x00,0x80,0x18,0x08,0x1A,0x21,0x8B,0x40,0x18,0x05,0xB2, + 0x61,0x8A,0xE0,0x89,0x49,0x00,0x41,0x18,0xE0,0x8A,0x42,0x00,0x80,0x18,0x08,0x1A, + 0x61,0x8B,0x40,0x18,0x00,0xB2,0x00,0x2D,0x01,0xDA,0x00,0x25,0x06,0xE0,0x33,0x49, + 0x09,0x68,0x09,0x8A,0x49,0x1E,0xA9,0x42,0x00,0xDA,0x0D,0xB2,0x00,0x28,0x01,0xDA, + 0x00,0x20,0x06,0xE0,0x2D,0x49,0x09,0x68,0x49,0x8A,0x49,0x1E,0x81,0x42,0x00,0xDA, + 0x08,0xB2,0xA5,0x84,0xE0,0x84,0xE1,0x89,0x40,0x1A,0x28,0x49,0x09,0x68,0x02,0x91, + 0x49,0x78,0x05,0x91,0x48,0x43,0x02,0x99,0x49,0x8A,0xFB,0xF7,0xA1,0xF9,0x21,0x46, + 0x20,0x31,0x00,0x91,0x01,0x91,0x49,0x7A,0x04,0x91,0x0A,0x07,0x12,0x0F,0x82,0x18, + 0x09,0x09,0x40,0x18,0x40,0xB2,0x03,0x90,0xA0,0x89,0x02,0x99,0x28,0x1A,0x8D,0x78, + 0x57,0xB2,0x68,0x43,0x09,0x8A,0xFB,0xF7,0x8B,0xF9,0x01,0x99,0x8A,0x7A,0x11,0x07, + 0x09,0x0F,0x41,0x18,0x13,0x09,0xC0,0x18,0x49,0xB2,0x40,0xB2,0x00,0x2F,0x00,0xDA, + 0x00,0x27,0x05,0x9B,0x03,0x9C,0x5B,0x1E,0xA3,0x42,0x01,0xDA,0x5B,0xB2,0x03,0x93, + 0x00,0x29,0x00,0xE0,0x12,0xE0,0x00,0xDA,0x00,0x21,0x6D,0x1E,0x85,0x42,0x00,0xDA, + 0x68,0xB2,0x03,0x9C,0x3B,0x07,0x1B,0x0F,0x24,0x01,0x23,0x43,0x09,0x07,0x00,0x9C, + 0x09,0x0F,0x00,0x01,0x63,0x72,0x01,0x43,0x00,0x98,0x81,0x72,0x76,0x1C,0xF6,0xB2, + 0x08,0x98,0x86,0x42,0x00,0xD2,0x5F,0xE7,0x09,0xB0,0xF0,0xBD,0x38,0x00,0x00,0x20, + 0x03,0x48,0x02,0x49,0x81,0x60,0xC0,0x68,0x70,0x47,0x00,0x00,0xC0,0x7F,0x00,0x00, + 0x00,0x01,0x00,0x40,0x01,0x46,0x09,0x48,0x30,0xB5,0x03,0x46,0x40,0x33,0x1D,0x46, + 0xC4,0x6B,0xC0,0x3D,0x18,0x89,0x2D,0x7A,0x22,0x79,0x80,0xB2,0x01,0x2D,0x02,0xD1, + 0x18,0x8A,0xE2,0x79,0x80,0xB2,0xFD,0xF7,0x1D,0xFC,0x30,0xBD,0xC4,0x00,0x00,0x20, + 0xFE,0xB5,0x49,0x48,0x48,0x49,0x40,0x7A,0x80,0x31,0x00,0x25,0x00,0x91,0x00,0x28, + 0x12,0xD0,0xC9,0x6B,0x00,0x9A,0x00,0x20,0xC9,0x7A,0x52,0x69,0x0A,0xE0,0x38,0x23, + 0x43,0x43,0xD3,0x56,0x00,0x2B,0x03,0xDD,0x6D,0x1C,0xED,0xB2,0xA9,0x42,0x03,0xD0, + 0x40,0x1C,0xC0,0xB2,0x81,0x42,0xF2,0xD8,0x00,0x20,0x3B,0x4F,0x3B,0x4C,0x06,0x46, + 0x20,0x37,0x01,0x90,0x1D,0xE0,0x00,0x98,0x41,0x69,0x38,0x20,0x70,0x43,0x08,0x56, + 0x00,0x28,0x14,0xDD,0x02,0xAA,0x21,0x46,0x30,0x46,0x01,0xF0,0xDF,0xFD,0x01,0x98, + 0x64,0x1D,0x00,0x28,0x07,0xD1,0x38,0x7A,0xC0,0x09,0xC0,0x01,0x28,0x43,0x20,0x70, + 0xAB,0x20,0x60,0x70,0xA4,0x1C,0x01,0x98,0x40,0x1C,0xC0,0xB2,0x01,0x90,0x76,0x1C, + 0xF6,0xB2,0x00,0x98,0xC0,0x6B,0xC0,0x7A,0xB0,0x42,0xDC,0xD8,0x38,0x7A,0xC1,0x09, + 0x0A,0xD0,0x20,0x70,0xB8,0x7A,0x00,0x2D,0x60,0x70,0x01,0xD0,0xA4,0x1C,0x05,0xE0, + 0x80,0x20,0x60,0x71,0xA4,0x1D,0x01,0xE0,0x01,0x2D,0x02,0xD9,0xAB,0x20,0x20,0x70, + 0x64,0x1C,0x20,0x46,0xFD,0xF7,0xF8,0xFC,0x1C,0x48,0x01,0x79,0x49,0x06,0x49,0x0E, + 0x01,0x71,0x01,0x79,0x1A,0x4A,0x12,0x7A,0xD2,0x09,0xD2,0x01,0x11,0x43,0x01,0x71, + 0x03,0x46,0x20,0x33,0x05,0x2D,0x23,0xD2,0x39,0x7A,0x00,0x20,0xC9,0x09,0x01,0xD0, + 0x03,0x20,0x03,0xE0,0x01,0x2D,0x01,0xD9,0x01,0x20,0x03,0xE0,0x00,0x2D,0x01,0xD1, + 0x01,0x25,0x00,0x20,0x6D,0x1E,0xA9,0x00,0x69,0x18,0x08,0x18,0xC0,0x1D,0xC4,0xB2, + 0x68,0x46,0x04,0x72,0x55,0x22,0x09,0x49,0x00,0x20,0x05,0xE0,0x0D,0x78,0x49,0x1C, + 0xAA,0x18,0x40,0x1C,0xD2,0xB2,0x80,0xB2,0xA0,0x42,0xF7,0xD3,0x1A,0x70,0xFE,0xBD, + 0x00,0x20,0x18,0x70,0xFE,0xBD,0x00,0x00,0x44,0x00,0x00,0x20,0xEB,0x08,0x00,0x20, + 0x84,0x01,0x00,0x20,0x0A,0x46,0x10,0xB5,0x0F,0x49,0x03,0x46,0x4C,0x7D,0x00,0x20, + 0x01,0x2C,0x10,0xD0,0x4C,0x7D,0x05,0x2C,0x0D,0xD0,0x4C,0x7D,0x08,0x2C,0x0A,0xD0, + 0x4C,0x7D,0x04,0x2C,0x0A,0xD0,0x4A,0x7D,0x03,0x2A,0x02,0xD0,0x49,0x7D,0x06,0x29, + 0x00,0xD1,0x01,0x20,0x10,0xBD,0x48,0x7D,0x19,0x46,0x01,0xE0,0x19,0x46,0x04,0x20, + 0x00,0xF0,0x04,0xF8,0xF5,0xE7,0x00,0x00,0x64,0x00,0x00,0x20,0xF7,0xB5,0x24,0x4D, + 0x86,0xB0,0xE9,0x6B,0x04,0x91,0xA9,0x6B,0x13,0x46,0x03,0x91,0x04,0x28,0x0C,0xD0, + 0x68,0x46,0xFD,0xF7,0x89,0xFC,0x0B,0x22,0x69,0x46,0x18,0x46,0xFE,0xF7,0x86,0xF9, + 0x07,0x98,0x01,0xF0,0xCD,0xFB,0x09,0xB0,0xF0,0xBD,0x19,0x4C,0x6F,0x6D,0x80,0x34, + 0xE0,0x6B,0xAB,0x6D,0xC6,0x78,0x00,0x79,0x46,0x43,0x68,0x46,0xFD,0xF7,0x44,0xFC, + 0x32,0x46,0x19,0x46,0x38,0x46,0xFE,0xF7,0x71,0xF9,0xBE,0x19,0x0B,0x22,0x69,0x46, + 0x30,0x46,0xFE,0xF7,0x6B,0xF9,0xE0,0x6B,0x0B,0x36,0x02,0x79,0x30,0x46,0x69,0x6F, + 0xFE,0xF7,0x64,0xF9,0xE0,0x6B,0x01,0x79,0xC2,0x78,0x8E,0x19,0x30,0x46,0xE9,0x6D, + 0xFE,0xF7,0x5C,0xF9,0xE0,0x6B,0xC1,0x78,0x02,0x79,0x8D,0x19,0x28,0x46,0x04,0x99, + 0xFE,0xF7,0x54,0xF9,0xE0,0x6B,0x03,0x99,0x02,0x79,0x50,0x19,0xC6,0xE7,0x00,0x00, + 0x44,0x00,0x00,0x20,0x10,0xB5,0x0C,0x46,0x01,0x46,0x0B,0x48,0xC0,0x6B,0xC2,0x78, + 0x03,0x79,0xC0,0x79,0xD2,0x18,0x05,0x28,0x01,0xD2,0x04,0x20,0x00,0xE0,0x08,0x20, + 0x10,0x18,0x42,0x00,0x04,0x48,0x80,0x38,0x80,0x6D,0xFE,0xF7,0x37,0xF9,0x20,0x46, + 0x01,0xF0,0x7E,0xFB,0x10,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20,0xF8,0xB5,0x1E,0x4E, + 0x30,0x7C,0x1E,0x4D,0x01,0x27,0xE9,0x6B,0x4A,0x7C,0x39,0x46,0x91,0x40,0x08,0x43, + 0x30,0x74,0x2C,0x46,0x60,0x3C,0x60,0x7D,0x00,0x28,0x05,0xD0,0x18,0x49,0x14,0x20, + 0xFF,0xF7,0x60,0xFF,0x00,0x28,0x25,0xD1,0x20,0x7D,0x00,0x07,0x02,0xD5,0x01,0x20, + 0x02,0xF0,0x6E,0xFA,0x11,0x48,0x80,0x38,0x40,0x7A,0x00,0x28,0x07,0xD1,0xE9,0x6B, + 0xA0,0x7B,0xC9,0x7C,0x88,0x42,0x15,0xD3,0x20,0x7A,0x00,0x06,0x12,0xD5,0x60,0x7C, + 0x00,0x28,0x0F,0xD1,0x30,0x7C,0xE9,0x6B,0x49,0x7C,0x8F,0x40,0x38,0x43,0x30,0x74, + 0x06,0x48,0x07,0x49,0x40,0x30,0x01,0x60,0xFF,0xF7,0xA2,0xFE,0x20,0x7D,0x04,0x21, + 0x08,0x43,0x20,0x75,0xF8,0xBD,0x00,0x00,0x00,0x03,0x00,0x40,0xC4,0x00,0x00,0x20, + 0xEB,0x08,0x00,0x20,0x00,0xB5,0x05,0x49,0xAA,0x20,0x88,0x80,0x04,0x48,0x00,0x21, + 0x81,0x74,0x20,0x38,0x80,0x79,0x01,0xF0,0x81,0xFC,0x00,0xBD,0x00,0x02,0x00,0x40, + 0x64,0x00,0x00,0x20,0xF0,0xB5,0x88,0x49,0x8D,0xB0,0x08,0x46,0x8E,0x78,0x80,0x30, + 0x09,0x90,0xC0,0x6B,0x01,0x23,0x87,0x79,0x42,0x79,0x0A,0x92,0x02,0x79,0x09,0x6D, + 0x72,0x43,0x52,0x00,0x8D,0x18,0x80,0x4A,0xE0,0x32,0x08,0x92,0x13,0x70,0xC0,0x3A, + 0xD2,0x7D,0x00,0x2A,0x7E,0xD0,0x7D,0x4C,0xBE,0x42,0x7C,0xD2,0x22,0x46,0xA1,0x7C, + 0x20,0x7C,0x20,0x3A,0xD2,0x6B,0x41,0x43,0x02,0x90,0x89,0x18,0x78,0x48,0x01,0x91, + 0x81,0x7C,0x49,0x06,0x49,0x0E,0x81,0x74,0x00,0x21,0x03,0xA8,0xFF,0xF7,0x42,0xFE, + 0xA0,0x7C,0x79,0x1E,0x82,0x19,0x8A,0x42,0x43,0xD2,0x00,0x2E,0x08,0xD1,0x00,0x28, + 0x06,0xD1,0x00,0x21,0x01,0x20,0x01,0xF0,0xC7,0xFB,0x01,0x20,0x01,0xF0,0xA6,0xF9, + 0x6B,0x48,0x81,0x7C,0x80,0x22,0x11,0x43,0x81,0x74,0xD0,0x05,0x41,0x88,0x08,0x22, + 0x11,0x43,0x41,0x80,0x67,0x49,0x0A,0x88,0x02,0x23,0x1A,0x43,0x0A,0x80,0x41,0x88, + 0x04,0x22,0x11,0x43,0x41,0x80,0x20,0x7C,0xA1,0x7C,0x82,0x1E,0x91,0x42,0x05,0xD0, + 0x02,0x9A,0x01,0x2A,0x12,0xD1,0xBA,0x1E,0x96,0x42,0x0F,0xD1,0x42,0x00,0x92,0x19, + 0xBA,0x42,0x01,0xD9,0x38,0x1A,0x01,0xE0,0xB6,0x1C,0x88,0x19,0x56,0x49,0xC0,0xB2, + 0xC9,0x6D,0x08,0x5C,0x01,0x02,0x01,0x43,0x56,0x48,0xC1,0x81,0xE0,0x7C,0x00,0x21, + 0x40,0x1C,0xC0,0xB2,0x01,0xF0,0x90,0xFB,0xE0,0x7C,0x40,0x1C,0xC0,0xB2,0x01,0xF0, + 0x6D,0xF9,0x22,0x7C,0x0B,0xA8,0x01,0x99,0xFE,0xF7,0x60,0xF8,0x02,0x98,0x0A,0x9A, + 0x00,0x02,0x10,0x43,0x11,0x21,0x00,0x90,0x01,0x91,0x03,0xA8,0x81,0xB2,0x0B,0xA8, + 0xAB,0xB2,0xAA,0xB2,0x80,0xB2,0xFD,0xF7,0x01,0xFA,0x02,0x99,0xA0,0x7C,0x49,0x1E, + 0x88,0x42,0x2A,0xD1,0x40,0x49,0x02,0x9A,0x8B,0x78,0x00,0x20,0x9A,0x18,0x8A,0x70, + 0xA0,0x74,0x01,0xE0,0x64,0xE0,0x3C,0xE0,0x61,0x7C,0x02,0x29,0x04,0xD0,0x04,0x29, + 0x04,0xD0,0x08,0x29,0x04,0xD0,0x04,0xE0,0x01,0x20,0x02,0xE0,0x02,0x20,0x00,0xE0, + 0x03,0x20,0x02,0x99,0x01,0x29,0x12,0xD0,0x00,0x28,0x10,0xD0,0x22,0x7C,0x0A,0x99, + 0x4A,0x43,0x00,0x21,0x06,0xE0,0x00,0x23,0xEB,0x5E,0x03,0x41,0x2B,0x80,0xAD,0x1C, + 0x49,0x1C,0x89,0xB2,0x91,0x42,0xF6,0xD3,0x01,0xE0,0x40,0x1C,0xA0,0x74,0x2A,0x4A, + 0x90,0x78,0x39,0x1A,0x20,0x7C,0x81,0x42,0x3C,0xDA,0x00,0x29,0x3A,0xDD,0x41,0x1A, + 0x38,0x1A,0xC0,0xB2,0xCB,0xB2,0x90,0x70,0x09,0x99,0x12,0x6D,0xC9,0x6B,0x09,0x79, + 0x48,0x43,0x40,0x00,0x80,0x18,0x59,0x43,0x4A,0x00,0x00,0x21,0xFE,0xF7,0x16,0xF8, + 0x28,0xE0,0xBE,0x42,0x26,0xD1,0x01,0x22,0x92,0x07,0x54,0x88,0x04,0x23,0x9C,0x43, + 0x54,0x80,0x00,0x79,0x18,0x4C,0x70,0x43,0x40,0x00,0x08,0x18,0x00,0x21,0xFF,0xF7, + 0x89,0xFD,0x00,0x20,0x01,0xF0,0xC6,0xFA,0x00,0x21,0x08,0x46,0x01,0xF0,0xE4,0xF9, + 0x01,0x21,0x32,0x46,0x08,0x46,0x01,0xF0,0xD9,0xFB,0x00,0x20,0x20,0x72,0x09,0x98, + 0xC0,0x6B,0x40,0x30,0x81,0x8A,0x0F,0x48,0xC1,0x80,0x08,0x99,0x01,0x20,0x48,0x70, + 0x0D,0xB0,0xF0,0xBD,0x08,0x48,0x80,0x78,0xB8,0x42,0x03,0xD0,0xE0,0x7C,0x40,0x1C, + 0xE0,0x74,0xF5,0xE7,0x00,0x20,0x01,0xF0,0xA5,0xFA,0x08,0x99,0x01,0x20,0x48,0x70, + 0xFF,0xF7,0x88,0xFC,0xEC,0xE7,0x00,0x00,0x44,0x00,0x00,0x20,0x64,0x01,0x00,0x20, + 0xE0,0x12,0x00,0x40,0x00,0x10,0x00,0x40,0xFF,0xB5,0x01,0x20,0x81,0xB0,0x00,0x90, + 0x01,0x2A,0x01,0xD1,0x00,0x20,0x00,0x90,0x3A,0x49,0x39,0x48,0x48,0x82,0x00,0x27, + 0x62,0xE0,0x04,0x98,0xB9,0x00,0x0E,0x18,0x31,0x68,0x0F,0x20,0x08,0x70,0x30,0x68, + 0xBF,0x21,0x20,0x38,0xC1,0x77,0x33,0x4C,0x33,0x48,0x20,0x81,0x33,0x48,0x60,0x81, + 0x3A,0x46,0x03,0x21,0x00,0x98,0x01,0xF0,0x91,0xFB,0xA5,0x04,0x68,0x89,0x80,0x21, + 0x08,0x43,0x68,0x81,0x2E,0x48,0x20,0x80,0x2D,0x48,0x42,0x38,0x20,0x80,0x01,0x21, + 0x08,0x20,0xFD,0xF7,0x37,0xF8,0x69,0x89,0x80,0x20,0x81,0x43,0x69,0x81,0x00,0x24, + 0x20,0x25,0x2C,0x43,0xE0,0xB2,0x01,0xF0,0x6B,0xF8,0x21,0x48,0x21,0x49,0x40,0x38, + 0x48,0x82,0x01,0x21,0x64,0x20,0xFD,0xF7,0x25,0xF8,0x1E,0x49,0x21,0x48,0x48,0x82, + 0x01,0x21,0x64,0x20,0xFD,0xF7,0x1E,0xF8,0x30,0x68,0x00,0x78,0x00,0x06,0x00,0xD4, + 0xAC,0x43,0x6D,0x08,0xE5,0xD1,0x17,0x49,0x15,0x48,0x48,0x82,0x80,0x06,0x41,0x89, + 0x80,0x22,0x11,0x43,0x41,0x81,0x3A,0x46,0x01,0x21,0x00,0x98,0x01,0xF0,0x56,0xFB, + 0x31,0x68,0x30,0x20,0x08,0x70,0x30,0x68,0x00,0x21,0x20,0x38,0xC1,0x77,0x00,0x2C, + 0x00,0xD1,0x01,0x24,0x02,0x98,0x10,0x49,0x04,0x80,0x02,0x98,0x80,0x1C,0x02,0x90, + 0xAA,0x20,0x88,0x80,0x7F,0x1C,0xFF,0xB2,0x01,0x98,0x87,0x42,0x99,0xD3,0x01,0x20, + 0x80,0x07,0x41,0x89,0x80,0x22,0x11,0x43,0x41,0x81,0x05,0xB0,0xF0,0xBD,0x00,0x00, + 0xD0,0x82,0x00,0x00,0x00,0x10,0x00,0x40,0xE0,0xE8,0x00,0x00,0xFF,0x02,0x00,0x00, + 0x45,0x08,0x00,0x00,0x90,0x80,0x00,0x00,0x00,0x02,0x00,0x40,0x70,0xB5,0x0E,0x4A, + 0x0D,0x4C,0xD2,0x6B,0x80,0x3C,0x95,0x78,0x13,0x79,0xD6,0x79,0x92,0x79,0x64,0x6D, + 0x5A,0x43,0x52,0x00,0xA3,0x18,0x00,0x22,0x0B,0xE0,0x00,0x24,0x1C,0x5F,0xAC,0x42, + 0x04,0xDB,0x0C,0x78,0x02,0x55,0x0C,0x78,0x64,0x1C,0x0C,0x70,0x9B,0x1C,0x52,0x1C, + 0xD2,0xB2,0xB2,0x42,0xF1,0xD3,0x70,0xBD,0xC4,0x00,0x00,0x20,0xFF,0xB5,0x30,0x49, + 0x1C,0x46,0xC9,0x6B,0x83,0xB0,0x0E,0x79,0x0B,0x7B,0x00,0x02,0x20,0x31,0x01,0x93, + 0x89,0x78,0x15,0x46,0x08,0x43,0x2B,0x49,0x0C,0x9A,0x08,0x81,0x00,0x2A,0x00,0xD0, + 0x90,0x47,0x00,0x20,0x28,0x4A,0x05,0xE0,0x41,0x00,0x00,0x23,0x6A,0x52,0x40,0x1C, + 0x63,0x52,0xC0,0xB2,0xB0,0x42,0xF7,0xD3,0x21,0x48,0x00,0x27,0x60,0x30,0x00,0x90, + 0x2B,0xE0,0x22,0x49,0xA3,0x20,0x88,0x74,0x00,0x9A,0x00,0x20,0x10,0x70,0x1D,0x48, + 0x11,0x22,0x82,0x80,0x45,0x22,0x02,0x80,0x43,0x22,0x02,0x80,0x00,0xE0,0x30,0xBF, + 0x00,0x98,0x00,0x78,0x00,0x28,0xFA,0xD0,0x23,0x20,0x88,0x74,0x00,0x21,0x04,0x98, + 0xFF,0xF7,0x70,0xFC,0x00,0x21,0x0C,0xE0,0x4A,0x00,0x04,0x98,0xAB,0x5E,0x80,0x5A, + 0x83,0x42,0x00,0xDD,0xA8,0x52,0xA3,0x5E,0x83,0x42,0x00,0xDA,0xA0,0x52,0x49,0x1C, + 0xC9,0xB2,0xB1,0x42,0xF0,0xD3,0x78,0x1C,0xC7,0xB2,0x01,0x99,0x8F,0x42,0xD0,0xD3, + 0x00,0x21,0x08,0x46,0x07,0xE0,0x42,0x00,0xA3,0x5A,0xAA,0x5A,0x9A,0x1A,0x51,0x18, + 0x40,0x1C,0x89,0xB2,0xC0,0xB2,0xB0,0x42,0xF5,0xD3,0x88,0x08,0x07,0xB0,0xF0,0xBD, + 0xC4,0x00,0x00,0x20,0x00,0x10,0x00,0x40,0xFF,0x7F,0x00,0x00,0xE0,0x12,0x00,0x40, + 0x30,0xB5,0x05,0x46,0x0C,0x46,0x10,0x46,0x01,0xF0,0xC0,0xFD,0x21,0x46,0x28,0x46, + 0xFF,0xF7,0x38,0xFC,0x30,0xBD,0x00,0x00,0xF8,0xB5,0x26,0x4C,0xE0,0x6B,0x81,0x79, + 0x42,0x79,0x20,0x46,0x51,0x43,0x80,0x38,0x4A,0x00,0x00,0x6D,0x00,0x21,0xFD,0xF7, + 0xA5,0xFE,0x21,0x48,0x81,0x7C,0x80,0x22,0x11,0x43,0x81,0x74,0xE0,0x6B,0x54,0x21, + 0x1E,0x4D,0x09,0x5A,0xE9,0x80,0x00,0x26,0x21,0x46,0x60,0x31,0x4E,0x70,0x0E,0x70, + 0x20,0x30,0xC1,0x7D,0x80,0x7D,0x89,0x00,0x00,0x01,0x01,0x43,0x43,0x20,0x01,0x43, + 0x17,0x48,0x01,0x72,0xA0,0x34,0xE6,0x74,0xD7,0x05,0x78,0x88,0x04,0x21,0x08,0x43, + 0x78,0x80,0x10,0x48,0x80,0x38,0xC0,0x6D,0x00,0x78,0x01,0x02,0x01,0x43,0xE9,0x81, + 0x00,0x21,0x02,0x20,0x01,0xF0,0x60,0xF8,0x00,0x20,0x00,0xF0,0x6F,0xFF,0x78,0x88, + 0x08,0x21,0x08,0x43,0x78,0x80,0x11,0x20,0xA8,0x80,0x45,0x20,0x28,0x80,0x43,0x20, + 0x28,0x80,0x04,0x48,0x80,0x38,0x86,0x70,0xA6,0x74,0xE0,0x7C,0x40,0x1C,0xE0,0x74, + 0xF8,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20,0xE0,0x12,0x00,0x40,0x00,0x10,0x00,0x40, + 0x00,0x03,0x00,0x40,0x10,0xB5,0xFA,0xF7,0x9D,0xFF,0xFC,0xF7,0x9F,0xFC,0x11,0x4C, + 0x00,0x20,0x20,0x72,0x20,0x46,0x02,0x21,0x20,0x30,0xC1,0x75,0xFF,0xF7,0x9C,0xFF, + 0x60,0x78,0x05,0x28,0x04,0xD9,0xE0,0x1D,0xF9,0x30,0x40,0x7F,0x00,0x28,0x06,0xD0, + 0x08,0x48,0xE0,0x30,0x41,0x78,0x00,0x29,0x09,0xD0,0xFC,0xF7,0x87,0xFC,0xFD,0xF7, + 0x3F,0xF9,0x60,0x78,0xC8,0x28,0x01,0xD2,0x40,0x1C,0x60,0x70,0x10,0xBD,0x30,0xBF, + 0xF0,0xE7,0x00,0x00,0x44,0x00,0x00,0x20,0x70,0xB5,0x1D,0x4E,0x3C,0x25,0x00,0x20, + 0x33,0x6E,0x02,0x46,0x01,0x46,0x00,0x24,0x1C,0x5F,0xAC,0x42,0x01,0xDD,0x52,0x1C, + 0x20,0x18,0x9B,0x1C,0x49,0x1C,0x09,0x29,0xF5,0xD3,0x00,0x21,0xB4,0x6F,0x0B,0x46, + 0x00,0x26,0xA6,0x5F,0xAE,0x42,0x01,0xDD,0x49,0x1C,0x30,0x18,0xA4,0x1C,0x5B,0x1C, + 0x08,0x2B,0xF5,0xD3,0x0F,0x4C,0x06,0x2A,0xA3,0x7F,0x01,0xD9,0x05,0x29,0x02,0xD8, + 0x51,0x18,0x0B,0x29,0x07,0xD9,0xAF,0x21,0xC9,0x00,0x88,0x42,0x03,0xD9,0x0A,0x2B, + 0x05,0xD2,0x5B,0x1C,0x02,0xE0,0x00,0x2B,0x01,0xD0,0x5B,0x1E,0xA3,0x77,0x05,0x48, + 0x40,0x38,0x40,0x7E,0x00,0x28,0x01,0xD0,0x00,0x20,0xA0,0x77,0x70,0xBD,0x00,0x00, + 0x44,0x00,0x00,0x20,0x44,0x01,0x00,0x20,0xF0,0xB5,0x60,0x48,0x8B,0xB0,0x81,0x6F, + 0x80,0x30,0xC0,0x6B,0x0E,0x46,0xC7,0x78,0x00,0x79,0x09,0x90,0x5B,0x48,0xE0,0x30, + 0xC0,0x8A,0x64,0x28,0x01,0xD2,0x00,0x20,0x06,0xE0,0x64,0x38,0xFF,0x22,0x80,0xB2, + 0x91,0x32,0x90,0x42,0x00,0xD9,0x10,0x46,0x80,0x08,0xFA,0x30,0x07,0x90,0x00,0x20, + 0x05,0x46,0x04,0x46,0x08,0x90,0x0B,0xE0,0x00,0x22,0x8A,0x5E,0x3C,0x2A,0x01,0xDD, + 0x6D,0x1C,0xED,0xB2,0xA2,0x42,0x00,0xDD,0x14,0x46,0x89,0x1C,0x40,0x1C,0x80,0xB2, + 0xB8,0x42,0xF1,0xD3,0xB8,0x00,0x05,0x21,0xFA,0xF7,0x88,0xFC,0xA8,0x42,0x07,0xD2, + 0xFF,0x20,0x2D,0x30,0x84,0x42,0x03,0xDD,0xA0,0xB2,0x07,0x90,0x01,0x20,0x08,0x90, + 0x07,0x98,0x84,0x42,0x00,0xDD,0x04,0xB2,0x00,0x25,0x58,0xE0,0x00,0x22,0x31,0x46, + 0x20,0x39,0xB2,0x5E,0xC9,0x8B,0x6B,0x46,0x99,0x82,0xDA,0x82,0x71,0x88,0x10,0x46, + 0x19,0x83,0x00,0x2D,0x08,0xD0,0x79,0x1E,0x8D,0x42,0x01,0xD1,0x00,0x21,0x19,0x83, + 0x00,0x2A,0x04,0xDC,0x01,0x20,0x06,0xE0,0x00,0x21,0x99,0x82,0xF8,0xE7,0x07,0x9B, + 0x9A,0x42,0x00,0xDD,0x18,0x46,0x6B,0x46,0x14,0x21,0x59,0x5E,0x8C,0x46,0x62,0x45, + 0x14,0xDA,0x18,0x21,0x59,0x5E,0x8A,0x42,0x10,0xDA,0x1E,0x29,0x02,0xDC,0x62,0x46, + 0x1E,0x2A,0x0B,0xDD,0x60,0x46,0x40,0x18,0x40,0x10,0x02,0xB2,0x32,0x80,0x00,0x2A, + 0x04,0xDC,0x60,0x46,0x61,0x45,0x00,0xDC,0x01,0x46,0x48,0x10,0x08,0x99,0x00,0x29, + 0x06,0xD0,0x3C,0x28,0x01,0xD9,0x3C,0x38,0x00,0xE0,0x01,0x20,0x3C,0x3C,0x24,0xB2, + 0x1E,0x2C,0x0A,0xDD,0x00,0x02,0x21,0x46,0xFA,0xF7,0x30,0xFC,0x80,0xB2,0x69,0x00, + 0x6A,0x46,0x50,0x52,0x00,0x28,0x05,0xD0,0x06,0xE0,0xFF,0x21,0x01,0x31,0x6A,0x00, + 0x99,0x52,0x01,0xE0,0x01,0x20,0x50,0x52,0xB6,0x1C,0x6D,0x1C,0xAD,0xB2,0xBD,0x42, + 0xA4,0xD3,0x00,0x22,0x1C,0xE0,0x11,0x48,0x51,0x00,0x40,0x6D,0x09,0x9B,0x41,0x18, + 0x00,0x20,0x5E,0x00,0x10,0xE0,0x00,0x23,0xCB,0x5E,0x0F,0x2B,0x09,0xDB,0x45,0x00, + 0x6C,0x46,0x65,0x5B,0x5D,0x43,0x2D,0x0A,0xEC,0x00,0x64,0x1B,0xE3,0x18,0xDB,0x10, + 0x0B,0x80,0x71,0x18,0x40,0x1C,0xC0,0xB2,0xB8,0x42,0xEC,0xD3,0x52,0x1C,0xD2,0xB2, + 0x09,0x98,0x82,0x42,0xDF,0xD3,0x0B,0xB0,0xF0,0xBD,0x00,0x00,0x44,0x00,0x00,0x20, + 0xF7,0xB5,0x4E,0x48,0x86,0xB0,0x80,0x6F,0x05,0x90,0x4C,0x48,0x06,0x99,0x80,0x30, + 0x47,0x68,0xC0,0x6B,0x80,0x79,0x04,0x90,0x00,0x20,0x08,0x80,0x03,0x46,0x05,0x46, + 0x00,0x90,0x01,0x90,0x46,0x48,0x1C,0x46,0x2E,0x46,0x00,0x22,0x03,0x90,0x20,0xE0, + 0x05,0x99,0x50,0x00,0x09,0x5A,0x38,0x5A,0x08,0x1A,0x00,0xB2,0x14,0x28,0x01,0xDB, + 0x2D,0x18,0x04,0xE0,0x09,0x21,0xC9,0x43,0x88,0x42,0x00,0xDA,0x36,0x18,0x19,0x18, + 0x0B,0xB2,0x00,0x99,0x81,0x42,0x00,0xDA,0x00,0x90,0x01,0x1B,0x04,0x46,0x01,0x98, + 0x09,0xB2,0x88,0x42,0x00,0xDA,0x01,0x91,0x03,0x98,0x88,0x42,0x00,0xDD,0x03,0x91, + 0x52,0x1C,0x04,0x98,0x82,0x42,0xDB,0xD3,0x01,0x46,0x18,0x46,0xFA,0xF7,0xC0,0xFB, + 0x00,0x24,0x00,0xB2,0x86,0x46,0x20,0x46,0x84,0x46,0x21,0x46,0x02,0x94,0x17,0xE0, + 0x05,0x9B,0x4A,0x00,0x9B,0x5A,0xBA,0x5A,0x9A,0x1A,0x12,0xB2,0x72,0x45,0x06,0xDB, + 0x08,0x9B,0x9A,0x42,0x03,0xDD,0x40,0x1C,0x94,0x44,0xC0,0xB2,0x07,0xE0,0x00,0x2A, + 0x00,0xDA,0x52,0x42,0x02,0x9B,0xD2,0x18,0x64,0x1C,0xE4,0xB2,0x02,0x92,0x49,0x1C, + 0x04,0x9A,0x91,0x42,0xE4,0xD3,0x00,0x21,0x06,0x9A,0x0F,0x46,0x11,0x80,0x00,0x28, + 0x15,0xD0,0x00,0x2C,0x16,0xD0,0x01,0x46,0x60,0x46,0xFA,0xF7,0x91,0xFB,0x04,0x90, + 0x21,0x46,0x02,0x98,0xFA,0xF7,0x8C,0xFB,0x41,0x1C,0x04,0x98,0xFA,0xF7,0x88,0xFB, + 0x06,0x99,0x80,0xB2,0x08,0x80,0x07,0x99,0x88,0x42,0x02,0xD3,0x02,0xE0,0x02,0x2C, + 0x00,0xD3,0x01,0x27,0x64,0x2D,0x03,0xD8,0x63,0x20,0xC0,0x43,0x86,0x42,0x11,0xDA, + 0x01,0x98,0x32,0x28,0x0D,0xDD,0x31,0x21,0x03,0x98,0xC9,0x43,0x88,0x42,0x08,0xDA, + 0x96,0x2D,0x06,0xD9,0x00,0x98,0x3C,0x28,0x03,0xDD,0x77,0x20,0xC0,0x43,0x86,0x42, + 0x00,0xDC,0x01,0x27,0x38,0x46,0x09,0xB0,0xF0,0xBD,0x00,0x00,0x44,0x00,0x00,0x20, + 0xFF,0x7F,0x00,0x00,0xF1,0xB5,0x54,0x48,0x82,0xB0,0xC1,0x6B,0x02,0x46,0x86,0x46, + 0x80,0x3A,0x90,0x6E,0x0E,0x79,0x84,0x46,0x13,0x6F,0xD0,0x6E,0x00,0x93,0x14,0x6E, + 0x02,0x9A,0x00,0x2A,0x08,0xD0,0x4C,0x49,0x00,0x22,0x80,0x39,0x4A,0x61,0x8A,0x61, + 0x00,0x21,0x0B,0x46,0x01,0x91,0x4B,0xE0,0x70,0x46,0x00,0x68,0xCE,0x78,0x84,0x46, + 0x70,0x46,0x71,0x46,0x40,0x68,0x89,0x68,0x00,0x91,0x43,0x49,0x80,0x39,0x8C,0x6F, + 0xEE,0xE7,0x59,0x00,0x62,0x46,0x52,0x5A,0x45,0x5A,0x1A,0x27,0x52,0x1B,0x15,0xB2, + 0x65,0x52,0x72,0x46,0xD2,0x6B,0xD7,0x57,0xAF,0x42,0x09,0xDD,0x02,0x99,0x01,0x29, + 0x2C,0xD1,0x39,0x4D,0x80,0x3D,0x6A,0x69,0x99,0x40,0x0A,0x43,0x6A,0x61,0x25,0xE0, + 0x92,0x7D,0xAA,0x42,0x0E,0xDA,0x14,0x32,0xAA,0x42,0x01,0xDA,0x01,0x21,0x01,0x91, + 0x02,0x99,0x01,0x29,0x1A,0xD1,0x30,0x4D,0x80,0x3D,0xAA,0x69,0x99,0x40,0x0A,0x43, + 0xAA,0x61,0x13,0xE0,0x2C,0x4A,0x60,0x3A,0x12,0x79,0x00,0x2A,0x0E,0xD1,0x00,0x9D, + 0x47,0x5E,0xED,0x5C,0x3A,0x02,0xAA,0x18,0x65,0x46,0x6D,0x5E,0xAD,0x00,0xAA,0x18, + 0xBD,0x00,0x55,0x1B,0x2A,0x12,0x42,0x52,0x00,0x99,0xCD,0x54,0x5B,0x1C,0xDB,0xB2, + 0xB3,0x42,0xBE,0xD3,0x20,0x49,0x80,0x31,0x49,0x7F,0x00,0x29,0x0B,0xD0,0x01,0x99, + 0x00,0x29,0x08,0xD1,0x72,0x00,0x61,0x46,0xFD,0xF7,0x08,0xFC,0x32,0x46,0x00,0x21, + 0x00,0x98,0xFD,0xF7,0x13,0xFC,0x00,0x20,0x13,0x23,0xDB,0x43,0x05,0x46,0x02,0x46, + 0x47,0x1F,0x10,0xE0,0x51,0x00,0x61,0x5E,0xB9,0x42,0x03,0xDA,0x99,0x42,0x07,0xDA, + 0x19,0x46,0x05,0xE0,0x05,0x29,0x03,0xDD,0x14,0x29,0x00,0xDD,0x14,0x21,0x6D,0x1C, + 0x40,0x18,0x52,0x1C,0xD2,0xB2,0xB2,0x42,0xEC,0xD3,0x31,0x46,0xFA,0xF7,0xC8,0xFA, + 0x03,0x2D,0x10,0xD9,0x00,0x22,0x0C,0xE0,0x53,0x00,0xE1,0x5E,0x00,0x28,0x05,0xDD, + 0x81,0x42,0x02,0xDD,0x09,0x1A,0x09,0xB2,0x00,0xE0,0x01,0x21,0x52,0x1C,0xE1,0x52, + 0xD2,0xB2,0xB2,0x42,0xF0,0xD3,0xFE,0xBD,0xC4,0x00,0x00,0x20,0x10,0xB5,0x01,0x46, + 0x08,0x4A,0x10,0x20,0xD0,0x80,0x08,0x48,0x07,0x4B,0xC0,0x6B,0x01,0x22,0x20,0x30, + 0xC0,0x7B,0x60,0x3B,0xDA,0x73,0x40,0x1E,0xA0,0x33,0xC0,0xB2,0x1A,0x77,0x00,0xF0, + 0x05,0xF8,0x10,0xBD,0x00,0x10,0x00,0x40,0xC4,0x00,0x00,0x20,0xF3,0xB5,0x3C,0x4A, + 0x8F,0xB0,0x10,0x6E,0x11,0x46,0x80,0x31,0x0C,0x90,0xC8,0x6B,0x10,0x9B,0x06,0x79, + 0x01,0x2B,0x0E,0xD0,0xCD,0x68,0x91,0x6F,0x0C,0x91,0xC6,0x78,0x40,0x30,0xC0,0x89, + 0x0D,0x90,0x02,0x20,0x0B,0x90,0x00,0x20,0x0A,0x90,0x00,0x20,0x03,0x46,0x31,0x4A, + 0x07,0xE0,0x55,0x6F,0xF2,0xE7,0x44,0x00,0x69,0x46,0x0A,0x53,0x2B,0x54,0x40,0x1C, + 0xC0,0xB2,0xB0,0x42,0xF7,0xD3,0x00,0x24,0x27,0x46,0x40,0xE0,0x01,0x21,0x10,0x98, + 0x00,0xF0,0xF2,0xFA,0x00,0x20,0x1A,0xE0,0x01,0x21,0x81,0x40,0x8C,0x46,0x21,0x42, + 0x13,0xD1,0x0C,0x9A,0x41,0x00,0x53,0x5E,0x0D,0x9A,0x9A,0x1A,0x00,0xD5,0x52,0x42, + 0x6B,0x46,0x5B,0x5A,0x92,0xB2,0x93,0x42,0x02,0xD3,0x6B,0x46,0x5A,0x52,0x04,0xE0, + 0x29,0x5C,0x49,0x1E,0x29,0x54,0x61,0x46,0x0C,0x43,0x40,0x1C,0xC0,0xB2,0xB0,0x42, + 0xE2,0xD3,0x01,0x21,0x08,0x46,0xB0,0x40,0x40,0x1E,0xA0,0x42,0x02,0xD1,0x01,0x20, + 0x0A,0x90,0x17,0xE0,0x0F,0x98,0x7F,0x1C,0x87,0x42,0x13,0xD2,0x00,0x20,0x0B,0x46, + 0x0B,0xE0,0x29,0x5C,0x0F,0x9A,0x91,0x42,0x05,0xD2,0x1A,0x46,0x82,0x40,0x22,0x42, + 0x01,0xD1,0x49,0x1C,0x29,0x54,0x40,0x1C,0xC0,0xB2,0xB0,0x42,0xF1,0xD3,0x0A,0x98, + 0x00,0x28,0xBB,0xD0,0x0B,0x98,0x40,0x1E,0x00,0x06,0x00,0x0E,0x0B,0x90,0x02,0xD0, + 0x0A,0x98,0x00,0x28,0xA1,0xD0,0x0A,0x98,0x11,0xB0,0xC0,0xB2,0xF0,0xBD,0x00,0x00, + 0x44,0x00,0x00,0x20,0xFF,0xFF,0x00,0x00,0xF0,0xB5,0x8C,0x46,0x3D,0x49,0x00,0x28, + 0xCE,0x6B,0xCC,0x69,0x35,0x79,0x4B,0x6A,0x02,0xD1,0xF5,0x78,0x8C,0x69,0x0B,0x6A, + 0x05,0x2A,0x05,0xD0,0x01,0x2A,0x27,0xD0,0x03,0x2A,0x24,0xD1,0x00,0x20,0x66,0xE0, + 0x00,0x20,0x1E,0xE0,0xC2,0x07,0xD2,0x0F,0x62,0x45,0x16,0xD1,0x22,0x68,0x91,0x1C, + 0x56,0x1C,0x1F,0x3A,0x97,0x7F,0x8E,0x46,0x19,0x78,0x0F,0x43,0x97,0x77,0xD7,0x7F, + 0x19,0x78,0x8F,0x43,0xD7,0x77,0x31,0x78,0x1A,0x78,0x91,0x43,0x31,0x70,0x71,0x46, + 0x0A,0x78,0x19,0x78,0x8A,0x43,0x71,0x46,0x0A,0x70,0x24,0x1D,0x5B,0x1C,0x40,0x1C, + 0xC0,0xB2,0xA8,0x42,0xDE,0xD3,0xF0,0xBD,0x00,0x20,0x1E,0xE0,0xC2,0x07,0xD2,0x0F, + 0x62,0x45,0x16,0xD1,0x22,0x68,0x91,0x1C,0x56,0x1C,0x1F,0x3A,0x97,0x7F,0x8E,0x46, + 0x19,0x78,0x8F,0x43,0x97,0x77,0xD7,0x7F,0x19,0x78,0x8F,0x43,0xD7,0x77,0x31,0x78, + 0x1A,0x78,0x11,0x43,0x31,0x70,0x71,0x46,0x0A,0x78,0x19,0x78,0x8A,0x43,0x71,0x46, + 0x0A,0x70,0x24,0x1D,0x5B,0x1C,0x40,0x1C,0xC0,0xB2,0xA8,0x42,0xDE,0xD3,0xF0,0xBD, + 0xC2,0x07,0xD2,0x0F,0x62,0x45,0x16,0xD1,0x22,0x68,0x91,0x1C,0x56,0x1C,0x1F,0x3A, + 0x97,0x7F,0x8E,0x46,0x19,0x78,0x8F,0x43,0x97,0x77,0xD7,0x7F,0x19,0x78,0x8F,0x43, + 0xD7,0x77,0x31,0x78,0x1A,0x78,0x91,0x43,0x31,0x70,0x71,0x46,0x0A,0x78,0x19,0x78, + 0x0A,0x43,0x71,0x46,0x0A,0x70,0x24,0x1D,0x5B,0x1C,0x40,0x1C,0xC0,0xB2,0xA8,0x42, + 0xDE,0xD3,0xF0,0xBD,0xC4,0x00,0x00,0x20,0xF0,0xB5,0x36,0x4D,0x00,0x28,0xEE,0x6B, + 0xEB,0x69,0x34,0x79,0x6A,0x6A,0x02,0xD1,0xF4,0x78,0xAB,0x69,0x2A,0x6A,0x05,0x29, + 0x05,0xD0,0x01,0x29,0x22,0xD0,0x03,0x29,0x1F,0xD1,0x00,0x25,0x57,0xE0,0x00,0x25, + 0x19,0xE0,0x01,0xCB,0x81,0x1C,0x8C,0x46,0x41,0x1C,0x1F,0x38,0x86,0x7F,0x17,0x78, + 0x3E,0x43,0x86,0x77,0xC6,0x7F,0x17,0x78,0xBE,0x43,0xC6,0x77,0x08,0x78,0x16,0x78, + 0xB0,0x43,0x08,0x70,0x61,0x46,0x08,0x78,0x11,0x78,0x52,0x1C,0x88,0x43,0x61,0x46, + 0x08,0x70,0x6D,0x1C,0xED,0xB2,0xA5,0x42,0xE3,0xD3,0xF0,0xBD,0x00,0x25,0x19,0xE0, + 0x01,0xCB,0x81,0x1C,0x8C,0x46,0x41,0x1C,0x1F,0x38,0x86,0x7F,0x17,0x78,0xBE,0x43, + 0x86,0x77,0xC6,0x7F,0x17,0x78,0xBE,0x43,0xC6,0x77,0x08,0x78,0x16,0x78,0x30,0x43, + 0x08,0x70,0x61,0x46,0x08,0x78,0x11,0x78,0x52,0x1C,0x88,0x43,0x61,0x46,0x08,0x70, + 0x6D,0x1C,0xED,0xB2,0xA5,0x42,0xE3,0xD3,0xF0,0xBD,0x01,0xCB,0x81,0x1C,0x8C,0x46, + 0x41,0x1C,0x1F,0x38,0x86,0x7F,0x17,0x78,0xBE,0x43,0x86,0x77,0xC6,0x7F,0x17,0x78, + 0xBE,0x43,0xC6,0x77,0x08,0x78,0x16,0x78,0xB0,0x43,0x08,0x70,0x61,0x46,0x08,0x78, + 0x11,0x78,0x52,0x1C,0x08,0x43,0x61,0x46,0x08,0x70,0x6D,0x1C,0xED,0xB2,0xA5,0x42, + 0xE3,0xD3,0xF0,0xBD,0xC4,0x00,0x00,0x20,0xF8,0xB5,0x25,0x4A,0xD1,0x6B,0x16,0x46, + 0x00,0x91,0x80,0x3E,0xF7,0x6E,0x0D,0x79,0xBE,0x46,0x37,0x6F,0x74,0x6E,0xB3,0x6E, + 0x31,0x6E,0xBC,0x46,0x00,0x28,0x08,0xD1,0x00,0x98,0xB1,0x6F,0xC5,0x78,0x50,0x68, + 0x13,0x68,0x86,0x46,0x90,0x68,0xF4,0x6F,0x84,0x46,0x19,0x48,0x80,0x38,0x40,0x78, + 0x02,0x28,0x0A,0xD8,0x00,0x20,0x06,0xE0,0x42,0x00,0x8E,0x5A,0xA6,0x52,0x8E,0x5A, + 0x40,0x1C,0x9E,0x52,0xC0,0xB2,0xA8,0x42,0xF6,0xD3,0x00,0x22,0x0B,0xE0,0x50,0x00, + 0x0E,0x5E,0x77,0x00,0xF6,0x19,0x27,0x5E,0xF6,0x19,0xB6,0x10,0x1E,0x52,0x0E,0x5A, + 0x52,0x1C,0x26,0x52,0xD2,0xB2,0xAA,0x42,0xF1,0xD3,0x09,0x48,0x80,0x38,0x40,0x78, + 0x05,0x28,0x0C,0xD8,0x00,0x20,0x04,0x46,0x07,0xE0,0x41,0x00,0x5A,0x5A,0x76,0x46, + 0x72,0x52,0x61,0x46,0x0C,0x54,0x40,0x1C,0xC0,0xB2,0xA8,0x42,0xF5,0xD3,0xF8,0xBD, + 0xC4,0x00,0x00,0x20,0xF0,0xB5,0x6C,0x48,0x89,0xB0,0x01,0x88,0x08,0x91,0x41,0x88, + 0x07,0x91,0xC1,0x88,0x06,0x91,0xC1,0x89,0x05,0x91,0x01,0x89,0x04,0x91,0x40,0x89, + 0x03,0x90,0x66,0x48,0x01,0x7C,0x02,0x91,0x81,0x7C,0x01,0x91,0x40,0x7C,0x64,0x4C, + 0x00,0x90,0xE2,0x6B,0x0E,0x25,0x90,0x7B,0x00,0x28,0x7D,0xD0,0x10,0x46,0x20,0x30, + 0x81,0x7B,0xC3,0x7B,0xC6,0x78,0xC9,0x18,0x83,0x78,0x5E,0x4F,0x9B,0x19,0x9B,0x1C, + 0x26,0x46,0x9C,0x46,0x60,0x36,0x33,0x7A,0x76,0x7A,0x89,0x1C,0x76,0x00,0xF6,0x19, + 0x9E,0x5D,0x63,0x46,0xF3,0x18,0x4E,0x19,0xB3,0x42,0x02,0xD2,0x5B,0x00,0xB3,0x42, + 0x01,0xD3,0x59,0x1A,0xCD,0xB2,0x81,0x7A,0x50,0x4B,0x09,0x01,0x49,0x1C,0x19,0x74, + 0x10,0x21,0x59,0x74,0x86,0x7B,0x29,0x02,0x31,0x43,0x4B,0x4E,0x31,0x81,0x50,0x21, + 0x89,0x5A,0xF1,0x80,0x11,0x7C,0xD2,0x7B,0x80,0x27,0x12,0x01,0x3A,0x43,0x11,0x43, + 0x99,0x74,0x49,0x49,0x71,0x80,0x41,0x21,0x31,0x80,0xC0,0x7B,0xFF,0x30,0xFF,0x30, + 0x02,0x30,0x70,0x81,0x00,0xF0,0xCE,0xFA,0xE0,0x6B,0x01,0x7C,0xC0,0x7B,0x00,0x01, + 0x38,0x43,0x01,0x43,0x99,0x74,0x3E,0x48,0x3D,0x4F,0x80,0x38,0x40,0x78,0xA0,0x37, + 0x01,0x28,0x12,0xD8,0x02,0x20,0x00,0xF0,0x85,0xFA,0x01,0x20,0xFF,0xF7,0xBE,0xFD, + 0xE0,0x6B,0x20,0x30,0x40,0x7E,0x00,0x28,0x02,0xD0,0x00,0x20,0xFF,0xF7,0xB6,0xFD, + 0x3D,0x70,0xE0,0x6B,0x40,0x30,0x00,0x8A,0xF0,0x80,0xE0,0x6B,0x20,0x30,0x40,0x7E, + 0x00,0x28,0x1D,0xD0,0x01,0x21,0x08,0x46,0xFF,0xF7,0xBE,0xFE,0x38,0x78,0xFF,0x28, + 0x07,0xD0,0xE1,0x6B,0x00,0x02,0x20,0x31,0x89,0x7B,0x08,0x43,0x30,0x81,0xFF,0x20, + 0x38,0x70,0x00,0x21,0x08,0x46,0x00,0xF0,0xCF,0xF8,0x08,0x21,0x28,0x46,0x00,0xF0, + 0x4D,0xF8,0xE0,0x6B,0x20,0x30,0x00,0xE0,0x3B,0xE0,0x40,0x7E,0x00,0x28,0x02,0xD1, + 0x02,0x20,0x00,0xF0,0x4F,0xFA,0x00,0x21,0x01,0x20,0x00,0xF0,0xBD,0xF8,0x1B,0x4D, + 0xA8,0x7C,0x40,0x06,0x40,0x0E,0xA8,0x74,0x01,0x20,0x00,0xF0,0x43,0xFA,0xE0,0x6B, + 0x20,0x30,0x40,0x7E,0x00,0x28,0x07,0xD0,0x00,0x20,0xFF,0xF7,0xFD,0xFE,0x00,0x20, + 0xFF,0xF7,0xC8,0xFC,0x00,0xF0,0xC2,0xF9,0x01,0x20,0xFF,0xF7,0xF5,0xFE,0x01,0x20, + 0xFF,0xF7,0xC0,0xFC,0xFF,0xF7,0x18,0xFB,0x08,0x98,0x30,0x80,0x07,0x98,0x70,0x80, + 0x06,0x98,0xF0,0x80,0x05,0x98,0xF0,0x81,0x04,0x98,0x30,0x81,0x03,0x98,0x70,0x81, + 0x02,0x98,0x28,0x74,0x01,0x98,0xA8,0x74,0x00,0x98,0x68,0x74,0x02,0x20,0x00,0xF0, + 0xF9,0xFB,0x09,0xB0,0xF0,0xBD,0x00,0x00,0x00,0x10,0x00,0x40,0xE0,0x12,0x00,0x40, + 0xC4,0x00,0x00,0x20,0xDC,0x7B,0x00,0x00,0x83,0x10,0x00,0x00,0xF3,0xB5,0x05,0x46, + 0x3A,0xA0,0x8F,0xB0,0x00,0x68,0x3A,0x4A,0x0C,0x90,0x90,0x6F,0x02,0x90,0x10,0x46, + 0x80,0x30,0x0D,0x90,0x43,0x68,0xA0,0x30,0xFF,0x21,0x01,0x90,0x01,0x70,0x50,0x78, + 0x02,0x28,0x04,0xD8,0x08,0x22,0x18,0x46,0x02,0x99,0xFD,0xF7,0x07,0xF9,0x30,0x48, + 0xE0,0x30,0x00,0x79,0x00,0x28,0x56,0xD0,0x08,0x22,0x08,0xA8,0x02,0x99,0xFD,0xF7, + 0xFD,0xF8,0x00,0x26,0x68,0x46,0x00,0x95,0x86,0x81,0x34,0x46,0x37,0x46,0x00,0x21, + 0x08,0x46,0x00,0xF0,0x51,0xF8,0x32,0x22,0x0A,0x21,0x03,0xA8,0xFF,0xF7,0xC8,0xFB, + 0x0E,0x90,0x68,0x46,0x80,0x89,0xB0,0x42,0x0C,0xD9,0x0F,0x28,0x0A,0xD3,0x08,0x22, + 0x04,0xA8,0x02,0x99,0xFD,0xF7,0xE2,0xF8,0x68,0x46,0x86,0x89,0x1D,0x48,0x00,0x89, + 0x00,0x0A,0x00,0x90,0x0E,0x98,0x00,0x28,0x1C,0xD0,0x68,0x46,0x80,0x89,0x14,0x28, + 0x18,0xD2,0x04,0x2C,0x06,0xD2,0x0C,0xA8,0x00,0x5D,0x40,0x19,0x64,0x1C,0xC0,0xB2, + 0xE4,0xB2,0x03,0xE0,0x00,0x24,0x2D,0x1D,0xED,0xB2,0x28,0x46,0x0D,0x99,0x00,0x02, + 0xC9,0x6B,0x20,0x31,0x89,0x7B,0x08,0x43,0x0E,0x49,0x08,0x81,0x10,0x98,0x7F,0x1C, + 0x87,0x42,0xC4,0xD3,0x0F,0x2E,0x06,0xD3,0x08,0x22,0x04,0xA9,0x02,0x98,0xFD,0xF7, + 0xB5,0xF8,0x00,0x98,0x05,0xE0,0x08,0x22,0x08,0xA9,0x02,0x98,0xFD,0xF7,0xAE,0xF8, + 0xFF,0x20,0x01,0x99,0x08,0x70,0x11,0xB0,0xF0,0xBD,0x00,0x00,0xFF,0x01,0xFE,0x02, + 0x44,0x00,0x00,0x20,0x00,0x10,0x00,0x40,0xF3,0xB5,0x46,0x4D,0xBC,0x20,0x42,0x59, + 0x85,0xB0,0x11,0x46,0x28,0x46,0x05,0x9C,0x43,0x4B,0x20,0x31,0xC0,0x30,0x01,0x2C, + 0x22,0xD0,0xC6,0x68,0x00,0x7F,0xD4,0x78,0x02,0x02,0xAD,0x6F,0x02,0x43,0xDA,0x81, + 0x08,0x7E,0x01,0x28,0x5E,0xD0,0x03,0x22,0x00,0x21,0x05,0x98,0xFF,0xF7,0x44,0xFD, + 0x01,0x22,0x11,0x46,0x05,0x98,0xFF,0xF7,0x3F,0xFD,0x00,0x22,0x02,0x21,0x05,0x98, + 0x00,0xF0,0x6C,0xF8,0x00,0xF0,0xD8,0xF8,0xB0,0xB2,0x22,0x46,0x69,0x46,0xFC,0xF7, + 0x31,0xFA,0x00,0x20,0x6F,0x46,0x0F,0xE0,0x86,0x68,0x2E,0x48,0x14,0x79,0x20,0x30, + 0xC0,0x7B,0x2D,0x6E,0x02,0x02,0x02,0x43,0xDA,0x81,0xC8,0x7A,0xD9,0xE7,0x41,0x00, + 0x7A,0x5A,0x80,0x1C,0x6A,0x52,0xC0,0xB2,0xA0,0x42,0xF8,0xD3,0x00,0x22,0x03,0x21, + 0x05,0x98,0x00,0xF0,0x4B,0xF8,0x01,0x22,0x00,0x21,0x05,0x98,0xFF,0xF7,0x14,0xFD, + 0x03,0x22,0x01,0x21,0x05,0x98,0xFF,0xF7,0x0F,0xFD,0x01,0x22,0x02,0x21,0x05,0x98, + 0x00,0xF0,0x3C,0xF8,0x1B,0x48,0x00,0x21,0xE0,0x30,0x01,0x70,0x00,0xF0,0xA4,0xF8, + 0xB0,0xB2,0x22,0x46,0x69,0x46,0xFC,0xF7,0xFD,0xF9,0x01,0x20,0x04,0xE0,0x41,0x00, + 0x7A,0x5A,0x80,0x1C,0x6A,0x52,0xC0,0xB2,0xA0,0x42,0xF8,0xD3,0x01,0x22,0x03,0x21, + 0x05,0x98,0x00,0xF0,0x23,0xF8,0x01,0x22,0x11,0x46,0x05,0x98,0xFF,0xF7,0xEC,0xFC, + 0x07,0xB0,0xF0,0xBD,0x03,0x21,0x05,0x98,0xFF,0xF7,0x66,0xFD,0x02,0x21,0x05,0x98, + 0x00,0xF0,0x50,0xF8,0x00,0xF0,0x80,0xF8,0xB0,0xB2,0x22,0x46,0x29,0x46,0xFC,0xF7, + 0xD9,0xF9,0x03,0x21,0x05,0x98,0x00,0xF0,0x45,0xF8,0x01,0x21,0x05,0x98,0xFF,0xF7, + 0x53,0xFD,0xE5,0xE7,0x44,0x00,0x00,0x20,0x00,0x10,0x00,0x40,0xF0,0xB5,0x1C,0x4E, + 0x97,0x00,0xF3,0x6B,0x34,0x46,0x9C,0x46,0x1D,0x79,0x80,0x3C,0xB3,0x6A,0x64,0x6F, + 0xDB,0x19,0xA4,0x18,0x00,0x28,0x05,0xD1,0x60,0x46,0xC5,0x78,0xF0,0x6A,0xC3,0x19, + 0xF0,0x68,0x84,0x18,0x02,0x29,0x03,0xD0,0x03,0x29,0x14,0xD1,0x00,0x20,0x1B,0xE0, + 0x0F,0x21,0x09,0x02,0x80,0x26,0x0C,0xE0,0x20,0x78,0x1F,0x68,0x30,0x43,0xA4,0x1C, + 0x08,0x43,0x20,0x3F,0xF8,0x77,0x0F,0x20,0x1F,0x68,0x08,0x33,0x38,0x70,0x92,0x1C, + 0xD2,0xB2,0xAA,0x42,0xF0,0xD3,0xF0,0xBD,0x19,0x68,0x20,0x39,0xC8,0x77,0x19,0x68, + 0x08,0x33,0x08,0x70,0x92,0x1C,0xD2,0xB2,0xAA,0x42,0xF5,0xD3,0xF0,0xBD,0x00,0x00, + 0xC4,0x00,0x00,0x20,0x70,0xB5,0x17,0x4D,0xEE,0x6B,0x2B,0x46,0x80,0x3B,0x34,0x79, + 0xAA,0x6A,0x5B,0x6F,0x00,0x28,0x02,0xD1,0xF4,0x78,0xEB,0x68,0xEA,0x6A,0x02,0x29, + 0x04,0xD0,0x03,0x29,0x13,0xD1,0x00,0x20,0x01,0x46,0x18,0xE0,0x00,0x20,0x0F,0x21, + 0x0B,0xE0,0x1D,0x78,0x16,0x68,0xAD,0x06,0xAD,0x0E,0x5B,0x1C,0x80,0x35,0x20,0x3E, + 0xF5,0x77,0x20,0xCA,0x29,0x70,0x40,0x1C,0xC0,0xB2,0xA0,0x42,0xF1,0xD3,0x70,0xBD, + 0x13,0x68,0x20,0x3B,0xD9,0x77,0x08,0xCA,0x19,0x70,0x40,0x1C,0xC0,0xB2,0xA0,0x42, + 0xF6,0xD3,0x70,0xBD,0xC4,0x00,0x00,0x20,0x10,0xB5,0x09,0x4B,0x01,0x20,0x98,0x72, + 0x08,0x48,0x00,0x22,0x02,0x70,0x08,0x49,0x11,0x24,0x8C,0x80,0x43,0x24,0x0C,0x80, + 0x00,0xE0,0x30,0xBF,0x01,0x78,0x00,0x29,0xFB,0xD0,0x9A,0x72,0x10,0xBD,0x00,0x00, + 0x00,0x03,0x00,0x40,0x24,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0xFE,0xB5,0x2F,0x48, + 0x80,0x6F,0x86,0x46,0x2D,0x48,0x80,0x30,0xC0,0x6B,0x81,0x79,0x20,0x30,0x85,0x7E, + 0xC0,0x7E,0x00,0x90,0x8C,0x46,0x00,0x20,0x01,0x46,0x09,0xE0,0x4B,0x00,0x72,0x46, + 0xD2,0x5E,0xAA,0x42,0x02,0xDD,0x90,0x42,0x00,0xD2,0x10,0x46,0x49,0x1C,0x09,0xB2, + 0x61,0x45,0xF3,0xDB,0x21,0x4C,0x00,0x21,0xC0,0x34,0x38,0xE0,0x63,0x69,0x00,0x22, + 0x5A,0x54,0x4A,0x00,0x01,0x92,0x73,0x46,0x9B,0x5E,0x66,0x7E,0x00,0x9A,0x2F,0x46, + 0x00,0x2E,0x01,0xD0,0x14,0x37,0x0A,0x32,0xBB,0x42,0x26,0xDD,0x01,0x9F,0x1E,0x26, + 0x77,0x44,0x02,0x97,0x20,0x3F,0xBE,0x5F,0x01,0x96,0x02,0x9F,0x02,0x26,0xBE,0x5F, + 0x00,0x29,0x1F,0xD0,0x67,0x46,0x7F,0x1E,0xB9,0x42,0x00,0xD1,0x00,0x26,0x01,0x9F, + 0xBB,0x42,0x01,0xDB,0xB3,0x42,0x05,0xDA,0x90,0x42,0x0E,0xD9,0x17,0x46,0x0A,0x3F, + 0xBB,0x42,0x0A,0xDD,0x01,0x27,0x66,0x69,0x90,0x42,0x77,0x54,0x05,0xD9,0x0A,0x3A, + 0x93,0x42,0x02,0xDC,0x63,0x69,0x00,0x22,0x5A,0x54,0x49,0x1C,0x09,0xB2,0x61,0x45, + 0xC4,0xDB,0xFE,0xBD,0x00,0x27,0x01,0x97,0xE1,0xE7,0x00,0x00,0x44,0x00,0x00,0x20, + 0x3F,0x28,0x01,0xD9,0x01,0x20,0x70,0x47,0xC1,0x08,0x40,0x07,0x40,0x0F,0x09,0x01, + 0x01,0x43,0x88,0x20,0x01,0x43,0x02,0x48,0x81,0x74,0x00,0x20,0x70,0x47,0x00,0x00, + 0xE0,0x12,0x00,0x40,0x70,0xB5,0x06,0x46,0x07,0x48,0x00,0x24,0xC0,0x6B,0xC5,0x78, + 0x06,0xE0,0x22,0x46,0x31,0x46,0x01,0x20,0x00,0xF0,0xF0,0xFA,0x64,0x1C,0xE4,0xB2, + 0xAC,0x42,0xF6,0xD3,0x70,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20,0x06,0x21,0x09,0x4B, + 0x10,0xB5,0x48,0x43,0xC1,0x18,0x08,0x4A,0x4C,0x78,0x54,0x70,0x18,0x5C,0x10,0x70, + 0xC8,0x78,0x50,0x72,0x88,0x78,0x10,0x72,0x48,0x79,0x50,0x74,0x08,0x79,0x10,0x74, + 0x10,0xBD,0x00,0x00,0xAC,0x09,0x00,0x20,0x40,0x03,0x00,0x40,0x04,0x48,0xFF,0x21, + 0x01,0x70,0x00,0x22,0x42,0x70,0x01,0x72,0x42,0x72,0x01,0x74,0x42,0x74,0x70,0x47, + 0x40,0x03,0x00,0x40,0x0F,0x48,0x40,0x68,0x81,0x7A,0xCA,0x29,0x19,0xD1,0xC1,0x7A, + 0x0A,0x02,0x01,0x7B,0x0A,0x43,0x0C,0x49,0x0A,0x81,0x42,0x7B,0xFF,0x32,0xFF,0x32, + 0x02,0x32,0x4A,0x81,0xC1,0x7B,0x80,0x7B,0x80,0x22,0x00,0x01,0x01,0x43,0x05,0x48, + 0x40,0x38,0xC0,0x6B,0x20,0x30,0x80,0x79,0xC0,0x00,0x10,0x43,0x01,0x43,0x03,0x48, + 0x81,0x74,0x70,0x47,0x04,0x01,0x00,0x20,0x00,0x10,0x00,0x40,0xE0,0x12,0x00,0x40, + 0xF0,0xB5,0x8C,0x46,0x47,0x4B,0x46,0x49,0x1A,0x46,0x41,0x18,0xC0,0x32,0x34,0x29, + 0x03,0xD8,0x45,0x48,0xD9,0x60,0x10,0x60,0xF0,0xBD,0x0D,0x21,0x09,0x03,0x41,0x1A, + 0x36,0x29,0x01,0xD8,0xD9,0x60,0xF0,0xBD,0x3E,0x4C,0x01,0x21,0xC0,0x34,0x09,0x03, + 0x65,0x68,0x88,0x42,0x01,0xD2,0x15,0x60,0x5E,0xE0,0x3A,0x4C,0x01,0x27,0x46,0x1A, + 0x7F,0x03,0x20,0x34,0xBE,0x42,0x0F,0xD2,0x60,0x7D,0x04,0x28,0x0A,0xD0,0x60,0x7D, + 0x05,0x28,0x07,0xD0,0x60,0x7D,0x06,0x28,0x04,0xD0,0x60,0x7D,0x0A,0x28,0x01,0xD0, + 0x98,0x6C,0x1F,0xE0,0x58,0x6D,0x1D,0xE0,0x03,0x26,0x36,0x03,0x86,0x1B,0xBE,0x42, + 0x01,0xD2,0x58,0x6C,0x16,0xE0,0x05,0x26,0x36,0x03,0x86,0x1B,0xBE,0x42,0x01,0xD2, + 0x98,0x6D,0x0F,0xE0,0x07,0x26,0x36,0x03,0x86,0x1B,0x8E,0x42,0x36,0xD2,0x39,0x27, + 0x7F,0x02,0xB8,0x42,0x0D,0xD2,0x60,0x7D,0x05,0x28,0x06,0xD0,0x60,0x7D,0x01,0x28, + 0x05,0xD0,0xD8,0x6E,0x10,0x60,0xDE,0x60,0xF0,0xBD,0x18,0x6E,0xFA,0xE7,0x98,0x6E, + 0xF8,0xE7,0x1D,0x25,0xAD,0x02,0xA8,0x42,0x0F,0xD2,0x61,0x7D,0x05,0x29,0x08,0xD0, + 0x64,0x7D,0x18,0x49,0x80,0x31,0x01,0x2C,0x05,0xD0,0x49,0x68,0xC0,0x1B,0x11,0x60, + 0x12,0xE0,0x99,0x6F,0xFA,0xE7,0x09,0x68,0xF8,0xE7,0x3B,0x21,0x49,0x02,0x88,0x42, + 0x03,0xD2,0xD9,0x6B,0x40,0x1B,0x11,0x60,0x06,0xE0,0x0F,0x24,0xE4,0x02,0xA0,0x42, + 0xDA,0xD2,0x9C,0x6B,0x40,0x1A,0x14,0x60,0xD8,0x60,0xF0,0xBD,0x01,0x21,0xC9,0x03, + 0x41,0x1A,0xFF,0x29,0x02,0xD8,0x60,0x46,0x10,0x60,0x8B,0xE7,0x41,0x21,0x49,0x02, + 0x40,0x1A,0xFF,0x28,0x01,0xD8,0x0A,0x35,0x8D,0xE7,0x04,0x48,0xEC,0xE7,0x00,0x00, + 0x10,0x2E,0xFF,0xFF,0x44,0x00,0x00,0x20,0x50,0x7F,0x00,0x00,0xFF,0xFF,0x00,0x00, + 0x04,0x48,0xFF,0x21,0x41,0x75,0x01,0x75,0x00,0x22,0xC2,0x74,0x01,0x74,0x82,0x74, + 0x42,0x74,0x70,0x47,0x00,0x03,0x00,0x40,0x10,0xB5,0x0C,0x46,0x02,0x28,0x06,0xD0, + 0x00,0x28,0x01,0xD0,0x01,0x28,0x01,0xD1,0x00,0xF0,0x0A,0xF8,0x10,0xBD,0x01,0x20, + 0x00,0xF0,0x06,0xF8,0x00,0x21,0x20,0x46,0x00,0xF0,0x1E,0xF9,0x10,0xBD,0x00,0x00, + 0x70,0xB5,0x0D,0x4C,0x00,0x23,0x26,0x46,0xE5,0x6B,0x80,0x3E,0x36,0x7A,0x2A,0x79, + 0xA1,0x6A,0x01,0x2E,0x01,0xD1,0xEA,0x79,0x61,0x6B,0x00,0x28,0x02,0xD0,0x01,0x28, + 0x00,0xD1,0x0F,0x23,0x00,0x20,0x03,0xE0,0x10,0xC9,0x23,0x70,0x40,0x1C,0xC0,0xB2, + 0x90,0x42,0xF9,0xD3,0x70,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20,0x10,0xB5,0x0F,0x49, + 0xCB,0x6B,0x00,0x21,0xDA,0x79,0x15,0xE0,0x04,0x78,0x8C,0x42,0x10,0xD1,0x0B,0x48, + 0x83,0x24,0x60,0x38,0x02,0x7A,0x22,0x43,0x02,0x72,0x1A,0x7D,0x42,0x72,0x0A,0x01, + 0x17,0x32,0x82,0x72,0x02,0x46,0x20,0x3A,0x91,0x85,0x01,0x21,0x81,0x73,0x10,0xBD, + 0x49,0x1C,0xC9,0xB2,0x91,0x42,0xE7,0xD3,0x10,0xBD,0x00,0x00,0xC4,0x00,0x00,0x20, + 0xF8,0xB5,0x0D,0x4D,0x01,0x27,0x69,0x68,0x4F,0x71,0x0C,0x4E,0x31,0x7C,0x2C,0x46, + 0x40,0x3C,0xE2,0x6B,0x3B,0x46,0x52,0x7C,0x93,0x40,0x99,0x43,0x31,0x74,0x00,0xF0, + 0x43,0xFF,0x30,0x7C,0xE1,0x6B,0x49,0x7C,0x8F,0x40,0x38,0x43,0x30,0x74,0x69,0x68, + 0x00,0x20,0x48,0x71,0xF8,0xBD,0x00,0x00,0x04,0x01,0x00,0x20,0x00,0x03,0x00,0x40, + 0xF3,0xB5,0x83,0xB0,0x00,0x27,0x5D,0xE0,0x38,0x20,0x03,0x99,0x78,0x43,0x44,0x18, + 0xA0,0x78,0x00,0x28,0x54,0xD0,0x20,0x46,0xF9,0xF7,0x7E,0xFF,0x00,0x90,0xA0,0x79, + 0x00,0x28,0x0D,0xD0,0x63,0x8C,0x22,0x8C,0xE1,0x89,0xA0,0x89,0xFB,0xF7,0xFE,0xFE, + 0x27,0x49,0x09,0x68,0x89,0x79,0x49,0x08,0x88,0x42,0x01,0xD2,0x00,0x20,0xA0,0x71, + 0x60,0x79,0x01,0x28,0x02,0xD9,0xA0,0x79,0x00,0x28,0x05,0xD0,0x68,0x46,0x00,0x88, + 0x20,0x84,0x68,0x46,0x40,0x88,0x32,0xE0,0x00,0x25,0x2E,0x46,0x11,0xE0,0xB0,0x00, + 0x20,0x18,0x41,0x8A,0x00,0x8A,0x63,0x8C,0x22,0x8C,0xFB,0xF7,0xDF,0xFE,0x01,0x46, + 0x17,0x48,0x00,0x68,0x80,0x79,0x81,0x42,0x01,0xD2,0x6D,0x1C,0xED,0xB2,0x76,0x1C, + 0xF6,0xB2,0x60,0x79,0xB0,0x42,0xEA,0xD8,0xC6,0xB2,0xAE,0x42,0x01,0xD1,0x01,0x20, + 0xA0,0x71,0x68,0x46,0x01,0x88,0x70,0x1B,0x41,0x43,0x01,0x90,0x20,0x8C,0x68,0x43, + 0x08,0x18,0x31,0x46,0xF9,0xF7,0x24,0xFC,0x20,0x84,0x68,0x46,0x41,0x88,0x01,0x98, + 0x41,0x43,0x60,0x8C,0x68,0x43,0x08,0x18,0x31,0x46,0xF9,0xF7,0x19,0xFC,0x60,0x84, + 0x7F,0x1C,0xFF,0xB2,0x04,0x98,0x87,0x42,0x9E,0xD3,0x05,0xB0,0xF0,0xBD,0x00,0x00, + 0x38,0x00,0x00,0x20,0xF0,0xB5,0x27,0x4B,0x1E,0x46,0xDC,0x6B,0x80,0x3E,0x36,0x7A, + 0x25,0x79,0xDA,0x69,0x59,0x6A,0x01,0x2E,0x02,0xD1,0xE5,0x79,0x1A,0x6B,0x99,0x6B, + 0x00,0x28,0x03,0xD0,0x02,0x28,0x1F,0xD1,0x00,0x24,0x38,0xE0,0x00,0x24,0x19,0xE0, + 0x01,0xCA,0x83,0x1C,0x9C,0x46,0x43,0x1C,0x1F,0x38,0x86,0x7F,0x0F,0x78,0x3E,0x43, + 0x86,0x77,0xC6,0x7F,0x0F,0x78,0xBE,0x43,0xC6,0x77,0x18,0x78,0x0E,0x78,0xB0,0x43, + 0x18,0x70,0x63,0x46,0x18,0x78,0x0B,0x78,0x49,0x1C,0x98,0x43,0x63,0x46,0x18,0x70, + 0x64,0x1C,0xE4,0xB2,0xAC,0x42,0xE3,0xD3,0xF0,0xBD,0x01,0xCA,0x83,0x1C,0x9C,0x46, + 0x43,0x1C,0x1F,0x38,0x86,0x7F,0x0F,0x78,0xBE,0x43,0x86,0x77,0xC6,0x7F,0x0F,0x78, + 0xBE,0x43,0xC6,0x77,0x18,0x78,0x0E,0x78,0xB0,0x43,0x18,0x70,0x63,0x46,0x18,0x78, + 0x0B,0x78,0x49,0x1C,0x18,0x43,0x63,0x46,0x18,0x70,0x64,0x1C,0xE4,0xB2,0xAC,0x42, + 0xE3,0xD3,0xF0,0xBD,0xC4,0x00,0x00,0x20,0xFE,0xB5,0x8C,0x46,0x1D,0x49,0x42,0x00, + 0x09,0x68,0x6C,0x46,0x8A,0x5A,0x1B,0x49,0xC0,0x39,0xCE,0x6B,0x80,0x39,0x33,0x79, + 0x89,0x6D,0x58,0x43,0x0F,0x18,0x00,0x20,0x06,0xE0,0x61,0x46,0x00,0x29,0x10,0xD0, + 0x82,0x25,0x25,0x54,0x40,0x1C,0xC0,0xB2,0x98,0x42,0xF6,0xD3,0x11,0x49,0x12,0x48, + 0x80,0x39,0x0A,0x89,0xC2,0x80,0x0A,0x46,0xC0,0x3A,0x12,0x7A,0x01,0x2A,0x0A,0xD0, + 0x0C,0xE0,0x39,0x5C,0x8D,0x06,0xAD,0x0E,0xD1,0x07,0x80,0x35,0x49,0x0E,0x0D,0x43, + 0x25,0x54,0x52,0x08,0xE6,0xE7,0xF3,0x79,0x09,0x8A,0xC1,0x80,0x81,0x88,0x10,0x22, + 0x11,0x43,0x81,0x80,0x04,0x81,0x43,0x80,0x31,0x21,0x01,0x80,0x81,0x88,0xC9,0x06, + 0xFC,0xD5,0xFE,0xBD,0x84,0x01,0x00,0x20,0x00,0x11,0x00,0x40,0xFE,0xB5,0x06,0x46, + 0x18,0x48,0x0F,0x46,0xC0,0x6B,0x14,0x46,0x05,0x79,0x00,0x20,0x00,0x90,0x01,0x90, + 0x01,0x46,0x02,0x90,0x2A,0x46,0x68,0x46,0xFC,0xF7,0x98,0xFC,0xAC,0x42,0x00,0xD9, + 0x2C,0x46,0x80,0x21,0x00,0x22,0x60,0x1E,0x0F,0x43,0x6B,0x46,0x0E,0x43,0x06,0xE0, + 0x82,0x42,0x01,0xDA,0x9F,0x54,0x00,0xE0,0x9E,0x54,0x52,0x1C,0xD2,0xB2,0xA2,0x42, + 0xF6,0xD3,0x08,0x48,0x40,0x30,0x01,0x89,0x07,0x48,0xC1,0x80,0x81,0x88,0x10,0x22, + 0x11,0x43,0x81,0x80,0x03,0x81,0x45,0x80,0x31,0x21,0x01,0x80,0x81,0x88,0xC9,0x06, + 0xFC,0xD5,0xFE,0xBD,0xC4,0x00,0x00,0x20,0x00,0x11,0x00,0x40,0x41,0x01,0x0A,0x48, + 0x02,0x88,0x20,0x23,0x1A,0x40,0x88,0x32,0x02,0x80,0xC2,0x13,0x11,0x43,0x01,0x81, + 0x41,0x88,0x01,0x88,0x08,0x22,0x91,0x43,0x01,0x80,0xAA,0x21,0x81,0x80,0x01,0x88, + 0x19,0x43,0x01,0x80,0x70,0x47,0x00,0x00,0x00,0x02,0x00,0x40,0xF0,0xB5,0x1A,0x4B, + 0x9C,0x46,0xDB,0x6B,0xDC,0x7A,0x84,0x42,0x27,0xD9,0x9D,0x7C,0x38,0x23,0x04,0x46, + 0x5C,0x43,0x27,0x46,0x14,0x4B,0x22,0x37,0xBE,0x1E,0x5B,0x69,0x01,0x2D,0x1D,0xD0, + 0x9D,0x5B,0xDE,0x5B,0x1F,0x57,0x00,0x01,0x01,0x2F,0x1A,0xD0,0x02,0x2F,0x18,0xD0, + 0x00,0x27,0x1F,0x55,0x08,0x70,0x28,0x09,0x48,0x70,0x30,0x09,0x88,0x70,0x33,0x07, + 0x28,0x01,0x1B,0x0F,0x18,0x43,0xC8,0x70,0x60,0x46,0x40,0x69,0xE4,0x1C,0x00,0x5D, + 0x40,0x08,0x08,0x71,0x10,0x78,0x40,0x1D,0x10,0x70,0xF0,0xBD,0xDD,0x5B,0x9E,0x5B, + 0xE0,0xE7,0x80,0x1D,0xE6,0xE7,0x00,0x00,0xC4,0x00,0x00,0x20,0xF0,0xB5,0x23,0x4B, + 0x96,0x00,0xDC,0x69,0x5D,0x6A,0xA4,0x19,0xAD,0x18,0x01,0x28,0x05,0xD0,0x1F,0x46, + 0x80,0x3F,0x3F,0x7A,0x01,0x2F,0x04,0xD0,0x07,0xE0,0x9C,0x69,0x1B,0x6A,0xA4,0x19, + 0x02,0xE0,0x1C,0x6B,0x9B,0x6B,0xA4,0x19,0x9D,0x18,0x22,0x68,0x2B,0x78,0x54,0x1E, + 0x25,0x78,0x9D,0x43,0x25,0x70,0x15,0x78,0x9D,0x43,0x15,0x70,0x55,0x78,0x9D,0x43, + 0x55,0x70,0x95,0x78,0x9D,0x43,0x95,0x70,0x01,0x28,0x03,0xD1,0x00,0x29,0x0B,0xD0, + 0x04,0x29,0x0C,0xD0,0x01,0x29,0x11,0xD0,0x02,0x29,0x13,0xD0,0x03,0x29,0x02,0xD1, + 0x90,0x78,0x18,0x43,0x90,0x70,0xF0,0xBD,0x20,0x78,0x98,0x43,0x01,0xE0,0x20,0x78, + 0x18,0x43,0x20,0x70,0x10,0x78,0x18,0x43,0x10,0x70,0xF0,0xBD,0x20,0x78,0x18,0x43, + 0x20,0x70,0xF0,0xBD,0x50,0x78,0x18,0x43,0x50,0x70,0xF0,0xBD,0xC4,0x00,0x00,0x20, + 0xF8,0xB5,0x47,0x49,0x0A,0x46,0x0C,0x46,0xFF,0x32,0x41,0x32,0x20,0x34,0xC0,0x31, + 0x01,0x28,0x2E,0xD0,0x02,0x28,0x2E,0xD0,0x03,0x28,0x32,0xD0,0x01,0x25,0x04,0x28, + 0x35,0xD0,0x05,0x28,0x36,0xD0,0x3E,0x4E,0x00,0x23,0xF7,0x1D,0xF9,0x37,0xBC,0x46, + 0x20,0x37,0xE0,0x36,0xBE,0x46,0x06,0x28,0x2E,0xD0,0x02,0x27,0x07,0x28,0x32,0xD0, + 0x08,0x28,0x3C,0xD0,0x37,0x4E,0x09,0x28,0x3B,0xD0,0x0A,0x28,0x3F,0xD0,0x0B,0x28, + 0x3F,0xD0,0x0C,0x28,0x3F,0xD0,0x0D,0x28,0x3F,0xD0,0x0E,0x28,0x3F,0xD0,0x0F,0x28, + 0x3F,0xD0,0x02,0x46,0x10,0x3A,0x0B,0x2A,0x40,0xD8,0x06,0x22,0x62,0x75,0x20,0x74, + 0x4F,0xE0,0x07,0x23,0x1F,0xE0,0x2D,0x49,0x2B,0x48,0xC8,0x60,0xBF,0xF3,0x40,0x8F, + 0xFE,0xE7,0x01,0x20,0xFF,0xF7,0x22,0xFF,0xFA,0x20,0xA0,0x74,0xFE,0xE7,0xCD,0x77, + 0x65,0x74,0x3E,0xE0,0x4D,0x77,0x3C,0xE0,0x8D,0x77,0x4B,0x77,0x65,0x46,0x6B,0x62, + 0x7B,0x70,0xF3,0x70,0x07,0xE0,0x00,0x23,0x8B,0x77,0x4F,0x77,0x67,0x46,0x7B,0x62, + 0x77,0x46,0x7B,0x70,0xF5,0x70,0x63,0x75,0x0F,0x23,0x93,0x71,0x29,0xE0,0x67,0x75, + 0x27,0xE0,0x63,0x75,0x32,0x88,0x20,0x23,0x1A,0x43,0x32,0x80,0x21,0xE0,0x65,0x75, + 0x1F,0xE0,0x03,0x22,0x08,0xE0,0x04,0x22,0x06,0xE0,0x05,0x22,0x04,0xE0,0x08,0x22, + 0x02,0xE0,0x8B,0x77,0x4F,0x77,0x0A,0x22,0x62,0x75,0x12,0xE0,0x1C,0x28,0x02,0xD0, + 0x1D,0x28,0x0C,0xD0,0x0D,0xE0,0x0E,0x49,0x10,0x20,0x88,0x71,0x64,0x21,0x03,0x20, + 0xFB,0xF7,0xE8,0xFB,0xFF,0xF7,0x2C,0xFD,0xAA,0x20,0xB0,0x80,0xFD,0xE7,0xCB,0x77, + 0x63,0x74,0x62,0x7D,0x4B,0x68,0x9A,0x70,0x49,0x68,0xC8,0x70,0xF8,0xBD,0x00,0x00, + 0x44,0x00,0x00,0x20,0x00,0x02,0x00,0x40,0x04,0x00,0xFA,0x05,0x00,0xED,0x00,0xE0, + 0x00,0x20,0x00,0x40,0x10,0xB5,0x0E,0x48,0x82,0x78,0xFF,0x38,0xAA,0x23,0x0D,0x49, + 0x01,0x38,0x00,0x2A,0x4A,0x88,0x06,0xD0,0x80,0x24,0x22,0x43,0x4A,0x80,0x8B,0x80, + 0x00,0x21,0x81,0x74,0x10,0xBD,0x4A,0x80,0x82,0x7C,0xFF,0x2A,0x02,0xD2,0x82,0x7C, + 0x52,0x1C,0x82,0x74,0x80,0x7C,0x30,0x28,0xF4,0xD2,0x8B,0x80,0x10,0xBD,0x00,0x00, + 0x64,0x01,0x00,0x20,0x00,0x02,0x00,0x40,0xFF,0xB5,0x82,0xB0,0x1C,0x46,0x0A,0x22, + 0xFF,0x21,0x02,0x98,0xFC,0xF7,0xD2,0xFB,0x14,0x22,0x00,0x21,0x0B,0x98,0xFC,0xF7, + 0xCD,0xFB,0x00,0x21,0x13,0xE0,0x11,0x48,0x4D,0x00,0x60,0x53,0x00,0x20,0x09,0xE0, + 0x4A,0x43,0x12,0x18,0x5B,0x68,0x52,0x00,0x66,0x5F,0x9F,0x5A,0xBE,0x42,0x00,0xDA, + 0x67,0x53,0x40,0x1C,0x0A,0x4B,0x1A,0x78,0x90,0x42,0xF1,0xDB,0x49,0x1C,0x08,0x4A, + 0x10,0x78,0x81,0x42,0xE7,0xDB,0x0B,0x98,0x0C,0x99,0x02,0xAD,0x01,0x91,0x00,0x90, + 0x07,0xCD,0x23,0x46,0xF9,0xF7,0x60,0xFA,0x06,0xB0,0xF0,0xBD,0x01,0x80,0xFF,0xFF, + 0x3C,0x00,0x00,0x20,0x82,0x00,0x01,0x20,0x00,0x21,0x00,0x04,0x82,0x42,0x01,0xD3, + 0x40,0x10,0x00,0xE0,0x80,0x20,0x01,0x43,0x0B,0x46,0x4B,0x43,0x93,0x42,0x00,0xD9, + 0x41,0x40,0x40,0x08,0xF7,0xD1,0x49,0x1C,0x48,0x08,0x70,0x47,0x00,0xB5,0xFD,0xF7, + 0xF1,0xFC,0x03,0x48,0x2F,0x21,0x80,0x6A,0x00,0x68,0x01,0x70,0x00,0xBD,0x00,0x00, + 0xC4,0x00,0x00,0x20,0x70,0xB5,0x2A,0x48,0x04,0x21,0x01,0x81,0xAA,0x21,0x81,0x80, + 0x28,0x21,0x01,0x80,0x27,0x48,0xCA,0x26,0x06,0x70,0x46,0x70,0x26,0x49,0x70,0x20, + 0x08,0x60,0x24,0x48,0x00,0x25,0x20,0x38,0xC5,0x71,0x25,0x4C,0x23,0x48,0x14,0x22, + 0x29,0x46,0x60,0x60,0xFC,0xF7,0xAA,0xFA,0x60,0x68,0x06,0x70,0x61,0x68,0x01,0x20, + 0x48,0x70,0x60,0x68,0x85,0x70,0x60,0x68,0xC5,0x70,0x61,0x68,0x02,0x20,0x08,0x71, + 0xFE,0xF7,0x16,0xF8,0x61,0x68,0x88,0x71,0x61,0x68,0x00,0x0A,0xC8,0x71,0x60,0x68, + 0x05,0x72,0x60,0x68,0x85,0x72,0x17,0x48,0x61,0x68,0x00,0x78,0xC8,0x72,0x61,0x68, + 0x10,0x20,0x08,0x73,0x61,0x68,0x20,0x20,0x48,0x73,0x61,0x68,0x03,0x20,0x88,0x73, + 0x61,0x68,0xC8,0x73,0x60,0x68,0x05,0x74,0x0F,0x48,0x05,0x70,0xFC,0xF7,0x66,0xFC, + 0xFC,0xF7,0x34,0xFC,0x3C,0x20,0xFF,0xF7,0x09,0xFE,0xFC,0xF7,0x87,0xFB,0xFC,0xF7, + 0x3D,0xFB,0xFC,0xF7,0xEB,0xFB,0xFC,0xF7,0xD1,0xFB,0x00,0xF0,0xC1,0xFC,0x70,0xBD, + 0x00,0x02,0x00,0x40,0x20,0x03,0x00,0x40,0x00,0x01,0x00,0x40,0x00,0x0A,0x00,0x20, + 0x04,0x01,0x00,0x20,0xDC,0x7B,0x00,0x00,0x2E,0x00,0x00,0x20,0xF0,0xB5,0x30,0x49, + 0x89,0xB0,0xC9,0x6B,0x2E,0x4E,0x8A,0x79,0x07,0x92,0x09,0x79,0x06,0x91,0x2D,0x49, + 0x80,0x3E,0x00,0x28,0x07,0xD0,0x43,0x20,0x08,0x72,0xC8,0x21,0x78,0x20,0xFB,0xF7, + 0xE1,0xFA,0x75,0x6C,0x17,0xE0,0x08,0x7A,0xBF,0x22,0x10,0x40,0x08,0x72,0x08,0x7A, + 0x83,0x22,0x10,0x43,0x08,0x72,0x00,0x22,0x11,0x46,0x01,0x20,0x75,0x6D,0xFF,0xF7, + 0x1D,0xFE,0x00,0x24,0x01,0x22,0x80,0x21,0x01,0xA8,0xFE,0xF7,0x79,0xFB,0x64,0x1C, + 0xE4,0xB2,0x32,0x2C,0xF6,0xD3,0x00,0x27,0x37,0x72,0x02,0x20,0xFF,0xF7,0xF2,0xFC, + 0x00,0x21,0x02,0x20,0xFF,0xF7,0x10,0xFC,0x06,0x98,0x15,0x4E,0x00,0x24,0x47,0x00, + 0x60,0x3E,0x19,0xE0,0x22,0x46,0x00,0x21,0x01,0x20,0xFF,0xF7,0xFF,0xFD,0x20,0x20, + 0x00,0x90,0x23,0x46,0x29,0x46,0x01,0xA8,0x06,0x9A,0xFB,0xF7,0x53,0xFC,0x01,0x21, + 0x7D,0x19,0x22,0x46,0x08,0x46,0xFF,0xF7,0xF1,0xFD,0x0B,0x49,0xAA,0x20,0x88,0x80, + 0x00,0x20,0xB0,0x74,0x64,0x1C,0xE4,0xB2,0x07,0x98,0x84,0x42,0xE2,0xD3,0x00,0x21, + 0x08,0x46,0xFF,0xF7,0xE9,0xFB,0x00,0x20,0xFF,0xF7,0xC4,0xFC,0x09,0xB0,0xF0,0xBD, + 0xC4,0x00,0x00,0x20,0x00,0x03,0x00,0x40,0x00,0x02,0x00,0x40,0x70,0xB5,0x28,0x48, + 0x54,0x21,0x41,0x72,0x43,0x21,0x01,0x72,0x27,0x4C,0x26,0x48,0x60,0x80,0x27,0x48, + 0x21,0x21,0x01,0x74,0x10,0x25,0x45,0x74,0xF1,0x21,0x09,0x01,0x21,0x81,0x11,0x21, + 0x49,0x01,0x61,0x81,0xC3,0x21,0x81,0x74,0xE5,0x80,0x41,0x20,0x20,0x80,0x02,0x20, + 0xFF,0xF7,0xC0,0xFA,0x01,0x20,0xFE,0xF7,0xF9,0xFD,0x00,0x20,0xFE,0xF7,0xF6,0xFD, + 0xE5,0x80,0x00,0x21,0x01,0x20,0xFF,0xF7,0x27,0xF9,0x00,0x21,0x08,0x46,0xFF,0xF7, + 0x23,0xF9,0x01,0x20,0xFF,0xF7,0xAE,0xFA,0x15,0x4A,0x00,0x20,0x51,0x6D,0x13,0x6E, + 0x44,0x00,0x1C,0x5B,0x53,0x6F,0xAA,0x25,0x1B,0x5C,0x40,0x1C,0x6B,0x43,0xE3,0x18, + 0x0B,0x80,0x89,0x1C,0x09,0x28,0xF2,0xD3,0x51,0x6D,0x00,0x20,0x12,0x31,0x13,0x46, + 0x80,0x33,0x94,0x6F,0x45,0x00,0x65,0x5B,0xDC,0x68,0xAA,0x26,0x24,0x5C,0x40,0x1C, + 0x74,0x43,0x2C,0x19,0x0C,0x80,0x89,0x1C,0x08,0x28,0xF2,0xD3,0x70,0xBD,0x00,0x00, + 0x00,0x03,0x00,0x40,0x83,0x10,0x00,0x00,0x00,0x10,0x00,0x40,0xE0,0x12,0x00,0x40, + 0x44,0x00,0x00,0x20,0xF0,0xB5,0x01,0x46,0x20,0x48,0x85,0xB0,0x42,0x8A,0x01,0x92, + 0x02,0x8A,0x00,0x92,0x1E,0x4A,0x42,0x80,0x1E,0x4A,0x02,0x80,0x1E,0x4A,0x11,0x23, + 0x53,0x74,0x35,0x23,0x13,0x74,0x00,0x22,0xC2,0x81,0x1C,0x4E,0x14,0x46,0xF0,0x6B, + 0x05,0x79,0xC7,0x78,0x68,0x00,0x40,0x18,0x02,0x91,0x03,0x90,0x06,0xE0,0x22,0x46, + 0x01,0x21,0x00,0x20,0xFF,0xF7,0x5A,0xFD,0x64,0x1C,0xE4,0xB2,0xAC,0x42,0xF6,0xD3, + 0x00,0x24,0x06,0xE0,0x01,0x21,0x22,0x46,0x08,0x46,0xFF,0xF7,0x4F,0xFD,0x64,0x1C, + 0xE4,0xB2,0xBC,0x42,0xF6,0xD3,0x01,0x22,0xB3,0x6A,0x28,0x46,0x02,0x99,0xFE,0xF7, + 0x93,0xF9,0x00,0x22,0xF3,0x6A,0x38,0x46,0x03,0x99,0xFE,0xF7,0x8D,0xF9,0x03,0x49, + 0x01,0x98,0x48,0x82,0x00,0x98,0x08,0x82,0x05,0xB0,0xF0,0xBD,0x00,0x10,0x00,0x40, + 0x82,0x10,0x00,0x00,0x45,0x08,0x00,0x00,0xE0,0x12,0x00,0x40,0xC4,0x00,0x00,0x20, + 0xF0,0xB5,0x28,0x4C,0x00,0x20,0x87,0xB0,0x06,0x46,0x65,0x69,0x07,0xE0,0x38,0x21, + 0x41,0x43,0x6A,0x5C,0x03,0x2A,0x00,0xD1,0x6E,0x54,0x40,0x1C,0xC0,0xB2,0xE1,0x6B, + 0xC9,0x7A,0x81,0x42,0xF3,0xD8,0xE0,0x6B,0x69,0x46,0x02,0x79,0x8A,0x70,0xC2,0x78, + 0x4A,0x70,0x01,0x46,0x40,0x31,0x0A,0x46,0x0B,0x89,0x69,0x46,0x0B,0x82,0x52,0x89, + 0x4A,0x82,0x18,0x4F,0xC0,0x7A,0x08,0x70,0x80,0x3F,0x78,0x7C,0x14,0x22,0x80,0x1C, + 0xC8,0x70,0x0E,0x71,0x12,0x20,0x48,0x71,0x0A,0x20,0x88,0x71,0xCE,0x71,0x4A,0x72, + 0x08,0x72,0x3C,0x20,0x88,0x72,0xC8,0x72,0x0E,0x73,0x50,0x20,0xC8,0x81,0x0E,0x48, + 0x05,0x90,0xF9,0x79,0x6A,0x46,0x63,0x69,0x20,0x69,0xFA,0xF7,0xAD,0xFF,0x7E,0x72, + 0x00,0x20,0xE2,0x6B,0x09,0xE0,0x38,0x21,0x41,0x43,0x69,0x56,0x00,0x29,0x02,0xDD, + 0x79,0x7A,0x49,0x1C,0x79,0x72,0x40,0x1C,0xC0,0xB2,0xD1,0x7A,0x81,0x42,0xF2,0xD8, + 0x07,0xB0,0xF0,0xBD,0xC4,0x00,0x00,0x20,0x9F,0x40,0x00,0x00,0x07,0x49,0x00,0x22, + 0x0A,0x70,0x07,0x4A,0x11,0x23,0x93,0x80,0x43,0x23,0x13,0x80,0x02,0xE0,0x00,0x28, + 0x00,0xD1,0x30,0xBF,0x0A,0x78,0x00,0x2A,0xF9,0xD0,0x70,0x47,0x24,0x01,0x00,0x20, + 0x00,0x10,0x00,0x40,0xFC,0xB5,0x37,0x49,0x0B,0x46,0xDF,0x1D,0xC8,0x78,0xF9,0x37, + 0x7C,0x7F,0x20,0x33,0x14,0x28,0x02,0xD3,0xB8,0x7F,0x00,0x28,0x01,0xD0,0x00,0x2C, + 0x5D,0xD0,0x30,0x48,0x2F,0x49,0x80,0x30,0xC2,0x6B,0xD5,0x78,0x10,0x79,0x45,0x43, + 0x01,0x95,0x4D,0x6D,0x48,0x6C,0x89,0x6C,0x8C,0x46,0x00,0x21,0x00,0x91,0x29,0x49, + 0x1E,0x79,0x20,0x31,0x49,0x79,0x00,0x2E,0x08,0xD0,0x49,0x1C,0xC9,0xB2,0x59,0x71, + 0x64,0x29,0x07,0xD9,0x01,0x21,0x00,0x91,0x00,0x21,0x02,0xE0,0x00,0x29,0x01,0xD0, + 0x49,0x1E,0x59,0x71,0x00,0x2C,0x04,0xD0,0x39,0x7F,0x00,0x29,0x01,0xD1,0x01,0x21, + 0x00,0x91,0x20,0x32,0x11,0x7D,0x56,0x7D,0x8E,0x46,0x7F,0x29,0x01,0xD9,0x7F,0x21, + 0x8E,0x46,0x7F,0x2E,0x00,0xD9,0x7F,0x26,0x16,0x49,0x00,0x24,0x0A,0x6C,0x22,0xE0, + 0x00,0x99,0x00,0x29,0x03,0xD0,0x61,0x46,0x09,0x88,0x01,0x80,0x13,0xE0,0x19,0x79, + 0x00,0x29,0x10,0xD1,0x51,0x56,0x2F,0x88,0xC9,0x19,0x09,0xB2,0x71,0x45,0x02,0xDD, + 0x01,0x88,0x49,0x1E,0x04,0xE0,0x77,0x42,0xB9,0x42,0x03,0xDA,0x01,0x88,0x49,0x1C, + 0x01,0x80,0x00,0x21,0x11,0x70,0x61,0x46,0x89,0x1C,0x52,0x1C,0xAD,0x1C,0x80,0x1C, + 0x64,0x1C,0x8C,0x46,0xE4,0xB2,0x01,0x99,0x8C,0x42,0xD9,0xD3,0xFC,0xBD,0x00,0x20, + 0x58,0x71,0xFC,0xBD,0x44,0x00,0x00,0x20,0xFF,0xB5,0x46,0x4C,0x81,0xB0,0xA0,0x78, + 0x0D,0x46,0x40,0x1C,0x0C,0x9F,0x0A,0x9E,0x0B,0x99,0xA0,0x70,0x68,0x46,0x80,0x88, + 0x00,0x2E,0x00,0xD0,0x10,0x1A,0x6E,0x46,0x30,0x80,0xF0,0x88,0x00,0x29,0x00,0xD0, + 0x18,0x1A,0x31,0x46,0x70,0x80,0x00,0x2F,0x20,0xD0,0xD0,0x18,0x40,0x08,0x01,0x2F, + 0x04,0xD0,0x02,0x2F,0x0A,0xD0,0x03,0x2F,0x18,0xD1,0x0E,0xE0,0xD2,0x1A,0x73,0x88, + 0x52,0x10,0x31,0x88,0xD2,0x18,0x32,0x80,0x40,0x1A,0x0E,0xE0,0x48,0x88,0x18,0x1A, + 0x48,0x80,0x08,0x88,0x10,0x1A,0x08,0x80,0x08,0xE0,0x31,0x88,0x76,0x88,0x80,0x1B, + 0x6E,0x46,0x30,0x80,0x98,0x1A,0x40,0x10,0x40,0x18,0x70,0x80,0x29,0x4E,0x20,0x78, + 0x72,0x78,0xC3,0x07,0x91,0x00,0x88,0x19,0x80,0x36,0x00,0x2B,0x12,0xD0,0x00,0x21, + 0x21,0x70,0x52,0x1C,0x62,0x70,0x69,0x46,0x09,0x88,0x81,0x80,0x69,0x46,0x49,0x88, + 0xC1,0x80,0x69,0x46,0x48,0x88,0x70,0x80,0x30,0x80,0x08,0x88,0xF0,0x80,0xB0,0x80, + 0x05,0xB0,0xF0,0xBD,0x43,0x88,0x62,0x5A,0x68,0x46,0x41,0x88,0x00,0x88,0xFB,0xF7, + 0x85,0xF9,0xA8,0x42,0x24,0xD3,0x60,0x78,0x1E,0x28,0x21,0xD2,0x81,0x00,0x40,0x1C, + 0x60,0x70,0x68,0x46,0x09,0x19,0x00,0x88,0x88,0x80,0x68,0x46,0x40,0x88,0xC8,0x80, + 0x68,0x46,0x31,0x88,0x40,0x88,0x81,0x42,0x00,0xD3,0x01,0x46,0x31,0x80,0x71,0x88, + 0x81,0x42,0x00,0xD9,0x08,0x46,0x70,0x80,0x68,0x46,0xB1,0x88,0x00,0x88,0x81,0x42, + 0x00,0xD3,0x01,0x46,0xB1,0x80,0xF1,0x88,0x81,0x42,0x00,0xD9,0x08,0x46,0xF0,0x80, + 0x04,0x48,0x69,0x46,0x7C,0x30,0x09,0x88,0x01,0x80,0x69,0x46,0x49,0x88,0x41,0x80, + 0xC6,0xE7,0x00,0x00,0xC0,0x0C,0x00,0x20,0x81,0x78,0x49,0x1E,0x81,0x70,0x01,0x79, + 0x00,0x29,0x03,0xD0,0x01,0x89,0x81,0x81,0x41,0x89,0x02,0xE0,0x81,0x8C,0x81,0x81, + 0xC1,0x8C,0xC1,0x81,0x70,0x47,0x00,0x00,0xF3,0xB5,0x04,0x46,0x80,0x78,0x81,0xB0, + 0x05,0x28,0x01,0xD2,0x40,0x1C,0xA0,0x70,0x1E,0x4F,0xA0,0x78,0x39,0x68,0xC9,0x78, + 0x88,0x42,0x01,0xD9,0x01,0x20,0x00,0xE0,0x00,0x20,0x60,0x70,0x69,0x46,0x20,0x79, + 0x0E,0x89,0x4D,0x89,0x00,0x28,0x1B,0xD0,0x60,0x78,0x00,0x28,0x01,0xD1,0x26,0x81, + 0x65,0x81,0x61,0x89,0x20,0x89,0x2B,0x46,0x32,0x46,0xFB,0xF7,0x1F,0xF9,0x39,0x68, + 0x49,0x79,0x88,0x42,0x02,0xD9,0x00,0x20,0x20,0x71,0x09,0xE0,0x20,0x79,0x00,0x28, + 0x06,0xD0,0x20,0x89,0xA0,0x84,0x61,0x89,0xE1,0x84,0xA0,0x81,0xE1,0x81,0x01,0xE0, + 0xA6,0x81,0xE5,0x81,0x60,0x79,0x03,0x28,0x01,0xD2,0x40,0x1C,0x60,0x71,0x60,0x78, + 0x00,0x28,0x04,0xD0,0x20,0x78,0x00,0x28,0x02,0xD0,0x02,0x20,0x20,0x70,0xFE,0xBD, + 0x01,0x20,0xFB,0xE7,0x38,0x00,0x00,0x20,0xFF,0xB5,0x04,0x46,0x85,0xB0,0x00,0x20, + 0x0C,0xE0,0x38,0x21,0x41,0x43,0x09,0x19,0x89,0x78,0x00,0x29,0x01,0xD0,0x01,0x21, + 0x00,0xE0,0xFF,0x21,0x6A,0x46,0x11,0x54,0x40,0x1C,0xC0,0xB2,0x0F,0x99,0x88,0x42, + 0xEF,0xD3,0x00,0x26,0x28,0xE0,0x0E,0x98,0x80,0x5D,0xFF,0x28,0x29,0xD0,0x08,0x99, + 0x08,0x22,0x08,0x5C,0x03,0x90,0x06,0x98,0xF1,0x00,0x0F,0x18,0x03,0x98,0x38,0x21, + 0x48,0x43,0x05,0x19,0x28,0x46,0x24,0x30,0x39,0x46,0xF8,0xF7,0xBD,0xFD,0xA8,0x89, + 0xA8,0x83,0xE8,0x89,0xE8,0x83,0x38,0x88,0x69,0x46,0x08,0x82,0x78,0x88,0x48,0x82, + 0x28,0x46,0x04,0x99,0xFF,0xF7,0x80,0xFF,0x38,0x79,0xE8,0x70,0x03,0x98,0xFF,0x21, + 0x6A,0x46,0x11,0x54,0x76,0x1C,0xF6,0xB2,0x07,0x98,0x86,0x42,0xD3,0xD3,0x00,0x22, + 0x5B,0xE0,0x22,0x46,0x00,0x20,0x0F,0x99,0x07,0xE0,0x38,0x23,0x43,0x43,0x9B,0x18, + 0x9B,0x78,0x00,0x2B,0x03,0xD0,0x40,0x1C,0xC0,0xB2,0x88,0x42,0xF5,0xD3,0x88,0x42, + 0x00,0xD3,0xFF,0x20,0x03,0x90,0xFF,0x28,0xE4,0xD0,0x38,0x22,0x50,0x43,0x01,0x21, + 0x05,0x19,0x29,0x71,0x00,0x22,0xAA,0x71,0x06,0x99,0xF3,0x00,0x5F,0x18,0x39,0x88, + 0xA9,0x83,0x79,0x88,0xE9,0x83,0x39,0x88,0x29,0x81,0x79,0x88,0x69,0x81,0x22,0x54, + 0x28,0x46,0x39,0x46,0x24,0x30,0x08,0x22,0xF8,0xF7,0x76,0xFD,0x38,0x88,0x69,0x46, + 0x08,0x82,0x78,0x88,0x48,0x82,0x28,0x46,0x04,0x99,0xFF,0xF7,0x3D,0xFF,0x38,0x79, + 0xE8,0x70,0x03,0x9A,0xFF,0x20,0x69,0x46,0x88,0x54,0xBB,0xE7,0x68,0x46,0x80,0x5C, + 0xFF,0x28,0x18,0xD0,0x10,0x46,0x38,0x21,0x48,0x43,0x21,0x56,0x00,0x29,0x0F,0xDD, + 0x0C,0x4D,0x01,0x19,0x2D,0x68,0x8B,0x78,0x2D,0x79,0x05,0x26,0x75,0x1B,0xAB,0x42, + 0x06,0xDC,0x03,0x23,0x23,0x54,0x00,0x20,0x48,0x71,0x88,0x70,0x48,0x70,0x02,0xE0, + 0x00,0x19,0xFF,0xF7,0x09,0xFF,0x52,0x1C,0xD2,0xB2,0x0F,0x98,0x82,0x42,0xDD,0xD3, + 0x09,0xB0,0xF0,0xBD,0x38,0x00,0x00,0x20,0x0E,0xB5,0x0E,0x48,0xC0,0x6B,0xC0,0x79, + 0x00,0x28,0x0F,0xD0,0x00,0x20,0x69,0x46,0x08,0x72,0x02,0xA9,0x68,0x46,0xFD,0xF7, + 0x8D,0xFF,0x08,0x48,0x60,0x38,0x00,0x7A,0x00,0x06,0x68,0x46,0x03,0xD5,0x01,0x7A, + 0xFC,0xF7,0x52,0xFD,0x0E,0xBD,0x00,0x7A,0x00,0x28,0xFB,0xD0,0x68,0x46,0xFF,0xF7, + 0xDD,0xF8,0x0E,0xBD,0xC4,0x00,0x00,0x20,0x10,0xB5,0x00,0xF0,0x43,0xF8,0xFA,0xF7, + 0x05,0xFD,0xFB,0xF7,0xBD,0xF9,0xF9,0xF7,0xE1,0xFC,0xFB,0xF7,0x1B,0xF8,0x10,0xBD, + 0xF0,0xB5,0x01,0x26,0xB6,0x07,0x31,0x89,0x08,0x27,0xB9,0x43,0x31,0x81,0x15,0x4D, + 0x15,0x4C,0x29,0x46,0x20,0x31,0xA0,0x22,0x08,0xE0,0x2B,0x78,0xAB,0x2B,0x08,0xD0, + 0x0B,0x79,0xAB,0x2B,0x05,0xD0,0x30,0xBF,0x10,0x4B,0x9A,0x80,0xA3,0x7C,0x83,0x42, + 0xF3,0xD3,0x30,0x89,0x38,0x43,0x30,0x81,0x28,0x78,0xAB,0x28,0x0A,0xD0,0x08,0x79, + 0xAB,0x28,0x07,0xD0,0x0A,0x48,0x01,0x88,0x0A,0x29,0x02,0xD2,0x01,0x88,0x89,0x1C, + 0x01,0x80,0xF0,0xBD,0x0A,0x79,0x00,0x20,0xAB,0x2A,0x01,0xD0,0x28,0x70,0xF0,0xBD, + 0x08,0x71,0xF0,0xBD,0xEB,0x08,0x00,0x20,0x64,0x00,0x00,0x20,0x00,0x02,0x00,0x40, + 0x02,0x00,0x00,0x20,0x03,0x48,0x00,0xE0,0x00,0xBF,0x41,0x78,0x00,0x29,0xFB,0xD0, + 0x70,0x47,0x00,0x00,0x24,0x01,0x00,0x20,0x70,0xB5,0x06,0x46,0x0D,0x4C,0xAA,0x20, + 0xA0,0x80,0x0D,0x4D,0x00,0x20,0xA8,0x74,0x32,0x20,0xFF,0xF7,0xF7,0xF9,0x22,0x88, + 0x28,0x46,0xA0,0x30,0x40,0x68,0xA0,0x21,0x03,0xE0,0x43,0x79,0x00,0x2B,0x03,0xD0, + 0xA1,0x80,0xAB,0x7C,0xB3,0x42,0xF8,0xD3,0x22,0x80,0x05,0x20,0xFF,0xF7,0xE6,0xF9, + 0x70,0xBD,0x00,0x00,0x00,0x02,0x00,0x40,0x64,0x00,0x00,0x20,0xF0,0xB5,0x4F,0x48, + 0x3A,0x21,0xC0,0x6B,0x89,0xB0,0x0B,0x5C,0x41,0x7D,0x06,0x91,0x01,0x78,0x05,0x91, + 0x4A,0x49,0x4A,0x4C,0x80,0x31,0x04,0x91,0x49,0x88,0x40,0x34,0x0A,0x29,0x03,0xD9, + 0x00,0x20,0x20,0x76,0x09,0xB0,0xF0,0xBD,0xC1,0x78,0x07,0x91,0x05,0x79,0x43,0x48, + 0x80,0x38,0x01,0x6E,0x02,0x6A,0x8C,0x46,0x00,0x21,0x08,0x46,0x02,0x92,0x29,0xE0, + 0x46,0x00,0x67,0x46,0xF7,0x19,0x03,0x97,0x20,0x3F,0xB6,0x46,0xFE,0x8B,0x6F,0x46, + 0x3E,0x80,0x76,0x46,0x67,0x46,0xBE,0x5F,0x6F,0x46,0x7E,0x80,0x03,0x9F,0xB6,0x46, + 0x7F,0x88,0x6E,0x46,0xB7,0x80,0x00,0x28,0x2F,0xD0,0x6F,0x1E,0xB8,0x42,0x01,0xD1, + 0x00,0x27,0xB7,0x80,0xD7,0x07,0x0B,0xD0,0x00,0x27,0xF7,0x5F,0x9F,0x42,0x07,0xDA, + 0x9E,0x45,0x05,0xDA,0x6F,0x46,0x04,0x26,0xBE,0x5F,0x9E,0x42,0x00,0xDA,0x49,0x1C, + 0x52,0x08,0x40,0x1C,0xA8,0x42,0xD3,0xD3,0x28,0x48,0x40,0x30,0x00,0x7E,0x00,0x29, + 0x29,0xD0,0x06,0x9A,0x12,0xB2,0x90,0x42,0x03,0xDA,0x49,0x1C,0x49,0x08,0x40,0x18, + 0x20,0x76,0x20,0x7E,0x90,0x42,0x2A,0xDB,0x20,0x4A,0x80,0x3A,0x90,0x69,0x00,0x28, + 0x06,0xD0,0x02,0x99,0x01,0x42,0x03,0xD0,0x12,0xE0,0x00,0x27,0x37,0x80,0xD1,0xE7, + 0x56,0x6D,0x91,0x6C,0x50,0x6C,0x07,0x9A,0x6A,0x43,0x55,0x00,0x2A,0x46,0xFB,0xF7, + 0xCD,0xFD,0x2A,0x46,0x00,0x21,0x30,0x46,0xFB,0xF7,0xD8,0xFD,0x00,0x20,0x20,0x76, + 0xC8,0x20,0x60,0x76,0x0B,0xE0,0x61,0x7E,0x00,0x29,0x04,0xD0,0x02,0x9A,0x00,0x2A, + 0x01,0xD1,0x49,0x1E,0x61,0x76,0x00,0x28,0x01,0xD0,0x40,0x1E,0x20,0x76,0x04,0x98, + 0x40,0x7F,0x00,0x28,0x02,0xD0,0x00,0x20,0x60,0x76,0x83,0xE7,0x60,0x7E,0x32,0x28, + 0x80,0xD9,0x81,0x08,0x05,0x98,0x08,0x18,0x04,0x49,0xC0,0xB2,0x80,0x39,0x08,0x70, + 0x64,0x28,0xF2,0xD9,0x64,0x20,0x08,0x70,0x74,0xE7,0x00,0x00,0xC4,0x00,0x00,0x20, + 0x03,0x48,0x00,0x21,0x01,0x76,0x41,0x76,0x81,0x76,0xC1,0x76,0x70,0x47,0x00,0x00, + 0x04,0x01,0x00,0x20,0xF0,0xB5,0x57,0x4F,0xB3,0xB0,0x39,0x7C,0x56,0x48,0x00,0x90, + 0xC0,0x6B,0x42,0x7C,0x01,0x20,0x90,0x40,0x01,0x43,0x39,0x74,0xFE,0xF7,0xA6,0xFE, + 0x51,0x4C,0x00,0x26,0x60,0x3C,0xA6,0x74,0x32,0x20,0xFF,0xF7,0x1F,0xF9,0x00,0x20, + 0xFA,0xF7,0x50,0xFF,0x25,0x46,0xE6,0x75,0xA0,0x35,0x8C,0xE0,0x21,0x7C,0x00,0x20, + 0x10,0x39,0x0B,0x00,0xF8,0xF7,0x90,0xFD,0x0A,0x06,0x06,0x27,0x2C,0x31,0x4D,0x5D, + 0x68,0x75,0x79,0x7D,0x46,0x48,0x45,0x49,0x41,0x80,0x10,0x21,0xC1,0x80,0x11,0x21, + 0x49,0x01,0x41,0x81,0x41,0x49,0x72,0x39,0x01,0x81,0x42,0x48,0x93,0x21,0x81,0x74, + 0x11,0x21,0x41,0x74,0x13,0x21,0x01,0x74,0x54,0x20,0x78,0x72,0x20,0x7C,0x10,0x28, + 0x07,0xD0,0x00,0x20,0xFF,0xF7,0x02,0xFB,0x20,0x7C,0x69,0x68,0x48,0x72,0x26,0x74, + 0x59,0xE0,0x01,0x20,0xF6,0xE7,0x01,0xA8,0xFF,0xF7,0xBC,0xFB,0x12,0x20,0xF4,0xE7, + 0x01,0xA8,0xFC,0xF7,0xB9,0xFE,0x13,0x20,0xEF,0xE7,0x33,0x49,0x20,0x20,0x08,0x60, + 0xFD,0xF7,0xF8,0xF9,0x38,0x78,0x10,0x21,0x08,0x43,0x38,0x70,0x20,0x7C,0x14,0x28, + 0x00,0xD1,0x30,0xBF,0x69,0x68,0x14,0x20,0x48,0x72,0x2C,0x49,0xA0,0x20,0x08,0x80, + 0x29,0x49,0x20,0x20,0x80,0x39,0x08,0x60,0x38,0x78,0xEF,0x21,0x08,0x40,0x38,0x70, + 0x35,0xE0,0x69,0x68,0x15,0x20,0x48,0x72,0xFE,0xF7,0x0A,0xFF,0x38,0x78,0x10,0x21, + 0x08,0x43,0x38,0x70,0x80,0x20,0xF8,0x71,0xFD,0xF7,0xD4,0xF9,0xFA,0xF7,0xAE,0xFD, + 0xFC,0xE7,0x69,0x68,0x16,0x20,0x48,0x72,0x39,0x7C,0x00,0x98,0xC0,0x6B,0x42,0x7C, + 0x01,0x20,0x90,0x40,0x01,0x43,0x09,0xE0,0x69,0x68,0x17,0x20,0x48,0x72,0x39,0x7C, + 0x00,0x98,0xC0,0x6B,0x42,0x7C,0x01,0x20,0x90,0x40,0x81,0x43,0x39,0x74,0x26,0x74, + 0x0D,0xE0,0xFF,0xF7,0x13,0xFB,0x18,0x20,0xA7,0xE7,0x69,0x68,0x19,0x20,0x48,0x72, + 0x05,0xE0,0x00,0x28,0x03,0xD0,0x32,0x21,0x01,0xA8,0xFD,0xF7,0xA3,0xFB,0x0B,0x49, + 0xA0,0x20,0x88,0x80,0xA6,0x74,0x60,0x7D,0x06,0x28,0x00,0xD1,0x6E,0xE7,0x33,0xB0, + 0xF0,0xBD,0x00,0x00,0x00,0x03,0x00,0x40,0xC4,0x00,0x00,0x20,0x82,0x10,0x00,0x00, + 0x00,0x10,0x00,0x40,0xE0,0x12,0x00,0x40,0x80,0xE1,0x00,0xE0,0x00,0x02,0x00,0x40, + 0x10,0xB5,0x23,0x49,0x01,0x20,0x48,0x70,0x0C,0x46,0xC0,0x3C,0xE1,0x7C,0x01,0x43, + 0xE1,0x74,0x20,0x7D,0xFD,0x21,0x08,0x40,0x20,0x75,0x20,0x7D,0xFB,0x21,0x08,0x40, + 0x20,0x75,0x20,0x7D,0xF7,0x21,0x08,0x40,0x20,0x75,0x2D,0xE0,0xFD,0xF7,0xD2,0xFB, + 0x01,0x20,0xFA,0xF7,0x8F,0xFE,0xF9,0xF7,0xCB,0xFC,0xFC,0xF7,0x23,0xFC,0xFE,0xF7, + 0xB9,0xFA,0xFD,0xF7,0x67,0xFE,0xF9,0xF7,0xE9,0xFA,0xFF,0xF7,0x6F,0xFE,0xF9,0xF7, + 0xCD,0xFE,0xFC,0xF7,0x6D,0xFA,0xFF,0xF7,0xD5,0xFB,0xFA,0xF7,0x1B,0xFE,0xFA,0xF7, + 0x49,0xF8,0xFA,0xF7,0xC1,0xFD,0xFF,0xF7,0xCF,0xFD,0x0A,0x48,0xF9,0xF7,0x20,0xFE, + 0xFC,0xF7,0xBC,0xFF,0xFF,0xF7,0x5C,0xFB,0xFB,0xF7,0x00,0xF9,0xFF,0xF7,0x2A,0xFE, + 0xFD,0xF7,0x64,0xFB,0xFD,0xF7,0x56,0xF8,0x60,0x7D,0x06,0x28,0xCE,0xD1,0x10,0xBD, + 0x24,0x01,0x00,0x20,0xB5,0x26,0x00,0x00,0x3C,0x14,0x32,0x08,0x09,0x09,0x08,0x00, + 0x00,0x08,0x05,0x02,0x08,0x01,0x01,0x05,0x03,0x00,0x00,0x06,0x04,0x28,0x28,0x1E, + 0x32,0x00,0xD8,0xE2,0x00,0x00,0x01,0x02,0x03,0x02,0x10,0x20,0x03,0x03,0x00,0x14, + 0x0A,0x01,0x02,0x01,0xC8,0x03,0x10,0x20,0x5A,0x5A,0x00,0x00,0x78,0x78,0x00,0x00, + 0x01,0x01,0x19,0x41,0x00,0x00,0x9C,0xFF,0x20,0x0F,0x10,0x03,0x03,0x08,0x90,0x01, + 0x2C,0x01,0x2C,0x01,0x90,0x01,0x80,0x02,0x20,0x00,0xEC,0xFF,0x1A,0x00,0x1A,0x00, + 0x04,0x03,0x05,0x02,0x01,0x00,0x08,0x09,0x06,0x05,0x04,0x03,0x01,0x02,0x09,0x07, + 0x00,0x17,0x16,0x03,0x13,0x02,0x11,0x07,0x00,0x04,0x15,0x05,0x14,0x01,0x12,0x10, + 0x23,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x49,0x03,0x00,0x40, + 0x41,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x41,0x03,0x00,0x40, + 0x41,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x41,0x03,0x00,0x40,0x49,0x03,0x00,0x40, + 0x41,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x49,0x03,0x00,0x40,0x51,0x03,0x00,0x40, + 0x41,0x03,0x00,0x40,0x80,0x40,0x08,0x08,0x04,0x02,0x80,0x01,0x10,0x20,0x20,0x10, + 0x02,0x04,0x01,0x08,0x40,0x00,0x00,0x00,0x11,0x12,0x00,0x40,0x0D,0x12,0x00,0x40, + 0x15,0x12,0x00,0x40,0x09,0x12,0x00,0x40,0x05,0x12,0x00,0x40,0x01,0x12,0x00,0x40, + 0x21,0x12,0x00,0x40,0x25,0x12,0x00,0x40,0x19,0x12,0x00,0x40,0x15,0x12,0x00,0x40, + 0x11,0x12,0x00,0x40,0x0D,0x12,0x00,0x40,0x05,0x12,0x00,0x40,0x09,0x12,0x00,0x40, + 0x25,0x12,0x00,0x40,0x1D,0x12,0x00,0x40,0x01,0x12,0x00,0x40,0x0E,0x17,0x11,0x1B, + 0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0xD8,0x00,0x00,0x00,0x00,0x00, + 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x05,0x00,0x08,0x00,0x0A,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00, + 0x09,0x00,0x11,0x00,0x1A,0x00,0x23,0x00,0x26,0x00,0x00,0x00,0x01,0x00,0x03,0x00, + 0x0A,0x00,0x18,0x00,0x2E,0x00,0x49,0x00,0x60,0x00,0x69,0x00,0x00,0x00,0x02,0x00, + 0x09,0x00,0x18,0x00,0x37,0x00,0x69,0x00,0xA6,0x00,0xDA,0x00,0xEF,0x00,0x01,0x00, + 0x05,0x00,0x11,0x00,0x2E,0x00,0x69,0x00,0xC7,0x00,0x3A,0x01,0x9C,0x01,0xC3,0x01, + 0x02,0x00,0x08,0x00,0x1A,0x00,0x49,0x00,0xA6,0x00,0x3A,0x01,0xEE,0x01,0x89,0x02, + 0xC7,0x02,0x02,0x00,0x0A,0x00,0x23,0x00,0x60,0x00,0xDA,0x00,0x9C,0x01,0x89,0x02, + 0x55,0x03,0xA7,0x03,0x02,0x00,0x0B,0x00,0x26,0x00,0x69,0x00,0xEF,0x00,0xC3,0x01, + 0xC7,0x02,0xA7,0x03,0x00,0x04,0x00,0x08,0xFF,0x07,0xFE,0x07,0xFD,0x07,0xFB,0x07, + 0xF8,0x07,0xF4,0x07,0xF0,0x07,0xEC,0x07,0xE6,0x07,0xE0,0x07,0xDA,0x07,0xD3,0x07, + 0xCB,0x07,0xC3,0x07,0xBA,0x07,0xB0,0x07,0xA6,0x07,0x9B,0x07,0x90,0x07,0x84,0x07, + 0x77,0x07,0x6A,0x07,0x5D,0x07,0x4E,0x07,0x40,0x07,0x30,0x07,0x20,0x07,0x10,0x07, + 0xFF,0x06,0xED,0x06,0xDB,0x06,0xC8,0x06,0xB5,0x06,0xA1,0x06,0x8D,0x06,0x78,0x06, + 0x63,0x06,0x4D,0x06,0x37,0x06,0x20,0x06,0x09,0x06,0xF1,0x05,0xD9,0x05,0xC1,0x05, + 0xA8,0x05,0x8E,0x05,0x74,0x05,0x5A,0x05,0x3F,0x05,0x24,0x05,0x08,0x05,0xEC,0x04, + 0xD0,0x04,0xB3,0x04,0x96,0x04,0x79,0x04,0x5B,0x04,0x3D,0x04,0x1E,0x04,0x00,0x04, + 0xE0,0x03,0xC1,0x03,0xA1,0x03,0x81,0x03,0x61,0x03,0x40,0x03,0x20,0x03,0xFF,0x02, + 0xDD,0x02,0xBC,0x02,0x9A,0x02,0x78,0x02,0x56,0x02,0x34,0x02,0x12,0x02,0xEF,0x01, + 0xCC,0x01,0xA9,0x01,0x86,0x01,0x63,0x01,0x40,0x01,0x1D,0x01,0xF9,0x00,0xD6,0x00, + 0xB2,0x00,0x8E,0x00,0x6B,0x00,0x47,0x00,0x23,0x00,0x00,0x00,0xFF,0x01,0x01,0x01, + 0xFF,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF, + 0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01, + 0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0x01,0xFF,0x01,0xFF,0xFF,0x01,0x01, + 0x01,0xFF,0xFF,0x01,0x01,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0x01,0x01,0x01,0xFF, + 0xFF,0xFF,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01, + 0x01,0x01,0x01,0xFF,0xFF,0x00,0x01,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x81,0x01, + 0x01,0x01,0x01,0x81,0x01,0x01,0x01,0x01,0x81,0x01,0x01,0x01,0x01,0x81,0x82,0x00, + 0x00,0x82,0x00,0x00,0x02,0x82,0x01,0x81,0x01,0x01,0x81,0x01,0x01,0x81,0x01,0x01, + 0x81,0x01,0x01,0x81,0x01,0x81,0x81,0x01,0x01,0x01,0x81,0x81,0x01,0x01,0x02,0x00, + 0x02,0x00,0x02,0x00,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x02,0x00,0x02,0x81,0x81, + 0x81,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x82,0x02,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x08,0x00,0x09,0x00,0x2C,0x01,0x2C,0x01,0x20,0x4E,0xCA,0xCA, + 0xAA,0x55,0xAA,0x55,0x11,0x27,0x17,0x92,0x01,0x00,0x00,0x01,0x96,0xBB,0x96,0x66, + 0xFF,0xFF,0xFF,0xFF,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0xDC,0xCA,0x8B,0xB3, +}; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst226se.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst226se.c new file mode 100644 index 000000000000..76283558171b --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst226se.c @@ -0,0 +1,558 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst226se.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst226se_fw.h" + + +#define BOOT_I2C_ADDR (0x5A) +#define MAIN_I2C_ADDR (0x5A) + +#define RW_REG_LEN (2) + +#define CST226SE_BIN_SIZE (7*1024+512) + +static struct hyn_ts_data *hyn_226data = NULL; +static const u8 gest_map_tbl[33] = {0xff,4,1,3,2,5,12,6,7,7,9,11,10,13,12,7,7,6,10,6,5,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,14}; + +static int cst226se_updata_judge(u8 *p_fw, u16 len); +static u32 cst226se_read_checksum(void); +static int cst226se_updata_tpinfo(void); +static int cst226se_enter_boot(void); +static int cst226se_set_workmode(enum work_mode mode,u8 enable); +static void cst226se_rst(void); + +static int cst226se_init(struct hyn_ts_data* ts_data) +{ + int ret = 0; + u8 buf[4]; + HYN_ENTER(); + hyn_226data = ts_data; + ret = cst226se_enter_boot(); + if(ret){ + HYN_ERROR("cst226se_enter_boot failed"); + return -1; + } + hyn_226data->fw_updata_addr = (u8*)fw_bin; + hyn_226data->fw_updata_len = CST226SE_BIN_SIZE; + hyn_226data->hw_info.ic_fw_checksum = cst226se_read_checksum(); + hyn_wr_reg(hyn_226data,0xA006EE,3,buf,0); //exit boot + cst226se_rst(); + mdelay(50); + hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR); + hyn_226data->need_updata_fw = cst226se_updata_judge((u8*)fw_bin,CST226SE_BIN_SIZE); + if(hyn_226data->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + return 0; +} + +static int cst226se_report(void) +{ + u8 buf[80]={0}; + u8 finger_num = 0,key_flg = 0,tmp_dat; + int len = 0; + int ret = 0,retry = 2; + switch(hyn_226data->work_mode){ + case NOMAL_MODE: + retry = 2; + while(retry--){ + ret = hyn_wr_reg(hyn_226data,0xD000,2,buf,7); + finger_num = buf[5] & 0x7F; + if(ret || buf[6] != 0xAB || buf[0] == 0xAB || finger_num > MAX_POINTS_REPORT){ + ret = -2; + continue; + } + key_flg = (buf[5]&0x80) ? 1:0; + len = 0; + if(finger_num > 1){ + len += (finger_num-1)*5; + } + if(key_flg && finger_num){ + len += 3; + } + if(len > 0){ + ret = hyn_wr_reg(hyn_226data,0xD007,2,&buf[5],len); + } + ret |= hyn_wr_reg(hyn_226data,0xD000AB,3,buf,0); + if(ret){ + ret = -3; + continue; + } + ret = 0; + break; + } + if(ret){ + hyn_wr_reg(hyn_226data,0xD000AB,3,buf,0); + HYN_ERROR("read frame failed"); + break; + } + if(key_flg){ //key + if(hyn_226data->rp_buf.report_need == REPORT_NONE){ + hyn_226data->rp_buf.report_need |= REPORT_KEY; + } + len = finger_num ? (len+5):3; + hyn_226data->rp_buf.key_id = (buf[len-2]>>4)-1; + hyn_226data->rp_buf.key_state = (buf[len-3]&0x0F)==0x03 ? 1:0; + HYN_INFO("key_id:%x state:%x",hyn_226data->rp_buf.key_id ,hyn_226data->rp_buf.key_state); + } + if(finger_num){ + u16 index = 0,i = 0; + u8 touch_down = 0; + if(hyn_226data->rp_buf.report_need == REPORT_NONE){ + hyn_226data->rp_buf.report_need |= REPORT_POS; + } + hyn_226data->rp_buf.rep_num = finger_num; + for(i = 0; i < finger_num; i++){ + index = i*5; + hyn_226data->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F; + hyn_226data->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0; + hyn_226data->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F); + hyn_226data->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F); + hyn_226data->rp_buf.pos_info[i].pres_z = buf[index + 4]; + if(hyn_226data->rp_buf.pos_info[i].event) touch_down++; + // HYN_INFO("report_id = %d, xy = %d,%d",hyn_226data->rp_buf.pos_info[i].pos_id,hyn_226data->rp_buf.pos_info[i].pos_x,hyn_226data->rp_buf.pos_info[i].pos_y); + } + if(0== touch_down){ + hyn_226data->rp_buf.rep_num = 0; + } + } + break; + case GESTURE_MODE: + ret = hyn_wr_reg(hyn_226data,0xD04C,2,&tmp_dat,1); + if((tmp_dat&0x7F) <= 32){ + tmp_dat = tmp_dat&0x7F; + hyn_226data->gesture_id = gest_map_tbl[tmp_dat]; + hyn_226data->rp_buf.report_need |= REPORT_GES; + } + break; + default: + break; + } + return ret; +} + + +static int cst226se_prox_handle(u8 cmd) +{ + int ret = 0; + HYN_ENTER(); + switch(cmd){ + case 1: //enable + hyn_226data->prox_is_enable = 1; + hyn_226data->prox_state = 0; + ret = hyn_wr_reg(hyn_226data,0xD004B01,3,NULL,0); + break; + case 0: //disable + hyn_226data->prox_is_enable = 0; + hyn_226data->prox_state = 0; + ret = hyn_wr_reg(hyn_226data,0xD004B00,3,NULL,0); + break; + case 2: //read + ret = hyn_wr_reg(hyn_226data,0xD004B,2,&hyn_226data->prox_state,1); + break; + } + return ret; +} + +static int cst226se_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0; + HYN_ENTER(); + hyn_226data->work_mode = mode; + if(mode != NOMAL_MODE) + hyn_esdcheck_switch(hyn_226data,DISABLE); + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_226data,ENABLE); + hyn_esdcheck_switch(hyn_226data,enable); + hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0); //soft rst + hyn_wr_reg(hyn_226data,0xD109,2,NULL,0); + break; + case GESTURE_MODE: + hyn_wr_reg(hyn_226data,0xD04C80,3,NULL,0); + break; + case LP_MODE: + break; + case DIFF_MODE: + hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0); + hyn_wr_reg(hyn_226data,0xD10D,2,NULL,0); + break; + case RAWDATA_MODE: + hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0); + hyn_wr_reg(hyn_226data,0xD10A,2,NULL,0); + break; + case FAC_TEST_MODE: + hyn_wr_reg(hyn_226data,0xD10B,2,NULL,0); + hyn_wr_reg(hyn_226data,0xD119,2,NULL,0); + msleep(50); //wait switch to fac mode + break; + case DEEPSLEEP: + hyn_irq_set(hyn_226data,DISABLE); + hyn_wr_reg(hyn_226data,0xD105,2,NULL,0); + break; + case ENTER_BOOT_MODE: + ret |= cst226se_enter_boot(); + break; + default : + hyn_esdcheck_switch(hyn_226data,ENABLE); + hyn_226data->work_mode = NOMAL_MODE; + break; + } + return ret; +} + + +static int cst226se_supend(void) +{ + HYN_ENTER(); + cst226se_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst226se_resum(void) +{ + HYN_ENTER(); + cst226se_rst(); + msleep(50); + cst226se_set_workmode(NOMAL_MODE,0); + return 0; +} + +static void cst226se_rst(void) +{ + if(hyn_226data->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR); + } + gpiod_direction_output(hyn_226data->plat_data.reset_gpio,0); + msleep(10); + gpiod_direction_output(hyn_226data->plat_data.reset_gpio,1); +} + +static int cst226se_enter_boot(void) +{ + int retry = 5,ret = 0; + u8 buf[4] = {0}; + hyn_set_i2c_addr(hyn_226data,BOOT_I2C_ADDR); + while(++retry<17){ + cst226se_rst(); + mdelay(retry); + ret = hyn_wr_reg(hyn_226data,0xA001AA,3,buf,0); + if(ret != 0){ + continue; + } + ret = hyn_wr_reg(hyn_226data,0xA003,2,buf,1); + if(ret == 0 && buf[0] == 0x55){ + return 0; + } + } + return -1; +} + +static int cst226se_updata_tpinfo(void) +{ + u8 buf[28]; + struct tp_info *ic = &hyn_226data->hw_info; + int ret = 0,retry = 5; + while(--retry){ + ret = hyn_wr_reg(hyn_226data,0xD101,2,buf,0); + mdelay(1); + ret |= hyn_wr_reg(hyn_226data,0xD1F4,2,buf,28); + cst226se_set_workmode(NOMAL_MODE,0); + if(ret ==0 && U8TO16(buf[19],buf[18])==0x00a8){ + break; + } + msleep(1); + } + + if(ret || retry==0){ + HYN_ERROR("cst226se_updata_tpinfo failed"); + return -1; + } + ic->fw_sensor_txnum = buf[0]; + ic->fw_sensor_rxnum = buf[2]; + ic->fw_key_num = buf[3]; + ic->fw_res_y = (buf[7]<<8)|buf[6]; + ic->fw_res_x = (buf[5]<<8)|buf[4]; + ic->fw_project_id = (buf[17]<<8)|buf[16]; + ic->fw_chip_type = U8TO16(buf[19],buf[18]); + ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20]; + + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return 0; +} + +static u32 cst226se_read_checksum(void) +{ + int ret; + u8 buf[4],retry = 5; + hyn_226data->boot_is_pass = 0; + while(retry--){ + ret = hyn_wr_reg(hyn_226data,0xA000,2,buf,1); + if(ret){ + mdelay(2); + continue; + } + if(buf[0]!=0) break; + mdelay(2); + } + mdelay(1); + if(buf[0] == 0x01){ + memset(buf,0,sizeof(buf)); + hyn_wr_reg(hyn_226data,0xA008,2,buf,4); + hyn_226data->boot_is_pass = 1; + } + return U8TO32(buf[3],buf[2],buf[1],buf[0]); +} + +static int cst226se_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + int ret = 0; + u8 *p_data = p_fw +7680-12; + struct tp_info *ic = &hyn_226data->hw_info; + + f_fw_project_id = U8TO16(p_data[1],p_data[0]); + f_ictype = U8TO16(p_data[3],p_data[2]); + + f_fw_ver = U8TO32(p_data[7],p_data[6],p_data[5],p_data[4]); + f_checksum = U8TO32(p_data[11],p_data[10],p_data[9],p_data[8]); + + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + + ret = cst226se_updata_tpinfo(); + if(ret)HYN_ERROR("get tpinfo failed"); + + //check h file + f_check_all = hyn_sum32(0x55,(u32*)p_fw,(len-4)/4); + if(f_check_all != f_checksum){ + HYN_INFO(".h file checksum erro:%04x len:%d",f_check_all,len); + return 0; //not updata + } + if(hyn_226data->boot_is_pass ==0 //emty chip + ||(hyn_226data->boot_is_pass && ret) //erro code + || ( ret == 0 && f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file + ){ + return 1; //need updata + } + return 0; +} + +static int cst226se_updata_fw(u8 *bin_addr, u16 len) +{ + #define CHECKSUM_OFFECT (7680-4) + int i,ret, retry = 4; + u8 i2c_buf[512+2]; + u16 eep_addr = 0, total_kbyte = len/512; + u32 fw_checksum = 0; + HYN_ENTER(); + if(0 == hyn_226data->fw_file_name[0]){ + fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT]); + } + else{ + ret = hyn_copy_for_updata(hyn_226data,i2c_buf,CHECKSUM_OFFECT,4); + if(ret) goto UPDATA_END; + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + } + + hyn_irq_set(hyn_226data,DISABLE); + while(--retry){ + ret = cst226se_enter_boot(); + if(ret){ + HYN_ERROR("cst226se_enter_boot fail"); + continue; + } + //start trans fw + for (i=0; i>8; + ret = hyn_write_data(hyn_226data, i2c_buf,RW_REG_LEN, 4); + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + if(0 == hyn_226data->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr + eep_addr, 512); + } + else{ + ret |= hyn_copy_for_updata(hyn_226data,i2c_buf + 2,eep_addr,512); + } + ret |= hyn_write_data(hyn_226data, i2c_buf,RW_REG_LEN, 514); + ret |= hyn_wr_reg(hyn_226data, 0xA004EE, 3,i2c_buf,0); + msleep(300); //wait finsh + { + uint8_t time_out = 10; + while(--time_out){ + ret = hyn_wr_reg(hyn_226data,0xA005,2,i2c_buf,1); + if (ret == 0 && i2c_buf[0] == 0x55){ + break; + } + msleep(100); + } + if(time_out==0){ + ret = -1; + break; + } + } + } + if(ret) continue; + ret = hyn_wr_reg(hyn_226data,0xA00100,3,i2c_buf,0); + ret |= hyn_wr_reg(hyn_226data,0xA00300,3,i2c_buf,0); + if(ret) continue; + hyn_226data->hw_info.ic_fw_checksum = cst226se_read_checksum(); + if(fw_checksum == hyn_226data->hw_info.ic_fw_checksum){ + break; + } + } + UPDATA_END: + hyn_set_i2c_addr(hyn_226data,MAIN_I2C_ADDR); + cst226se_rst(); + if(fw_checksum == hyn_226data->hw_info.ic_fw_checksum){ + mdelay(50); + cst226se_updata_tpinfo(); + ret = 0; + HYN_INFO("updata_fw success"); + } + else{ + ret = -1; + HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_226data->hw_info.ic_fw_checksum); + } + hyn_irq_set(hyn_226data,ENABLE); + return ret; +} + +static u32 cst226se_check_esd(void) +{ + int ret = 0; + u8 buf[6]; + ret = hyn_wr_reg(hyn_226data,0xD040,2,buf,6); + if(ret ==0){ + u16 checksum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5; + if(checksum != ( (buf[4]<<8)+ buf[5])){ + ret = -1; + } + } + return ret ? 0:(buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24)); +} + +static int cst226se_get_dbg_data(u8 *buf, u16 len) +{ + int ret = -1,timeout=0; + u16 read_len = (hyn_226data->hw_info.fw_sensor_txnum * hyn_226data->hw_info.fw_sensor_rxnum)*2; + u16 total_len = read_len + (hyn_226data->hw_info.fw_sensor_txnum + hyn_226data->hw_info.fw_sensor_rxnum*2 + hyn_226data->hw_info.fw_key_num)*2; + HYN_ENTER(); + if(total_len > len){ + HYN_ERROR("buf too small"); + return -1; + } + timeout = 500; + while(--timeout){ //wait rise edge + if(gpiod_get_value(hyn_226data->plat_data.irq_gpio)==1) break; + mdelay(1); + } + switch(hyn_226data->work_mode){ + case DIFF_MODE: + case RAWDATA_MODE: + { + u8 temp[10*16],*ptr; + u16 index = 0,*ptr_dif = (u16*)buf; + ret = hyn_wr_reg(hyn_226data,0x8001,2,buf,total_len); //mt //rx scap //tx scap + memcpy(temp,buf,read_len/2); + ptr = &buf[read_len/2]; + for(index = 0;index < read_len/2; index++){ + *ptr_dif = ((*ptr<<8)+temp[index]); + ptr++; + ptr_dif++; + } + } + break; + default: + HYN_ERROR("work_mode:%d",hyn_226data->work_mode); + break; + } + return ret==0 ? total_len:-1; +} + + +#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini" +#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log" +#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST) +static int cst226se_get_test_result(u8 *buf, u16 len) +{ + int ret = 0,timeout; + struct tp_info *ic = &hyn_226data->hw_info; + u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2; + + HYN_ENTER(); + if((mt_len*3 + scap_len) > len || mt_len==0){ + HYN_ERROR("buf too small"); + return FAC_GET_DATA_FAIL; + } + msleep(1); + timeout = 500; + while(--timeout){ //wait rise edge + if(gpiod_get_value(hyn_226data->plat_data.irq_gpio)==1) break; + msleep(10); + } + if(hyn_wr_reg(hyn_226data,0x1215,2,buf,mt_len*2+scap_len+4)){ //open high + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read open high failed"); + goto selftest_end; + } + { + u16 *test_high = (u16*)&buf[0],*test_low = (u16*)&buf[mt_len],*test_short = (u16*)&buf[mt_len*2],w_tmp = 0,i=0; + for(i=0; i< mt_len/2; i++){ + w_tmp = *test_low; + *test_low = *test_high; + *test_high = w_tmp; + test_high++; + test_low++; + } + + for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){ + *test_short = U16REV((u16)*test_short); + test_short++; + } + } + + //read data finlish start test + ret = hyn_factory_multitest(hyn_226data ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM); + +selftest_end: + if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_226data,(s16*)buf,ret,FACTEST_ITEM)){ + HYN_INFO("fac_test log save success"); + } + cst226se_resum(); + return ret; +} + + +const struct hyn_ts_fuc hyn_cst226se_fuc = { + .tp_rest = cst226se_rst, + .tp_report = cst226se_report, + .tp_supend = cst226se_supend, + .tp_resum = cst226se_resum, + .tp_chip_init = cst226se_init, + .tp_updata_fw = cst226se_updata_fw, + .tp_set_workmode = cst226se_set_workmode, + .tp_check_esd = cst226se_check_esd, + .tp_prox_handle = cst226se_prox_handle, + .tp_get_dbg_data = cst226se_get_dbg_data, + .tp_get_test_result = cst226se_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3240.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3240.c new file mode 100644 index 000000000000..9c4b4ce30920 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3240.c @@ -0,0 +1,627 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst3240.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst3240_fw.h" + +#define BOOT_I2C_ADDR (0x5A) +#define MAIN_I2C_ADDR (0x5A) +#define RW_REG_LEN (2) +#define MODULE_ID_ADDR (0x3FFC) +#define CST3240_BIN_SIZE (31*512 + 480) + +static struct hyn_ts_data *hyn_3240data = NULL; +static const u8 gest_map_tbl[] = { + IDX_NULL, IDX_RIGHT, IDX_UP, IDX_LEFT, + IDX_DOWN, IDX_O, IDX_C, IDX_e, + IDX_M, IDX_M, IDX_W, IDX_V, + IDX_S, IDX_Z, IDX_C, IDX_M, + IDX_M, IDX_e, IDX_S, IDX_e, + IDX_O, IDX_NULL, IDX_NULL, IDX_NULL, + IDX_NULL, IDX_NULL, IDX_NULL, IDX_NULL, + IDX_NULL, IDX_NULL, IDX_NULL, IDX_NULL, + IDX_POWER +}; + +static int cst3240_updata_judge(u8 *p_fw, u16 len); +static u32 cst3240_read_checksum(void); +static int cst3240_updata_tpinfo(void); +static int cst3240_enter_boot(void); +static u32 cst3240_fread_word(u32 addr); +static void cst3240_rst(void); + + +static const struct hyn_chip_series hyn_3240_fw[] = { + {0x3240,0x00,"cst32401",(u8*)fw_bin},//default fw + {0x3240,0x01,"cst32402",(u8*)fw_bin}, + {0x3240,0x02,"cst32403",(u8*)fw_bin}, + {0,0,"",NULL} +}; + +static int cst3240_init(struct hyn_ts_data* ts_data) +{ + int ret = 0,i; + u32 module_id; + HYN_ENTER(); + hyn_3240data = ts_data; + ret = cst3240_enter_boot(); + if(ret){ + HYN_INFO("cst3240_enter_boot failed"); + return -1; + } + module_id = cst3240_fread_word(MODULE_ID_ADDR); + hyn_3240data->fw_updata_addr = hyn_3240_fw[0].fw_bin; + + for(i = 0; ;i++){ + if( hyn_3240_fw[i].moudle_id == module_id){ + hyn_3240data->fw_updata_addr = hyn_3240_fw[i].fw_bin; + HYN_INFO("chip %s match fw success",hyn_3240_fw[i].chip_name); + break; + } + if(hyn_3240_fw[i].part_no == 0 && hyn_3240_fw[i].moudle_id == 0){ + HYN_INFO("unknown chip or unknown moudle_id use hyn_3240_fw[0]"); + break; + } + } + hyn_3240data->hw_info.fw_module_id = module_id; + hyn_3240data->fw_updata_len = CST3240_BIN_SIZE; + hyn_3240data->hw_info.ic_fw_checksum = cst3240_read_checksum(); + HYN_INFO("curt read checksum:0x%x module_id:0x%x",hyn_3240data->hw_info.ic_fw_checksum,module_id); + //hyn_wr_reg(hyn_3240data,0xA006EE,3,buf,0); //exit boot + hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR); + cst3240_rst(); + msleep(50); + hyn_3240data->need_updata_fw = cst3240_updata_judge((u8*)fw_bin,CST3240_BIN_SIZE); + return 0; +} + +static int cst3240_report(void) +{ + u8 buf[80]={0}; + u8 finger_num = 0,key_flg = 0,tmp_dat; + int len = 0; + int ret = 0,retry = 2; + switch(hyn_3240data->work_mode){ + case NOMAL_MODE: + retry = 2; + while(retry--){ + ret = hyn_wr_reg(hyn_3240data,0xD000,2,buf,7); + finger_num = buf[5] & 0x7F; + if(ret || buf[6] != 0xAB || buf[0] == 0xAB || finger_num > MAX_POINTS_REPORT){ + ret = -2; + continue; + } + key_flg = (buf[5]&0x80) ? 1:0; + len = 0; + if(finger_num > 1){ + len += (finger_num-1)*5; + } + if(key_flg && finger_num){ + len += 3; + } + if(len > 0){ + ret = hyn_wr_reg(hyn_3240data,0xD007,2,&buf[5],len); + } + if(ret && retry) continue; + ret |= hyn_wr_reg(hyn_3240data,0xD000AB,3,buf,0); + if(ret == 0){ + break; + } + } + if(ret){ + HYN_ERROR("read frame failed"); + break; + } + if(key_flg){ //key + if(hyn_3240data->rp_buf.report_need == REPORT_NONE){ + hyn_3240data->rp_buf.report_need |= REPORT_KEY; + } + len = finger_num ? (len+5):3; + hyn_3240data->rp_buf.key_id = (buf[len-2]>>4)-1; + hyn_3240data->rp_buf.key_state = (buf[len-3]&0x0F)==0x03 ? 1:0; + HYN_INFO("key_id:%x state:%x",hyn_3240data->rp_buf.key_id ,hyn_3240data->rp_buf.key_state); + } + if(finger_num){ + u16 index = 0,i = 0; + u8 touch_down = 0; + if(hyn_3240data->rp_buf.report_need == REPORT_NONE){ + hyn_3240data->rp_buf.report_need |= REPORT_POS; + } + hyn_3240data->rp_buf.rep_num = finger_num; + for(i = 0; i < finger_num; i++){ + index = i*5; + hyn_3240data->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F; + hyn_3240data->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0; + hyn_3240data->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F); + hyn_3240data->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F); + hyn_3240data->rp_buf.pos_info[i].pres_z = buf[index + 4]; + if(hyn_3240data->rp_buf.pos_info[i].event) touch_down++; + // HYN_INFO("report_id = %d, xy = %d,%d",hyn_3240data->rp_buf.pos_info[i].pos_id,hyn_3240data->rp_buf.pos_info[i].pos_x,hyn_3240data->rp_buf.pos_info[i].pos_y); + } + if(0== touch_down){ + hyn_3240data->rp_buf.rep_num = 0; + } + } + break; + case GESTURE_MODE: + ret = hyn_wr_reg(hyn_3240data,0xD04C,2,&tmp_dat,1); + if((tmp_dat&0x7F) <= 32){ + tmp_dat = tmp_dat&0x7F; + hyn_3240data->gesture_id = gest_map_tbl[tmp_dat]; + hyn_3240data->rp_buf.report_need |= REPORT_GES; + } + break; + default: + break; + } + return ret; +} + +static int cst3240_prox_handle(u8 cmd) +{ + /*int ret = 0; + switch(cmd){ + case 1: //enable + hyn_3240data->prox_is_enable = 1; + hyn_3240data->prox_state = 0; + ret = hyn_wr_reg(hyn_3240data,0xD004B01,3,NULL,0); + break; + case 0: //disable + hyn_3240data->prox_is_enable = 0; + hyn_3240data->prox_state = 0; + ret = hyn_wr_reg(hyn_3240data,0xD004B00,3,NULL,0); + break; + case 2: //read + ret = hyn_wr_reg(hyn_3240data,0xD004B,2,&hyn_3240data->prox_state,1); + break; + } + return ret;*/ + return 0; +} + +static int cst3240_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0; + HYN_ENTER(); + hyn_3240data->work_mode = mode; + if(mode != NOMAL_MODE) + hyn_esdcheck_switch(hyn_3240data,DISABLE); + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_3240data,ENABLE); + hyn_esdcheck_switch(hyn_3240data,enable); + ret |= hyn_wr_reg(hyn_3240data,0xD109,2,0,0); + break; + case GESTURE_MODE: + ret |= hyn_wr_reg(hyn_3240data,0xD104,2,0,0); + break; + case LP_MODE: + break; + case DIFF_MODE: + ret |= hyn_wr_reg(hyn_3240data,0xD10D,2,0,0); + ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0); + break; + case RAWDATA_MODE: + ret |= hyn_wr_reg(hyn_3240data,0xD10A,2,0,0); + ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0); + break; + case FAC_TEST_MODE: + cst3240_rst(); + msleep(50); + ret |= hyn_wr_reg(hyn_3240data,0xD119,2,0,0); + msleep(50); //wait switch to fac mode + break; + case DEEPSLEEP: + hyn_irq_set(hyn_3240data,DISABLE); + ret |= hyn_wr_reg(hyn_3240data,0xD105,2,0,0); + break; + case ENTER_BOOT_MODE: + ret |= cst3240_enter_boot(); + break; + default : + ret = -2; + break; + } + return ret; +} + + +static int cst3240_supend(void) +{ + HYN_ENTER(); + cst3240_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst3240_resum(void) +{ + HYN_ENTER(); + cst3240_rst(); + msleep(50); + cst3240_set_workmode(NOMAL_MODE,1); + return 0; +} + +static void cst3240_rst(void) +{ + if(hyn_3240data->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR); + } + gpiod_direction_output(hyn_3240data->plat_data.reset_gpio,0); + msleep(8); + gpiod_direction_output(hyn_3240data->plat_data.reset_gpio,1); +} + +static int cst3240_enter_boot(void) +{ + int retry = 0,ret = 0,times; + u8 buf[4]; + hyn_set_i2c_addr(hyn_3240data,BOOT_I2C_ADDR); + while(++retry<20){ + cst3240_rst(); + mdelay(5+retry); + ret = hyn_wr_reg(hyn_3240data,0xA001AA,3,0,0); + if(ret) continue; + times = 5; + while(--times){ + ret = hyn_wr_reg(hyn_3240data,0xA002,2,buf,2); + if(ret ==0 && buf[0] == 0x55 && buf[1] == 0xA8) break; + mdelay(1); + } + if(times == 0) continue; + ret = hyn_wr_reg(hyn_3240data,0xA00100,3,0,0); + if(ret) continue; + break; + } + return retry < 20 ? 0:-1; +} + +static int cst3240_updata_tpinfo(void) +{ + u8 buf[28]; + struct tp_info *ic = &hyn_3240data->hw_info; + int ret = 0,retry = 5; + HYN_ENTER(); + while(--retry){ + ret = hyn_wr_reg(hyn_3240data,0xD101,2,0,0); //get module info mode + ret |= hyn_wr_reg(hyn_3240data,0xD204,2,buf,8); + ret |= hyn_wr_reg(hyn_3240data,0xD1F4,2,&buf[8],8); + ret |= cst3240_set_workmode(NOMAL_MODE,ENABLE); + if(ret==0 && U8TO16(buf[3],buf[2])==0x3240)break; + mdelay(1); + } + + if(ret || retry==0){ + HYN_ERROR("cst3240_updata_tpinfo failed"); + return -1; + } + + ic->fw_project_id = U8TO16(buf[1],buf[0]); + ic->fw_chip_type = U8TO16(buf[3],buf[2]); + ic->fw_ver = U8TO32(buf[7],buf[6],buf[5],buf[4]); + + ic->fw_sensor_txnum = buf[8]; + ic->fw_sensor_rxnum = buf[10]; + ic->fw_key_num = buf[11]; + ic->fw_res_y = U8TO16(buf[15],buf[14]); + ic->fw_res_x = U8TO16(buf[13],buf[12]); + + HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y); + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return 0; +} + +static u32 cst3240_fread_word(u32 addr) +{ + int ret; + u8 rec_buf[4],retry; + u32 read_word = 0; + retry = 3; + while(retry--){ + ret = hyn_write_data(hyn_3240data,(u8[]){0xA0,0x18,0x00,0x00,0x00,0x00},2,6); + ret |= hyn_wr_reg(hyn_3240data,0xA01000,3,0,0); //set section + ret |= hyn_wr_reg(hyn_3240data,U8TO32(0xA0,0x0c,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr + ret |= hyn_wr_reg(hyn_3240data,0xA004E4,3,NULL,0); //trig read + if(ret ==0) break; + } + if(ret) return 0; + + retry = 10; + while(retry--){ + mdelay(2); + ret = hyn_wr_reg(hyn_3240data,0xA018,2,rec_buf,4); + if(ret==0){ + read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]); + ret = hyn_wr_reg(hyn_3240data,0xA018,2,rec_buf,4); + if(ret == 0 && read_word==U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0])){ + break; + } + } + } + return read_word; +} + +static u32 cst3240_read_checksum(void) +{ + int ret; + u32 check_sum = 0; + u8 buf[4],retry = 6; + hyn_3240data->boot_is_pass = 0; + while(--retry){ + ret = hyn_wr_reg(hyn_3240data,0xA000,2,buf,1); + if(ret ==0 && buf[0] == 0x01) break; + mdelay(2); + } + if(retry){ + retry = 3; + while(retry){ + ret = hyn_wr_reg(hyn_3240data,0xA008,2,buf,4); + if(ret==0){ + check_sum = U8TO32(buf[3],buf[2],buf[1],buf[0]); + hyn_3240data->boot_is_pass = 1; + break; + } + mdelay(1); + } + } + return check_sum; +} + +static int cst3240_updata_judge(u8 *p_fw, u16 len) +{ + int ret; + u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + u8 *p_data; // = p_fw + len- 16; + struct tp_info *ic = &hyn_3240data->hw_info; + HYN_ENTER(); + p_data = &p_fw[CST3240_BIN_SIZE-16+4]; + f_fw_project_id = U8TO16(p_data[1],p_data[0]); + f_ictype = U8TO16(p_data[3],p_data[2]); + f_fw_ver = U8TO32(p_data[7],p_data[6],p_data[5],p_data[4]); + f_checksum = U8TO32(p_data[11],p_data[10],p_data[9],p_data[8]); + + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + ret = cst3240_updata_tpinfo(); //boot checksum pass, communicate failed not updata + if(ret) HYN_ERROR("get tpinfo failed"); + + f_check_all = hyn_sum32(0x55,(u32*)p_fw,len/4-1); + if(f_check_all != f_checksum){ + HYN_INFO(".h file checksum erro:%04x",f_check_all); + return 0; //no need updata + } + + if(hyn_3240data->boot_is_pass ==0 //checksum failed + || ( ret == 0 && f_ictype == ic->fw_chip_type && f_fw_project_id == ic->fw_project_id + && f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file + ){ + return 1; //need updata + } + return 0; +} + +static int cst3240_updata_fw(u8 *bin_addr, u16 len) +{ + int i,ret=-1, times = 0,retry; + u8 i2c_buf[512+2]; + u16 eep_addr = 0; + u32 fw_checksum = 0; + HYN_ENTER(); + if(len < CST3240_BIN_SIZE){ + HYN_ERROR("len = %d",len); + goto UPDATA_END; + } + // if(len > CST3240_BIN_SIZE) len = CST3240_BIN_SIZE; + + if(0 == hyn_3240data->fw_file_name[0]){ + fw_checksum = *(u32*)(bin_addr+CST3240_BIN_SIZE-4); + } + else{ + ret = hyn_copy_for_updata(hyn_3240data,i2c_buf,CST3240_BIN_SIZE-4,4); + if(ret) goto UPDATA_END; + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + } + hyn_irq_set(hyn_3240data,DISABLE); + hyn_esdcheck_switch(hyn_3240data,DISABLE); + retry = 4; + while(--retry){ + hyn_3240data->fw_updata_process = 0; + ret = cst3240_enter_boot(); + if(ret) continue; + ret = hyn_wr_reg(hyn_3240data,0xA01000,3,0,0); + if(ret) continue; + //start trans fw + for (i=0; i<32;i++) { + if(31 == i){ + hyn_wr_reg(hyn_3240data, 0xA01002, 3,0,0); + hyn_wr_reg(hyn_3240data, 0xA00CE001, 4,0,0); + } + eep_addr = i << 9; //i * 512 + ret = hyn_wr_reg(hyn_3240data,0xA0140000+U16REV(eep_addr),4,0,0); + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + if(0 == hyn_3240data->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr + eep_addr, 512); + }else{ + ret |= hyn_copy_for_updata(hyn_3240data,i2c_buf + 2,eep_addr,512); + } + ret |= hyn_write_data(hyn_3240data, i2c_buf,RW_REG_LEN, i<31 ? 514:482); + if(ret){ //com erro + continue; + } + ret = hyn_wr_reg(hyn_3240data, 0xA004EE, 3,0,0); + if(ret) ret = hyn_wr_reg(hyn_3240data, 0xA004EE, 3,0,0); + mdelay((4-retry)*100); //wait finsh + times = 100; + while(--times){ + ret = hyn_wr_reg(hyn_3240data,0xA005,2,i2c_buf,1); + if(ret==0 && i2c_buf[0] == 0x55) break; + ret = -1; + mdelay(10); + } + if(ret) break; + hyn_3240data->fw_updata_process = i*100/32; + } + // HYN_INFO("ret = %d",ret); + if(ret) continue; + + ret = hyn_wr_reg(hyn_3240data,0xA00300,3,i2c_buf,0); + if(ret) continue; + hyn_3240data->hw_info.ic_fw_checksum = cst3240_read_checksum(); + HYN_INFO("retry:%d fw_checksum:%x ic_checksum:%x\r\n",4-retry,fw_checksum,hyn_3240data->hw_info.ic_fw_checksum); + if(fw_checksum != hyn_3240data->hw_info.ic_fw_checksum){ + ret = -2; + continue; + } + break; + } +UPDATA_END: + hyn_set_i2c_addr(hyn_3240data,MAIN_I2C_ADDR); + cst3240_rst(); + if(ret == 0){ + msleep(50); + cst3240_updata_tpinfo(); + hyn_3240data->fw_updata_process = 100; + HYN_INFO("updata_fw success"); + } + else{ + hyn_3240data->fw_updata_process |= 0x80; + HYN_ERROR("updata_fw failed"); + } + hyn_irq_set(hyn_3240data,ENABLE); + return ret; +} + +static u32 cst3240_check_esd(void) +{ + int ret = 0; + u8 buf[6]; + HYN_ENTER(); + ret = hyn_wr_reg(hyn_3240data,0xD040,2,buf,6); + if(ret ==0 && hyn_sum16(0xA5,buf,4)==U8TO16(buf[4],buf[5])){ + ret = U8TO32(buf[0],buf[1],buf[2],buf[3]); + } + return ret; +} + + +static int cst3240_get_dbg_data(u8 *buf, u16 len) +{ + int ret = -1,timeout; + u16 read_len = (hyn_3240data->hw_info.fw_sensor_txnum * hyn_3240data->hw_info.fw_sensor_rxnum)*2; + u16 total_len = read_len + (hyn_3240data->hw_info.fw_sensor_txnum + hyn_3240data->hw_info.fw_sensor_rxnum)*2; + HYN_ENTER(); + if(total_len > len){ + HYN_ERROR("buf too small"); + return -1; + } + switch(hyn_3240data->work_mode){ + case DIFF_MODE: + case RAWDATA_MODE: + timeout = 60; + while(--timeout){ //wait rise edge + if(gpiod_get_value(hyn_3240data->plat_data.irq_gpio)==1) break; + msleep(1); + } + ret = hyn_wr_reg(hyn_3240data,0x1000,2,buf,read_len); //mt + + buf += read_len; + read_len = hyn_3240data->hw_info.fw_sensor_rxnum*2; + ret |= hyn_wr_reg(hyn_3240data,0x7000,2,buf,read_len); //rx + + buf += read_len; + read_len = hyn_3240data->hw_info.fw_sensor_txnum*2; + ret |= hyn_wr_reg(hyn_3240data,0x7200,2,buf,read_len); //tx + + ret |= hyn_wr_reg(hyn_3240data,0x000500,3,0,0); //end + break; + default: + HYN_ERROR("work_mode:%d",hyn_3240data->work_mode); + break; + } + return ret==0 ? total_len:-1; +} + +#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini" +#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log" +#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST) +static int cst3240_get_test_result(u8 *buf, u16 len) +{ + int ret = 0,timeout; + struct tp_info *ic = &hyn_3240data->hw_info; + u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2,i = 0; + u16 *raw_s; + + HYN_ENTER(); + if((mt_len*3 + scap_len) > len || mt_len==0){ + HYN_ERROR("buf too small"); + return FAC_GET_DATA_FAIL; + } + msleep(1); + timeout = 500; + while(--timeout){ //wait rise edge + if(gpiod_get_value(hyn_3240data->plat_data.irq_gpio)==1) break; + msleep(10); + } + if(hyn_wr_reg(hyn_3240data,0x3000,2,buf,mt_len)){ //open high + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read open high failed"); + goto selftest_end; + } + if(hyn_wr_reg(hyn_3240data,0x1000,2,buf + mt_len,mt_len)){ //open low + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read open low failed"); + goto selftest_end; + } + //short test + if(hyn_wr_reg(hyn_3240data,0x5000,2,buf+(mt_len*2),scap_len)){ + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read fac short failed"); + goto selftest_end; + } + else{ + raw_s = (u16*)(buf + mt_len*2); + for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){ + *raw_s = U16REV((u16)*raw_s); + raw_s++; + } + } + + //read data finlish start test + ret = hyn_factory_multitest(hyn_3240data ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM); + +selftest_end: + if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_3240data,(s16*)buf,ret,FACTEST_ITEM)){ + HYN_INFO("fac_test log save success"); + } + cst3240_resum(); + return ret; +} + + +const struct hyn_ts_fuc hyn_cst3240_fuc = { + .tp_rest = cst3240_rst, + .tp_report = cst3240_report, + .tp_supend = cst3240_supend, + .tp_resum = cst3240_resum, + .tp_chip_init = cst3240_init, + .tp_updata_fw = cst3240_updata_fw, + .tp_set_workmode = cst3240_set_workmode, + .tp_check_esd = cst3240_check_esd, + .tp_prox_handle = cst3240_prox_handle, + .tp_get_dbg_data = cst3240_get_dbg_data, + .tp_get_test_result = cst3240_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst36xxes.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst36xxes.c new file mode 100644 index 000000000000..fc2002f14bb8 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst36xxes.c @@ -0,0 +1,844 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst36xxes.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + + +#include "cst36xxes_fw.h" + +#define BOOT_I2C_ADDR (0x5A) +#define MAIN_I2C_ADDR (0x58) //use 2 slave addr + +#define PART_NO_EN (1) +#define cst36xxes_BIN_SIZE (10*1024) +#define MODULE_ID_ADDR (0x6400) +#define PARTNUM_ADDR (0x7F10) + +static struct hyn_ts_data *hyn_36xxesdata = NULL; +static const u8 gest_map_tbl[] = { + IDX_POWER, //GESTURE_LABEL_CLICK, + IDX_POWER, //GESTURE_LABEL_CLICK2, + IDX_UP, //GESTURE_LABEL_TOP, + IDX_DOWN, //GESTURE_LABEL_BOTTOM, + IDX_LEFT, //GESTURE_LABEL_LEFT, + IDX_RIGHT, //GESTURE_LABEL_RIGHT, + IDX_C, //GESTURE_LABEL_C, + IDX_e, //GESTURE_LABEL_E, + IDX_V, //GESTURE_LABEL_v, + IDX_NULL, //GESTURE_LABEL_^, + IDX_NULL, //GESTURE_LABEL_>, + IDX_NULL, //GESTURE_LABEL_<, + IDX_M, //GESTURE_LABEL_M, + IDX_W, //GESTURE_LABEL_W, + IDX_O, //GESTURE_LABEL_O, + IDX_S, //GESTURE_LABEL_S, + IDX_Z, //GESTURE_LABEL_Z +}; + +static const struct hyn_chip_series hyn_36xxes_fw[] = { + {0xcaca2305,0xffffffff,"cst36xxes",(u8*)fw_bin}, + {0,0,"",NULL} +}; + +static int cst36xxes_updata_judge(u8 *p_fw, u16 len); +static u32 cst36xxes_read_checksum(void); +static int cst36xxes_enter_boot(void); +static u32 cst36xxes_fread_word(u32 addr); +static void cst36xxes_rst(void); + +static int cst36xxes_init(struct hyn_ts_data* ts_data) +{ + int ret = 0,i; + u32 read_part_no,module_id; + HYN_ENTER(); + hyn_36xxesdata = ts_data; + + ret = cst36xxes_enter_boot(); + if(ret){ + HYN_ERROR("cst36xxes_enter_boot failed"); + return -1; + } + hyn_36xxesdata->fw_updata_addr = hyn_36xxes_fw[0].fw_bin; + hyn_36xxesdata->fw_updata_len = cst36xxes_BIN_SIZE; + read_part_no = cst36xxes_fread_word(PARTNUM_ADDR); + module_id = cst36xxes_fread_word(MODULE_ID_ADDR); + HYN_INFO("read_part_no:0x%08x module_id:0x%08x",read_part_no,module_id); + if(module_id > 10) module_id = 0xffffffff; + + for(i = 0; ;i++){ +#if PART_NO_EN + if(hyn_36xxes_fw[i].part_no == read_part_no && hyn_36xxes_fw[i].moudle_id == module_id) +#else + if( hyn_36xxes_fw[i].moudle_id == module_id) +#endif + { hyn_36xxesdata->fw_updata_addr = hyn_36xxes_fw[i].fw_bin; + HYN_INFO("chip %s match fw success ,partNo check is [%s]",hyn_36xxes_fw[i].chip_name,PART_NO_EN ? "enable":"disable"); + break; + } + + if(hyn_36xxes_fw[i].part_no == 0 && hyn_36xxes_fw[i].moudle_id == 0){ + HYN_INFO("unknown chip or unknown moudle_id use hyn_36xxes_fw[0]"); + break; + } + } + + hyn_36xxesdata->hw_info.ic_fw_checksum = cst36xxes_read_checksum(); + hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR); + cst36xxes_rst(); //exit boot + mdelay(50); + + hyn_36xxesdata->need_updata_fw = cst36xxes_updata_judge(hyn_36xxesdata->fw_updata_addr,cst36xxes_BIN_SIZE); + if(hyn_36xxesdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + + + return 0; +} + + +static int cst36xxes_report(void) +{ + u8 buf[80],i=0; + u8 finger_num = 0,key_num=0,report_typ= 0,key_state=0,key_id = 0,tmp_dat=0; + int ret = 0,retry = 2; + + while(retry--){ //read point + ret = hyn_wr_reg(hyn_36xxesdata,0xD0050000,0x80|4,buf,11); + report_typ = buf[4];//FF:pos F0:ges E0:prox + finger_num = buf[5]&0x0f; + key_num = (buf[5]&0xf0)>>4; + if(finger_num+key_num <= MAX_POINTS_REPORT){ + if(key_num + finger_num > 1){ + ret |= hyn_read_data(hyn_36xxesdata,&buf[11],(key_num + finger_num -1)*5); + } + // if(hyn_sum16(0x55,&buf[6],(key_num + finger_num)*5) != (buf[0] | buf[1]<<8)){ + // ret = -1; + // } + } + else{ + ret = -2; + } + if(ret && retry) continue; + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,buf,0); + if(ret == 0){ + break; + } + } + if(ret) return ret; + + if((report_typ==0xff)&&((finger_num+key_num)>0)){ + if(key_num){ + key_id = buf[10]&0x0f; + key_state = buf[10]>>4; + if(hyn_36xxesdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys + hyn_36xxesdata->rp_buf.report_need |= REPORT_KEY; + } + hyn_36xxesdata->rp_buf.key_id = key_id; + hyn_36xxesdata->rp_buf.key_state = key_state !=0 ? 1:0; + } + + if(finger_num){ //pos + u16 index = 0; + u8 touch_down = 0; + if(hyn_36xxesdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys + hyn_36xxesdata->rp_buf.report_need |= REPORT_POS; + } + hyn_36xxesdata->rp_buf.rep_num = finger_num; + for(i = 0; i < finger_num; i++){ + index = (key_num+i)*5; + hyn_36xxesdata->rp_buf.pos_info[i].pos_id = buf[index+10]&0x0F; + hyn_36xxesdata->rp_buf.pos_info[i].event = buf[index+10]>>4; + hyn_36xxesdata->rp_buf.pos_info[i].pos_x = buf[index+6] + ((u16)(buf[index+9]&0x0F) <<8); //x is rx direction + hyn_36xxesdata->rp_buf.pos_info[i].pos_y = buf[index+7] + ((u16)(buf[index+9]&0xf0) <<4); + hyn_36xxesdata->rp_buf.pos_info[i].pres_z = buf[index+8]; + if(hyn_36xxesdata->rp_buf.pos_info[i].event){ + touch_down++; + } + } + if(0== touch_down){ + hyn_36xxesdata->rp_buf.rep_num = 0; + } + } + }else if(report_typ == 0xF0){ + tmp_dat = buf[10]&0xff; + if((tmp_dat&0x7F) < sizeof(gest_map_tbl) && gest_map_tbl[tmp_dat] != IDX_NULL){ + hyn_36xxesdata->gesture_id = gest_map_tbl[tmp_dat]; + hyn_36xxesdata->rp_buf.report_need |= REPORT_GES; + HYN_INFO("gesture_id:%d",tmp_dat); + } + }else if(report_typ == 0xE0){//proximity + u8 state = buf[6] ? PS_FAR_AWAY : PS_NEAR; + if(hyn_36xxesdata->prox_is_enable && hyn_36xxesdata->prox_state != state){ + hyn_36xxesdata->prox_state = state; + hyn_36xxesdata->rp_buf.report_need |= REPORT_PROX; + } + } + return ret; +} + +static int cst36xxes_prox_handle(u8 cmd) +{ + int ret = 0; + switch(cmd){ + case 1: //enable + hyn_36xxesdata->prox_is_enable = 1; + hyn_36xxesdata->prox_state = 0; + ret = hyn_wr_reg(hyn_36xxesdata,0xD004B001,4,NULL,0); + break; + case 0: //disable + hyn_36xxesdata->prox_is_enable = 0; + hyn_36xxesdata->prox_state = 0; + ret = hyn_wr_reg(hyn_36xxesdata,0xD004B000,4,NULL,0); + break; + default: + break; + } + return ret; +} + +static int cst36xxes_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0; + uint8_t i = 0; + for(i=0;i<5;i++) + { + hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,0,0); //disable lp i2c plu + mdelay(1); + ret = hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,0,0); + if(ret == 0) + break; + } + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_36xxesdata,ENABLE); + hyn_esdcheck_switch(hyn_36xxesdata,enable); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000000,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000C00,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000100,4,0,0); + break; + case GESTURE_MODE: + hyn_esdcheck_switch(hyn_36xxesdata,ENABLE); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000C01,4,0,0); + break; + case LP_MODE: + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00004AB,4,0,0); + break; + case DIFF_MODE: + case RAWDATA_MODE: + case BASELINE_MODE: + case CALIBRATE_MODE: + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00001AB,4,0,0); //enter debug mode + break; + case FAC_TEST_MODE: + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + cst36xxes_rst(); + msleep(50); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00000AB,4,0,0); //enter fac test + msleep(50); //wait switch to fac mode + break; + case DEEPSLEEP: + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + hyn_irq_set(hyn_36xxesdata,DISABLE); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00022AB,4,0,0); + break; + case ENTER_BOOT_MODE: + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + ret |= cst36xxes_enter_boot(); + break; + case GLOVE_EXIT: + case GLOVE_ENTER: + hyn_36xxesdata->glove_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_36xxesdata,(mode&0x01)? 0xD0000AAB:0xD0000A00,4,0,0); //glove mode + mode = hyn_36xxesdata->work_mode; //not switch work mode + HYN_INFO("set_glove:%d",hyn_36xxesdata->glove_is_enable); + break; + case CHARGE_EXIT: + case CHARGE_ENTER: + hyn_36xxesdata->charge_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_36xxesdata,(mode&0x01)? 0xD0000BAB:0xD0000B00,4,0,0); //charg mode + mode = hyn_36xxesdata->work_mode; //not switch work mode + HYN_INFO("set_charge:%d",hyn_36xxesdata->charge_is_enable); + break; + default : + hyn_esdcheck_switch(hyn_36xxesdata,enable); + ret = -2; + break; + } + if(ret != -2){ + hyn_36xxesdata->work_mode = mode; + } + HYN_INFO("set_workmode:%d ret:%d",mode,ret); + return ret; +} + + +static int cst36xxes_supend(void) +{ + HYN_ENTER(); + cst36xxes_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst36xxes_resum(void) +{ + HYN_ENTER(); + cst36xxes_rst(); + msleep(50); + cst36xxes_set_workmode(NOMAL_MODE,0); + return 0; +} + +static void cst36xxes_rst(void) +{ + HYN_ENTER(); + if(hyn_36xxesdata->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR); + } + gpiod_direction_output(hyn_36xxesdata->plat_data.reset_gpio,0); + msleep(2); + gpiod_direction_output(hyn_36xxesdata->plat_data.reset_gpio,1); +} + +static int cst36xxes_wait_ready(u16 times,u8 ms,u16 reg,u16 check_vlue) +{ + int ret = 0; + u8 buf[4]; + while(times--){ + ret = hyn_wr_reg(hyn_36xxesdata,reg,2,buf,2); + if(0==ret && U8TO16(buf[0],buf[1])==check_vlue){ + return 0; + } + mdelay(ms); + } + return -1; +} + +static int erase_all_mem(void) +{ + int ret = FALSE; + u8 i2c_buf[8]; + u32 retry = 3; + u32 Flash_addr; + int i = 0; + + for (i=0;i<3;i++){ + Flash_addr = 0x2000 + i*0x1000; + ret |= hyn_wr_reg(hyn_36xxesdata,U8TO32(0xA0,0x06,Flash_addr&0xFF,Flash_addr>>8),4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xA0080010,4,0,0); //set len + ret |= hyn_wr_reg(hyn_36xxesdata,0xA00A0100,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xA018CACA,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xA004E0,3,NULL,0); //trig read + + mdelay(30); + + retry = 20; + while(retry--){ + ret = hyn_wr_reg(hyn_36xxesdata,0xA020,2,i2c_buf,2); + if(ret==0 && i2c_buf[0]==0xE0 && i2c_buf[1]==0x88){ + break; + } + mdelay(1); + } + + } + + return TRUE; +} + +static int write_code(u8 *bin_addr,uint8_t pak_num) +{ + #define PKG_SIZE (512) + u16 eep_addr = 0, eep_len; + u8 i2c_buf[PKG_SIZE+10]; + int i = 0; + + //start trans fw + // eep_addr = 0; + eep_len = 0; + for (i=0; i>8),4,0,0); + hyn_wr_reg(hyn_36xxesdata,0xA0080002,4,0,0); + hyn_wr_reg(hyn_36xxesdata,0xA00A0000,4,0,0); + hyn_wr_reg(hyn_36xxesdata,0xA018CACA,4,0,0); + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x30; + if(0 == hyn_36xxesdata->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr+eep_len, PKG_SIZE); + }else{ + hyn_copy_for_updata(hyn_36xxesdata,i2c_buf + 2,eep_len,PKG_SIZE); + } + hyn_write_data(hyn_36xxesdata, i2c_buf,2, PKG_SIZE+2); + hyn_wr_reg(hyn_36xxesdata, 0xA004E1, 3,0,0); + + eep_len += PKG_SIZE; + mdelay(20); //wait finsh + cst36xxes_wait_ready(100,1,0xA020,0xE188); + hyn_36xxesdata->fw_updata_process = i*100/pak_num; + } + return TRUE; +} + + +static int cst36xxes_enter_boot(void) +{ + int retry = 0,ret = 0; + hyn_set_i2c_addr(hyn_36xxesdata,BOOT_I2C_ADDR); + while(++retry<20){ + cst36xxes_rst(); + mdelay(12+retry); + ret = hyn_wr_reg(hyn_36xxesdata,0xA001A7,3,0,0); + if(ret < 0){ + continue; + } + if(0==cst36xxes_wait_ready(10,2,0xA002,0x33DD)){ + return 0; + } + } + return -1; +} + +static int cst36xxes_updata_tpinfo(void) +{ + u8 buf[60]; + struct tp_info *ic = &hyn_36xxesdata->hw_info; + int ret = 0; + int retry = 5; + while(--retry){ + //get all config info + ret |= cst36xxes_set_workmode(NOMAL_MODE,ENABLE); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0010000,0x80|4,buf,50); + if(ret == 0 && buf[3]==0xCA && buf[2]==0xCA) break; + mdelay(1); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0000400,4,buf,0); + } + + if(ret || retry==0){ + HYN_ERROR("cst36xxes_updata_tpinfo failed"); + return -1; + } + + ic->fw_sensor_txnum = buf[48]; + ic->fw_sensor_rxnum = buf[49]; + ic->fw_key_num = buf[27]; + ic->fw_res_y = (buf[31]<<8)|buf[30]; + ic->fw_res_x = (buf[29]<<8)|buf[28]; + HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y); + + ic->fw_project_id = U8TO32(buf[39],buf[38],buf[37],buf[36]); + ic->fw_chip_type = U8TO32(buf[3],buf[2],buf[1],buf[0]); + ic->fw_ver = U8TO32(buf[35],buf[34],buf[33],buf[32]); + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return 0; +} + +static u32 cst36xxes_fread_word(u32 addr) +{ + int ret; + u8 rec_buf[4],retry; + u32 read_word = 0; + + retry = 3; + while(retry--){ + ret = hyn_wr_reg(hyn_36xxesdata,U8TO32(0xA0,0x06,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr + ret |= hyn_wr_reg(hyn_36xxesdata,0xA0080400,4,0,0); //set len + ret |= hyn_wr_reg(hyn_36xxesdata,0xA00A0000,4,0,0); + ret |= hyn_wr_reg(hyn_36xxesdata,0xA004D2,3,NULL,0); //trig read + if(ret ==0) break; + } + if(ret) return 0; + + retry = 20; + while(retry--){ + ret = hyn_wr_reg(hyn_36xxesdata,0xA020,2,rec_buf,2); + if(ret==0 && rec_buf[0]==0xD2 && rec_buf[1]==0x88){ + ret |= hyn_wr_reg(hyn_36xxesdata,0xA030,2,rec_buf,4); + if(ret ==0){ + read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]); + break; + } + } + mdelay(1); + } + return read_word; +} + +static u32 cst36xxes_read_checksum(void) +{ + int ret = -1; + u8 buf[10] = {0}; + u32 chipSum = 0; + hyn_36xxesdata->boot_is_pass = 0; + + hyn_wr_reg(hyn_36xxesdata,0xA004D6,3,0,0); + mdelay(30); + + ret = cst36xxes_wait_ready(20,2,0xA020,0xD688); + + ret |= hyn_wr_reg(hyn_36xxesdata,0xA030,2,buf,10); + if(ret == 0 && buf[5] == 0xCA){ + chipSum = U8TO32(buf[9],buf[8],buf[7],buf[6]); + hyn_36xxesdata->boot_is_pass = 1; + } + return chipSum; +} + +static int cst36xxes_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + // u32 f_check_all; + u8 *p_data = p_fw + 192; //35k + int ret; + struct tp_info *ic = &hyn_36xxesdata->hw_info; + + f_fw_project_id = U8TO32(p_data[39],p_data[38],p_data[37],p_data[36]); + f_ictype = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]); + f_fw_ver = U8TO32(p_data[35],p_data[34],p_data[33],p_data[32]); + + p_data = p_fw + cst36xxes_BIN_SIZE - 4; + f_checksum = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]); + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + + ret = cst36xxes_updata_tpinfo(); //boot checksum pass, communicate failed not updata + if(ret) HYN_ERROR("get tpinfo failed"); + + if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){ + HYN_ERROR("not update,please confirm:f_ictype 0x%04x,f_fw_project_id 0x%04x",f_ictype,f_fw_project_id); + return 0; //not updata + } + + if(hyn_36xxesdata->boot_is_pass ==0 //boot failed + || ( ret == 0 && f_ictype == ic->fw_chip_type && f_checksum != ic->ic_fw_checksum && f_fw_ver > ic->fw_ver ) // match new ver .h file + ){ + return 1; //need updata + } + return 0; +} + +static int cst36xxes_updata_fw(u8 *bin_addr, u16 len) +{ + #define PKG_SIZE (512) + int ret = -1, retry_fw= 4,pak_num; + u8 i2c_buf[PKG_SIZE+10] , *p_bin_addr; + u32 fw_checksum = 0; + HYN_ENTER(); + HYN_INFO("len = %d",len); + hyn_36xxesdata->fw_updata_process = 0; + if(len < cst36xxes_BIN_SIZE){ + HYN_ERROR("bin len erro"); + goto UPDATA_END; + } + len = cst36xxes_BIN_SIZE-4; + if(0 == hyn_36xxesdata->fw_file_name[0]){ + p_bin_addr = bin_addr + len; + fw_checksum = U8TO32(p_bin_addr[3],p_bin_addr[2],p_bin_addr[1],p_bin_addr[0]); + } + else{ + ret = hyn_copy_for_updata(hyn_36xxesdata,i2c_buf,cst36xxes_BIN_SIZE,4); + if(ret) goto UPDATA_END; + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + } + HYN_INFO("fw_checksum_all:%04x",fw_checksum); + hyn_irq_set(hyn_36xxesdata,DISABLE); + hyn_esdcheck_switch(hyn_36xxesdata,DISABLE); + len = cst36xxes_BIN_SIZE; + pak_num = len/PKG_SIZE; + while(--retry_fw){ + ret = cst36xxes_enter_boot(); + if(ret){ + HYN_INFO("cst36xxes_enter_boot fail"); + continue; + } + + ret = erase_all_mem(); + if(ret){ + HYN_INFO("erase_all_mem fail"); + continue; + } + + ret = write_code(bin_addr,pak_num); + if (ret){ + HYN_INFO("write_code fail"); + continue; + } + + hyn_36xxesdata->hw_info.ic_fw_checksum = cst36xxes_read_checksum(); + HYN_INFO("ic_fw_checksum:%04x",hyn_36xxesdata->hw_info.ic_fw_checksum); + if(fw_checksum == hyn_36xxesdata->hw_info.ic_fw_checksum && 0 != hyn_36xxesdata->boot_is_pass){ + break; + } + } +UPDATA_END: + hyn_set_i2c_addr(hyn_36xxesdata,MAIN_I2C_ADDR); + cst36xxes_rst(); + if(ret == 0){ + msleep(50); + cst36xxes_updata_tpinfo(); + hyn_36xxesdata->fw_updata_process = 100; + HYN_INFO("updata_fw success"); + } + else{ + hyn_36xxesdata->fw_updata_process |= 0x80; + HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_36xxesdata->hw_info.ic_fw_checksum); + } + hyn_irq_set(hyn_36xxesdata,ENABLE); + return ret; +} + +static u32 cst36xxes_check_esd(void) +{ + int16_t ok = FALSE; + uint8_t i2c_buf[6], retry; + uint8_t flag = 0; + uint32_t esd_value = 0; + + retry = 4; + flag = 0; + while (retry--) + { + hyn_wr_reg(hyn_36xxesdata,0xD0190000,4,i2c_buf,0); + udelay(200); + ok = hyn_wr_reg(hyn_36xxesdata,0xD0190000,4,i2c_buf,1); + if (ok == FALSE){ + msleep(1); + continue; + } else { + if ((i2c_buf[0] == 0x20) || (i2c_buf[0]==0xA0)){ + flag = 1; + esd_value = i2c_buf[0]; + break; + } else { + HYN_INFO("ESD data NA: 0x%x ",i2c_buf[0]); + msleep(2); + continue; + } + } + } + HYN_INFO("ESD data:%d,0x%04x,0x%04x", flag, esd_value, hyn_36xxesdata->esd_last_value); + if (flag == 0) + { + hyn_power_source_ctrl(hyn_36xxesdata, 0); + mdelay(2); + hyn_power_source_ctrl(hyn_36xxesdata, 1); + mdelay(2); + cst36xxes_rst(); + msleep(40); + esd_value = 0; + hyn_36xxesdata->esd_last_value = 0; + HYN_INFO("esd_check power reset ic"); + } + if ((hyn_36xxesdata->work_mode == GESTURE_MODE)&&(esd_value != 0xA0)) + { + ok = hyn_wr_reg(hyn_36xxesdata,0xD0000C01,4,0,0); + if (ok == FALSE){ + HYN_ERROR("enter_sleep failed"); + } + } + + hyn_36xxesdata->esd_last_value = esd_value; + return esd_value; +} + +static int red_dbg_data(u8 *buf, u16 len ,u32 *cmd_list,u8 type) +{ + struct tp_info *ic = &hyn_36xxesdata->hw_info; + int ret = 0; + u16 read_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum)*type; + u16 total_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum + ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*type; + if(total_len > len || read_len == 0){ + HYN_ERROR("buf too small or fw_sensor_rxnum fw_sensor_txnum erro"); + return -1; + } + ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //m cap + buf += read_len; + read_len = ic->fw_sensor_rxnum*type; + ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //s rx cap + buf += read_len; + read_len = ic->fw_sensor_txnum*type; + ret |= hyn_wr_reg(hyn_36xxesdata,*cmd_list++,0x80|4,buf,read_len); //s tx cap + // ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); //end + return ret < 0 ? -1:total_len; +} + +static int cst36xxes_get_dbg_data(u8 *buf, u16 len) +{ + int read_len = -1,ret = 0; + HYN_ENTER(); + switch(hyn_36xxesdata->work_mode){ + case DIFF_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD0090000,0xD0110000,0xD00D0000},2); + break; + case RAWDATA_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD0080000,0xD0100000,0xD00C0000},2); + break; + case BASELINE_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD00A0000,0xD0120000,0xD00E0000},2); + break; + case CALIBRATE_MODE:{ + u16 tmp_len = len/2; + len /= 2; + read_len = red_dbg_data(buf+tmp_len,tmp_len,(u32[]){0xD00B0000,0xD0130000,0xD00F0000},1); + if(read_len > 0){ + u8 *src_ptr = buf+tmp_len,tmp; + s16 *des_ptr = (s16*)buf; + tmp_len = read_len; + while(tmp_len--){ + tmp = (*src_ptr++)&0x7F; + *des_ptr++ = (tmp & 0x40) ? -(tmp&0x3F):tmp; + } + read_len *= 2; + } + break; + } + default: + HYN_ERROR("work_mode:%d",hyn_36xxesdata->work_mode); + break; + } + // HYN_INFO("read_len:%d len:%d",(int)(sizeof(struct ts_frame)+read_len),len); + if(read_len > 0 && len > (sizeof(struct ts_frame)+read_len)){ + ret = cst36xxes_report(); + if(ret ==0){ + memcpy(buf+read_len+4,(void*)&hyn_36xxesdata->rp_buf,sizeof(struct ts_frame)); + read_len += sizeof(struct ts_frame); + } + } + else{ + hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); //end + } + return read_len; +} + +static int get_fac_test_data(u32 cmd ,u8 *buf, u16 len ,u8 rev) +{ + int ret = 0; + ret = hyn_wr_reg(hyn_36xxesdata,cmd,4,0,0); + ret |= hyn_wait_irq_timeout(hyn_36xxesdata,100); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD0090000,0x80|4,buf+rev,len); + ret |= hyn_wr_reg(hyn_36xxesdata,0xD00002AB,4,0,0); + if(ret==0 && rev){ + len /= 2; + while(len--){ + *buf = *(buf+2); + buf += 2; + } + } + return ret; +} + +#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini" +#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log" +#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST|MULTI_SCAP_TEST) + +static int cst36xxes_get_test_result(u8 *buf, u16 len) +{ + struct tp_info *ic = &hyn_36xxesdata->hw_info; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2; + u16 st_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2; + u8 *rbuf = buf; + u16 *raw_s; + uint8_t i2c_buf[6]; + int i = 0; + + int ret = FAC_GET_DATA_FAIL; + HYN_ENTER(); + if((mt_len*3 + st_len*2 + 4) > len || mt_len==0){ + HYN_ERROR("%s", mt_len ? "buf too small":" ic->fw_sensor_rxnum*ic->fw_sensor_txnum=0"); + return FAC_GET_DATA_FAIL; + } + if(get_fac_test_data(0xD0002B77,rbuf,mt_len,0)){ //read open high data + HYN_ERROR("read open high failed"); + goto TEST_ERRO; + } + rbuf += mt_len; + if(get_fac_test_data(0xD0002B07,rbuf,mt_len,0)){ //read open low data + HYN_ERROR("read open low failed"); + goto TEST_ERRO; + } + rbuf += mt_len; + if(get_fac_test_data(0xD0002C00,rbuf,st_len,0)){ //read short test data + HYN_ERROR("read fac short failed"); + goto TEST_ERRO; + } + else + { + raw_s = (u16*)(rbuf); + HYN_INFO("raw_s start data = %d",*(raw_s)); + for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){ + HYN_INFO("short raw data = %d %d",i, *(raw_s+i)); + if((*raw_s) != 0) *raw_s = 2000 / (*raw_s); + else *raw_s =0; + HYN_INFO(" data = %d",*(raw_s)); + raw_s++; + } + } + //must rest + rbuf += st_len; + cst36xxes_rst(); + msleep(20); + ret = hyn_wr_reg(hyn_36xxesdata,0xD00000AB,4,0,0); + if(ret){ + HYN_ERROR("exit lowpower scan failed"); + return FAC_GET_CFG_FAIL; + } + for (i=0;i<10;i++) + { + ret = hyn_wr_reg(hyn_36xxesdata,0xD0020100,4,i2c_buf,1); + if(ret){ + msleep(1); + continue; + } + HYN_INFO("i2c_buf[0] 0x%x", i2c_buf[0]); + if (i2c_buf[0] == 0x30) + break; + + msleep(1); + } + + if(get_fac_test_data(0xD0002D00,rbuf,st_len,0)){ ///read scap test data + HYN_ERROR("read scap failed"); + goto TEST_ERRO; + } + ////read data finlish start test + ret = hyn_factory_multitest(hyn_36xxesdata ,FACTEST_PATH, buf,(s16*)(rbuf+st_len),FACTEST_ITEM); + +TEST_ERRO: + if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_36xxesdata,(s16*)buf,ret,FACTEST_ITEM)){ + HYN_INFO("fac_test log save success"); + } + cst36xxes_resum(); + return ret; +} + + +const struct hyn_ts_fuc hyn_cst36xxes_fuc = { + .tp_rest = cst36xxes_rst, + .tp_report = cst36xxes_report, + .tp_supend = cst36xxes_supend, + .tp_resum = cst36xxes_resum, + .tp_chip_init = cst36xxes_init, + .tp_updata_fw = cst36xxes_updata_fw, + .tp_set_workmode = cst36xxes_set_workmode, + .tp_check_esd = cst36xxes_check_esd, + .tp_prox_handle = cst36xxes_prox_handle, + .tp_get_dbg_data = cst36xxes_get_dbg_data, + .tp_get_test_result = cst36xxes_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3xx.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3xx.c new file mode 100644 index 000000000000..43d624d6f829 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst3xx.c @@ -0,0 +1,451 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst3xx.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst3xx_fw.h" + +#define BOOT_I2C_ADDR (0x1A) +#define MAIN_I2C_ADDR (0x1A) +#define RW_REG_LEN (2) +#define CST3xx_BIN_SIZE (24*1024 + 24) +#define SOFT_RST_ENABLE (0) + +static struct hyn_ts_data *hyn_3xxdata = NULL; +static const u8 gest_map_tbl[33] = {0xff,4,1,3,2,5,12,6,7,7,9,11,10,13,12,7,7,6,10,6,5,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,14}; + +static int cst3xx_updata_judge(u8 *p_fw, u16 len); +static int cst3xx_read_checksum(u32* check_sum); +static int cst3xx_updata_tpinfo(void); +static int cst3xx_enter_boot(void); +static int cst3xx_set_workmode(enum work_mode mode,u8 enable); +static void cst3xx_rst(void); + +static int cst3xx_init(struct hyn_ts_data* ts_data) +{ + int ret = 0; + HYN_ENTER(); + hyn_3xxdata = ts_data; + ret = cst3xx_enter_boot(); + if(ret){ + HYN_ERROR("cst3xx_enter_boot failed"); + return -1; + } + hyn_3xxdata->fw_updata_addr = (u8*)fw_bin; + hyn_3xxdata->fw_updata_len = CST3xx_BIN_SIZE; + if(0 == cst3xx_read_checksum(&hyn_3xxdata->hw_info.ic_fw_checksum)){ + hyn_3xxdata->boot_is_pass = 1; + } + hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR); + cst3xx_rst(); + mdelay(50); + + hyn_3xxdata->need_updata_fw = cst3xx_updata_judge((u8*)fw_bin,CST3xx_BIN_SIZE); + if(hyn_3xxdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + return 0; +} + +static int cst3xx_report(void) +{ + u8 buf[80]; + u8 finger_num = 0,len = 0,write_tail_end = 0,key_state=0,key_id = 0,tmp_dat; + int ret = 0; + hyn_3xxdata->rp_buf.report_need = REPORT_NONE; + switch(hyn_3xxdata->work_mode){ + case NOMAL_MODE: + write_tail_end = 1; + ret = hyn_wr_reg(hyn_3xxdata,0xD000,2,buf,7); + len = buf[5] & 0x7F; + if(ret || buf[6] != 0xAB || buf[0] == 0xAB || len > MAX_POINTS_REPORT){ + ret = -1; + break; + } + if(buf[5]&0x80){ //key + if(buf[5]==0x80){ + key_id = (buf[1]>>4)-1; + key_state = buf[0]; + } + else{ + // finger_num = len; + len = (len-1)*5+3; + ret = hyn_wr_reg(hyn_3xxdata,0xD007,2,&buf[5],len); + len += 5; + key_id = (buf[len-2]>>4)-1; + key_state = buf[len-3]; + } + if(key_state&0x80){ + hyn_3xxdata->rp_buf.report_need |= REPORT_KEY; + if((key_id == hyn_3xxdata->rp_buf.key_id || 0 == hyn_3xxdata->rp_buf.key_state)&& key_state == 0x83){ + hyn_3xxdata->rp_buf.key_id = key_id; + hyn_3xxdata->rp_buf.key_state = 1; + } + else{ + hyn_3xxdata->rp_buf.key_state = 0; + } + } + } + else{ //pos + u16 index = 0; + u8 i = 0; + finger_num = len; + hyn_3xxdata->rp_buf.report_need |= REPORT_POS; + if(finger_num > 1){ + len = (len-1)*5 + 1; + ret = hyn_wr_reg(hyn_3xxdata,0xD007,2,&buf[5],len); + } + hyn_3xxdata->rp_buf.rep_num = finger_num; + for(i = 0; i < finger_num; i++){ + index = i*5; + hyn_3xxdata->rp_buf.pos_info[i].pos_id = (buf[index]>>4)&0x0F; + hyn_3xxdata->rp_buf.pos_info[i].event = (buf[index]&0x0F) == 0x06 ? 1 : 0; + hyn_3xxdata->rp_buf.pos_info[i].pos_x = ((u16)buf[index + 1]<<4) + ((buf[index + 3] >> 4) & 0x0F); + hyn_3xxdata->rp_buf.pos_info[i].pos_y = ((u16)buf[index + 2]<<4) + (buf[index + 3] & 0x0F); + hyn_3xxdata->rp_buf.pos_info[i].pres_z = buf[index + 4]; + // HYN_INFO("report_id = %d, xy = %d,%d",hyn_3xxdata->rp_buf.pos_info[i].pos_id,hyn_3xxdata->rp_buf.pos_info[i].pos_x,hyn_3xxdata->rp_buf.pos_info[i].pos_y); + } + } + break; + case GESTURE_MODE: + ret = hyn_wr_reg(hyn_3xxdata,0xD04C,2,&tmp_dat,1); + if((tmp_dat&0x7F) <= 32){ + tmp_dat = tmp_dat&0x7F; + hyn_3xxdata->gesture_id = gest_map_tbl[tmp_dat]; + hyn_3xxdata->rp_buf.report_need |= REPORT_GES; + } + break; + default: + break; + } + if(write_tail_end){ + hyn_wr_reg(hyn_3xxdata,0xD000AB,3,buf,0); + } + return ret; +} + +static int cst3xx_prox_handle(u8 cmd) +{ + int ret = 0; + switch(cmd){ + case 1: //enable + hyn_3xxdata->prox_is_enable = 1; + hyn_3xxdata->prox_state = 0; + ret = hyn_wr_reg(hyn_3xxdata,0xD004B01,3,NULL,0); + break; + case 0: //disable + hyn_3xxdata->prox_is_enable = 0; + hyn_3xxdata->prox_state = 0; + ret = hyn_wr_reg(hyn_3xxdata,0xD004B00,3,NULL,0); + break; + case 2: //read + ret = hyn_wr_reg(hyn_3xxdata,0xD004B,2,&hyn_3xxdata->prox_state,1); + break; + } + return ret; +} + +static int cst3xx_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0; + hyn_3xxdata->work_mode = mode; + if(mode != NOMAL_MODE) + hyn_esdcheck_switch(hyn_3xxdata,DISABLE); + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_3xxdata,ENABLE); + hyn_esdcheck_switch(hyn_3xxdata,enable); + // hyn_wr_reg(hyn_3xxdata,0xD100,2,NULL,0); + hyn_wr_reg(hyn_3xxdata,0xD109,2,NULL,0); + break; + case GESTURE_MODE: + hyn_wr_reg(hyn_3xxdata,0xD04C80,3,NULL,0); + break; + case LP_MODE: + break; + case DIFF_MODE: + hyn_wr_reg(hyn_3xxdata,0xD10D,2,NULL,0); + break; + case RAWDATA_MODE: + hyn_wr_reg(hyn_3xxdata,0xD10A,2,NULL,0); + break; + case FAC_TEST_MODE: + hyn_wr_reg(hyn_3xxdata,0xD119,2,NULL,0); + break; + case DEEPSLEEP: + hyn_irq_set(hyn_3xxdata,DISABLE); + hyn_wr_reg(hyn_3xxdata,0xD105,2,NULL,0); + break; + case ENTER_BOOT_MODE: + ret |= cst3xx_enter_boot(); + break; + default : + hyn_esdcheck_switch(hyn_3xxdata,ENABLE); + hyn_3xxdata->work_mode = NOMAL_MODE; + break; + } + return ret; +} + + +static int cst3xx_supend(void) +{ + HYN_ENTER(); + cst3xx_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst3xx_resum(void) +{ + HYN_ENTER(); + cst3xx_rst(); + msleep(50); + cst3xx_set_workmode(NOMAL_MODE,0); + return 0; +} + +static void cst3xx_rst(void) +{ + if(hyn_3xxdata->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR); + } + #if SOFT_RST_ENABLE + hyn_wr_reg(hyn_3xxdata,0xD10E,2,NULL,0); + #endif + gpiod_direction_output(hyn_3xxdata->plat_data.reset_gpio,0); + msleep(10); + gpiod_direction_output(hyn_3xxdata->plat_data.reset_gpio,1); +} + +static int cst3xx_enter_boot(void) +{ + int retry = 5,ret = 0; + u8 buf[4] = {0}; + hyn_set_i2c_addr(hyn_3xxdata,BOOT_I2C_ADDR); + while(++retry < 17){ + cst3xx_rst(); + mdelay(retry); + ret = hyn_wr_reg(hyn_3xxdata,0xA001AA,3,buf,0); + if(ret != 0){ + continue; + } + ret = hyn_wr_reg(hyn_3xxdata,0xA002,2,buf,1); + if(ret == 0 && (buf[0] == 0xAC || buf[0] == 0x55)){ //ac:3xx 55:1xx + return 0; + } + } + return -1; +} + +static int cst3xx_updata_tpinfo(void) +{ + u8 buf[28]; + struct tp_info *ic = &hyn_3xxdata->hw_info; + int ret = 0; + ret = hyn_wr_reg(hyn_3xxdata,0xD101,2,buf,0); + mdelay(1); + ret |= hyn_wr_reg(hyn_3xxdata,0xD1F4,2,buf,28); + if(ret){ + HYN_ERROR("cst3xx_updata_tpinfo failed"); + return -1; + } + + ic->fw_sensor_txnum = buf[0]; + ic->fw_sensor_rxnum = buf[2]; + ic->fw_key_num = buf[3]; + ic->fw_res_y = (buf[7]<<8)|buf[6]; + ic->fw_res_x = (buf[5]<<8)|buf[4]; + ic->fw_project_id = (buf[17]<<8)|buf[16]; + ic->fw_chip_type = (buf[19]<<8)|buf[18]; + ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20]; + + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return 0; +} + +static int cst3xx_read_checksum(u32* check_sum) +{ + int ret; + u8 buf[4],retry = 5; + while(retry--){ + ret = hyn_wr_reg(hyn_3xxdata,0xA000,2,buf,1); + if(ret){ + mdelay(2); + continue; + } + if(buf[0]!=0) break; + mdelay(2); + } + mdelay(1); + if(buf[0] == 0x01){ + memset(buf,0,sizeof(buf)); + ret = hyn_wr_reg(hyn_3xxdata,0xA008,2,buf,4); + if(0 == ret){ + *check_sum = U8TO32(buf[3],buf[2],buf[1],buf[0]); + return 0; + } + } + return -1; +} + +static int cst3xx_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + u8 *p_data = p_fw + len- 16; + struct tp_info *ic = &hyn_3xxdata->hw_info; + f_fw_project_id = U8TO16(p_data[1],p_data[0]); + f_ictype = U8TO16(p_data[3],p_data[2]); + f_fw_ver = U8TO16(p_data[7],p_data[6]); + f_fw_ver = (f_fw_ver<<16)|U8TO16(p_data[5],p_data[4]); + f_checksum = U8TO16(p_data[11],p_data[10]); + f_checksum = (f_checksum << 16)|U8TO16(p_data[9],p_data[8]); + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + + cst3xx_updata_tpinfo(); + cst3xx_set_workmode(NOMAL_MODE,1); + + if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){ + return 0; //not updata + } + if( hyn_3xxdata->boot_is_pass ==0 //boot failed + ||(f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver)){ + return 1; //need updata + } + return 0; +} + +static int cst3xx_updata_fw(u8 *bin_addr, u16 len) +{ + #define CHECKSUM_OFFECT (24*1024+16) + int i,ret, retry = 4; + u8 *i2c_buf; + u16 eep_addr = 0, total_kbyte = 24; + u32 fw_checksum= 0; + HYN_ENTER(); + i2c_buf = kmalloc(1024 + 2, GFP_KERNEL); + if(0 == hyn_3xxdata->fw_file_name[0]){ + fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT]); + } + else{ + ret = hyn_copy_for_updata(hyn_3xxdata,i2c_buf,CHECKSUM_OFFECT,4); + if(ret) goto UPDATA_END; + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + } + hyn_irq_set(hyn_3xxdata,DISABLE); + while(--retry){ + ret = cst3xx_enter_boot(); + if(ret){ + HYN_ERROR("cst3xx_enter_boot fail"); + continue; + } + ret = hyn_wr_reg(hyn_3xxdata,0xA00200,3,i2c_buf,0); + if(ret) continue; + mdelay(5); + ret = hyn_wr_reg(hyn_3xxdata,0xA003,2,i2c_buf,1); + if(i2c_buf[0] != 0x55)continue; + //start trans fw + for (i=0; i>8; + hyn_write_data(hyn_3xxdata, i2c_buf,RW_REG_LEN, 4); + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + if(0 == hyn_3xxdata->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr + eep_addr, 1024); + } + else{ + hyn_copy_for_updata(hyn_3xxdata,i2c_buf + 2,eep_addr,1024); + } + hyn_write_data(hyn_3xxdata, i2c_buf,RW_REG_LEN, 1026); + + hyn_wr_reg(hyn_3xxdata, 0xA004EE, 3,i2c_buf,0); + mdelay(60); //wait finsh + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x05; + ret = hyn_wr_reg(hyn_3xxdata,0xA005,2,i2c_buf,1); + if (ret < 0 || i2c_buf[0] != 0x55){ + ret = -1; + break; + } + } + if(ret) continue; + ret = hyn_wr_reg(hyn_3xxdata,0xA00300,3,i2c_buf,0); + if(ret) continue; + cst3xx_read_checksum(&hyn_3xxdata->hw_info.ic_fw_checksum); + if(fw_checksum == hyn_3xxdata->hw_info.ic_fw_checksum){ + break; + } + } +UPDATA_END: + hyn_set_i2c_addr(hyn_3xxdata,MAIN_I2C_ADDR); + cst3xx_rst(); + if(fw_checksum == hyn_3xxdata->hw_info.ic_fw_checksum){ + mdelay(50); + cst3xx_updata_tpinfo(); + HYN_INFO("updata_fw success"); + } + else{ + HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_3xxdata->hw_info.ic_fw_checksum); + } + hyn_irq_set(hyn_3xxdata,ENABLE); + + kfree(i2c_buf); + return !retry; +} + +static u32 cst3xx_check_esd(void) +{ + int ret = 0; + u8 buf[6]; + ret = hyn_wr_reg(hyn_3xxdata,0xD040,2,buf,6); + if(ret ==0){ + u16 checksum = buf[0]+buf[1]+buf[2]+buf[3]+0xA5; + if(checksum != ( (buf[4]<<8)+ buf[5])){ + ret = -1; + } + } + return ret ? 0:(buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24)); +} + +static int cst3xx_get_dbg_data(u8 *buf, u16 len) +{ + return 0; +} + +static int cst3xx_get_test_result(u8 *buf, u16 len) +{ + return 0; +} + + +const struct hyn_ts_fuc hyn_cst3xx_fuc = { + .tp_rest = cst3xx_rst, + .tp_report = cst3xx_report, + .tp_supend = cst3xx_supend, + .tp_resum = cst3xx_resum, + .tp_chip_init = cst3xx_init, + .tp_updata_fw = cst3xx_updata_fw, + .tp_set_workmode = cst3xx_set_workmode, + .tp_check_esd = cst3xx_check_esd, + .tp_prox_handle = cst3xx_prox_handle, + .tp_get_dbg_data = cst3xx_get_dbg_data, + .tp_get_test_result = cst3xx_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst66xx.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst66xx.c new file mode 100644 index 000000000000..8b0dae3f19ff --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst66xx.c @@ -0,0 +1,802 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst66xx.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + + +#include "cst66xx_fw1.h" +#include "cst66xx_fw2.h" + +#define BOOT_I2C_ADDR (0x5A) +#define MAIN_I2C_ADDR (0x58) //use 2 slave addr + +#define PART_NO_EN (0) +#define cst66xx_BIN_SIZE (40*1024) //(44*1024) (36*1024) +#define MODULE_ID_ADDR (0xA400) +#define PARTNUM_ADDR (0xFF10) + +static struct hyn_ts_data *hyn_66xxdata = NULL; +static const u8 gest_map_tbl[] = { + IDX_POWER, //GESTURE_LABEL_CLICK, + IDX_POWER, //GESTURE_LABEL_CLICK2, + IDX_UP, //GESTURE_LABEL_TOP, + IDX_DOWN, //GESTURE_LABEL_BOTTOM, + IDX_LEFT, //GESTURE_LABEL_LEFT, + IDX_RIGHT, //GESTURE_LABEL_RIGHT, + IDX_C, //GESTURE_LABEL_C, + IDX_e, //GESTURE_LABEL_E, + IDX_V, //GESTURE_LABEL_v, + IDX_NULL, //GESTURE_LABEL_^, + IDX_NULL, //GESTURE_LABEL_>, + IDX_NULL, //GESTURE_LABEL_<, + IDX_M, //GESTURE_LABEL_M, + IDX_W, //GESTURE_LABEL_W, + IDX_O, //GESTURE_LABEL_O, + IDX_S, //GESTURE_LABEL_S, + IDX_Z, //GESTURE_LABEL_Z +}; + +static const struct hyn_chip_series hyn_6xx_fw[] = { + {0xCACA220E,0xffffffff,"cst3530",(u8*)fw_module1},//if PART_NO_EN==0 use default chip + {0xCACA2202,0xffffffff,"cst3640",(u8*)fw_module1}, + {0xCACA2201,0xffffffff,"cst6656",(u8*)fw_module1}, + {0xCACA220C,0xffffffff,"cst3548",(u8*)fw_module1}, + {0xCACA2209,0xffffffff,"cst3556",(u8*)fw_module1}, + {0xCACA2203,0xffffffff,"cst6644",(u8*)fw_module1}, + {0xCACA2204,0xffffffff,"cst6856",(u8*)fw_module1}, + {0xCACA2204,0x00000002,"cst6856",(u8*)fw_module2}, + //0xCACA2205 //154 + //0xCACA2206 //148E + {0,0,"",NULL} +}; + +static int cst66xx_updata_judge(u8 *p_fw, u16 len); +static u32 cst66xx_read_checksum(void); +static int cst66xx_enter_boot(void); +static u32 cst66xx_fread_word(u32 addr); +static void cst66xx_rst(void); + +static int cst66xx_init(struct hyn_ts_data* ts_data) +{ + int ret = 0,i; + u32 read_part_no,module_id; + HYN_ENTER(); + hyn_66xxdata = ts_data; + + ret = cst66xx_enter_boot(); + if(ret){ + HYN_ERROR("cst66xx_enter_boot failed"); + return -1; + } + hyn_66xxdata->fw_updata_addr = hyn_6xx_fw[0].fw_bin; + hyn_66xxdata->fw_updata_len = cst66xx_BIN_SIZE; + read_part_no = cst66xx_fread_word(PARTNUM_ADDR); + module_id = cst66xx_fread_word(MODULE_ID_ADDR); + HYN_INFO("read_part_no:0x%08x module_id:0x%08x",read_part_no,module_id); + if(module_id > 10) module_id = 0xffffffff; + + for(i = 0; ;i++){ +#if PART_NO_EN + if(hyn_6xx_fw[i].part_no == read_part_no && hyn_6xx_fw[i].moudle_id == module_id) +#else + if( hyn_6xx_fw[i].moudle_id == module_id) +#endif + { hyn_66xxdata->fw_updata_addr = hyn_6xx_fw[i].fw_bin; + HYN_INFO("chip %s match fw success ,partNo check is [%s]",hyn_6xx_fw[i].chip_name,PART_NO_EN ? "enable":"disable"); + break; + } + + if(hyn_6xx_fw[i].part_no == 0 && hyn_6xx_fw[i].moudle_id == 0){ + HYN_INFO("unknown chip or unknown moudle_id use hyn_6xx_fw[0]"); + break; + } + } + hyn_66xxdata->hw_info.fw_module_id = module_id; + hyn_66xxdata->hw_info.ic_fw_checksum = cst66xx_read_checksum(); + hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR); + cst66xx_rst(); //exit boot + mdelay(50); + + hyn_66xxdata->need_updata_fw = cst66xx_updata_judge(hyn_66xxdata->fw_updata_addr,cst66xx_BIN_SIZE); + if(hyn_66xxdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + return 0; +} + + +static int cst66xx_report(void) +{ + u8 buf[80],i=0; + u8 finger_num = 0,key_num=0,report_typ= 0,key_state=0,key_id = 0,tmp_dat=0; + int ret = 0,retry = 2; + + while(retry--){ //read point + ret = hyn_wr_reg(hyn_66xxdata,0xD0070000,0x80|4,buf,9); + report_typ = buf[2];//FF:pos F0:ges E0:prox + finger_num = buf[3]&0x0f; + key_num = ((buf[3]&0xf0)>>4); + if(finger_num+key_num <= MAX_POINTS_REPORT){ + if(key_num + finger_num > 1){ + ret |= hyn_read_data(hyn_66xxdata,&buf[9],(key_num + finger_num -1)*5); + } + if(hyn_sum16(0x55,&buf[4],(key_num + finger_num)*5) != (buf[0] | buf[1]<<8)){ + ret = -1; + } + } + else{ + ret = -2; + } + if(ret && retry) continue; + ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,buf,0); + if(ret == 0){ + break; + } + } + if(ret) return ret; + if((report_typ==0xff)&&((finger_num+key_num)>0)){ + if(key_num){ + key_id = buf[8]&0x0f; + key_state = buf[8]>>4; + if(hyn_66xxdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys + hyn_66xxdata->rp_buf.report_need |= REPORT_KEY; + } + hyn_66xxdata->rp_buf.key_id = key_id; + hyn_66xxdata->rp_buf.key_state = key_state !=0 ? 1:0; + } + + if(finger_num){ //pos + u16 index = 0; + u8 touch_down = 0; + if(hyn_66xxdata->rp_buf.report_need == REPORT_NONE){ //Mutually exclusive reporting of coordinates and keys + hyn_66xxdata->rp_buf.report_need |= REPORT_POS; + } + hyn_66xxdata->rp_buf.rep_num = finger_num; + for(i = 0; i < finger_num; i++){ + index = (key_num+i)*5; + hyn_66xxdata->rp_buf.pos_info[i].pos_id = buf[index+8]&0x0F; + hyn_66xxdata->rp_buf.pos_info[i].event = buf[index+8]>>4; + hyn_66xxdata->rp_buf.pos_info[i].pos_x = buf[index+4] + ((u16)(buf[index+7]&0x0F) <<8); //x is rx direction + hyn_66xxdata->rp_buf.pos_info[i].pos_y = buf[index+5] + ((u16)(buf[index+7]&0xf0) <<4); + hyn_66xxdata->rp_buf.pos_info[i].pres_z = buf[index+6]; + if(hyn_66xxdata->rp_buf.pos_info[i].event){ + touch_down++; + } + } + if(0== touch_down){ + hyn_66xxdata->rp_buf.rep_num = 0; + } + } + }else if(report_typ == 0xF0){ //gesture + tmp_dat = buf[8]&0xff; + if((tmp_dat&0x7F) < sizeof(gest_map_tbl) && gest_map_tbl[tmp_dat] != IDX_NULL){ + hyn_66xxdata->gesture_id = gest_map_tbl[tmp_dat]; + hyn_66xxdata->rp_buf.report_need |= REPORT_GES; + HYN_INFO("gesture_id:%d",tmp_dat); + } + }else if(report_typ == 0xE0){//proximity + u8 state = buf[4] ? PS_FAR_AWAY : PS_NEAR; + if(hyn_66xxdata->prox_is_enable && hyn_66xxdata->prox_state != state){ + hyn_66xxdata->prox_state =state; + hyn_66xxdata->rp_buf.report_need |= REPORT_PROX; + } + } + return ret; +} + +static int cst66xx_prox_handle(u8 cmd) +{ + int ret = 0; + switch(cmd){ + case 1: //enable + hyn_66xxdata->prox_is_enable = 1; + hyn_66xxdata->prox_state = 0xAA; + ret = hyn_wr_reg(hyn_66xxdata,0xD004B001,4,NULL,0); + break; + case 0: //disable + hyn_66xxdata->prox_is_enable = 0; + hyn_66xxdata->prox_state = 0xAA; + ret = hyn_wr_reg(hyn_66xxdata,0xD004B000,4,NULL,0); + break; + default: + break; + } + return ret; +} + +static int cst66xx_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0,i; + for(i=0;i<5;i++){ + ret = hyn_wr_reg(hyn_66xxdata,0xD0000400,4,0,0); //disable lp i2c plu + mdelay(1); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000400,4,0,0); + if(ret == 0) + break; + } + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_66xxdata,ENABLE); + hyn_esdcheck_switch(hyn_66xxdata,ENABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000000,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000C00,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000100,4,0,0); + break; + case GESTURE_MODE: + hyn_esdcheck_switch(hyn_66xxdata,ENABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000C01,4,0,0); + break; + case LP_MODE: + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00004AB,4,0,0); + break; + case DIFF_MODE: + case RAWDATA_MODE: + case BASELINE_MODE: + case CALIBRATE_MODE: + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00001AB,4,0,0); //enter debug mode + break; + case FAC_TEST_MODE: + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + cst66xx_rst(); + msleep(50); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00000AB,4,0,0); //enter fac test + msleep(50); //wait switch to fac mode + break; + case DEEPSLEEP: + hyn_irq_set(hyn_66xxdata,DISABLE); + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00022AB,4,0,0); + break; + case ENTER_BOOT_MODE: + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + ret |= cst66xx_enter_boot(); + break; + case GLOVE_EXIT: + case GLOVE_ENTER: + hyn_66xxdata->glove_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_66xxdata,(mode&0x01)? 0xD0000AAB:0xD0000A00,4,0,0); //glove mode + mode = hyn_66xxdata->work_mode; //not switch work mode + HYN_INFO("set_glove:%d",hyn_66xxdata->glove_is_enable); + break; + case CHARGE_EXIT: + case CHARGE_ENTER: + hyn_66xxdata->charge_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_66xxdata,(mode&0x01)? 0xD0000BAB:0xD0000B00,4,0,0); //charg mode + mode = hyn_66xxdata->work_mode; //not switch work mode + HYN_INFO("set_charge:%d",hyn_66xxdata->charge_is_enable); + break; + default : + hyn_esdcheck_switch(hyn_66xxdata,enable); + ret = -2; + break; + } + if(ret != -2){ + hyn_66xxdata->work_mode = mode; + } + HYN_INFO("set_workmode:%d ret:%d",mode,ret); + return ret; +} + + +static int cst66xx_supend(void) +{ + HYN_ENTER(); + cst66xx_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst66xx_resum(void) +{ + HYN_ENTER(); + cst66xx_rst(); + msleep(50); + cst66xx_set_workmode(NOMAL_MODE,1); + return 0; +} + +static void cst66xx_rst(void) +{ + HYN_ENTER(); + if(hyn_66xxdata->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR); + } + gpiod_direction_output(hyn_66xxdata->plat_data.reset_gpio,0); + msleep(8); + gpiod_direction_output(hyn_66xxdata->plat_data.reset_gpio,1); +} + +static int cst66xx_wait_ready(u16 times,u8 ms,u16 reg,u16 check_vlue) +{ + int ret = 0; + u8 buf[4]; + while(times--){ + ret = hyn_wr_reg(hyn_66xxdata,reg,2,buf,2); + if(0==ret && U8TO16(buf[0],buf[1])==check_vlue){ + return 0; + } + mdelay(ms); + } + return -1; +} + +static int cst66xx_enter_boot(void) +{ + int retry = 0,ret = 0; + hyn_set_i2c_addr(hyn_66xxdata,BOOT_I2C_ADDR); + while(++retry<20){ + cst66xx_rst(); + mdelay(12+retry); + ret = hyn_wr_reg(hyn_66xxdata,0xA001A8,3,0,0); + if(ret < 0){ + continue; + } + if(0==cst66xx_wait_ready(10,2,0xA002,0x22DD)){ + return 0; + } + } + return -1; +} + +static int cst66xx_updata_tpinfo(void) +{ + u8 buf[60]; + struct tp_info *ic = &hyn_66xxdata->hw_info; + int ret = 0; + int retry = 5; + while(--retry){ + //get all config info + ret |= cst66xx_set_workmode(NOMAL_MODE,ENABLE); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0030000,0x80|4,buf,50); + if(ret == 0 && buf[3]==0xCA && buf[2]==0xCA) break; + mdelay(1); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0000400,4,buf,0); + } + + if(ret || retry==0){ + HYN_ERROR("cst66xx_updata_tpinfo failed"); + return -1; + } + + ic->fw_sensor_txnum = buf[48]; + ic->fw_sensor_rxnum = buf[49]; + ic->fw_key_num = buf[27]; + ic->fw_res_y = (buf[31]<<8)|buf[30]; + ic->fw_res_x = (buf[29]<<8)|buf[28]; + HYN_INFO("IC_info tx:%d rx:%d key:%d res-x:%d res-y:%d",ic->fw_sensor_txnum,ic->fw_sensor_rxnum,ic->fw_key_num,ic->fw_res_x,ic->fw_res_y); + + ic->fw_project_id = U8TO32(buf[39],buf[38],buf[37],buf[36]); + ic->fw_chip_type = U8TO32(buf[3],buf[2],buf[1],buf[0]); + ic->fw_ver = U8TO32(buf[35],buf[34],buf[33],buf[32]); + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return 0; +} + +static u32 cst66xx_fread_word(u32 addr) +{ + int ret; + u8 rec_buf[4],retry; + u32 read_word = 0; + + retry = 3; + while(retry--){ + ret = hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x06,(addr&0xFF),((addr>>8)&0xFF)),4,NULL,0); //set addr + ret |= hyn_wr_reg(hyn_66xxdata,0xA0080400,4,0,0); //set len + ret |= hyn_wr_reg(hyn_66xxdata,0xA00A0300,4,0,0); //? + ret |= hyn_wr_reg(hyn_66xxdata,0xA004D2,3,NULL,0); //trig read + if(ret ==0) break; + } + if(ret) return 0; + + retry = 20; + while(retry--){ + ret = hyn_wr_reg(hyn_66xxdata,0xA020,2,rec_buf,2); + if(ret==0 && rec_buf[0]==0xD2 && rec_buf[1]==0x88){ + ret |= hyn_wr_reg(hyn_66xxdata,0xA040,2,rec_buf,4); + if(ret ==0){ + read_word = U8TO32(rec_buf[3],rec_buf[2],rec_buf[1],rec_buf[0]); + break; + } + } + mdelay(1); + } + return read_word; +} + +static int read_checksum(u16 start_val,u16 start_addr,u16 len ,u32 *check_sum) +{ + int ret,retry = 3; + u8 buf[8] = {0}; + while(retry--){ + ret = hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x06,start_addr&0xFF,start_addr>>8),4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x08,len&0xFF,len>>8),4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,U8TO32(0xA0,0x0A,start_val&0xFF,start_val>>8),4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xA004D6,3,0,0); + if(ret) continue; + mdelay(len/0xc00 + 1); + ret = cst66xx_wait_ready(20,2,0xA020,0xD688); + ret |= hyn_wr_reg(hyn_66xxdata,0xA040,2,buf,5); + if(ret == 0 && buf[0] == 0xCA){ + *check_sum = U8TO32(buf[4],buf[3],buf[2],buf[1]); + break; + } + else{ + ret = -1; + continue; + } + } + return ret ? -1:0; +} + +static u32 cst66xx_read_checksum(void) +{ + int ret = -1; + u32 chipSum1 = 0,chipSum2 = 0,chipSum3=0,totalSum = 0; + hyn_66xxdata->boot_is_pass = 0; + if(0==read_checksum(0,0,0x9000,&chipSum1)){ + if (0==read_checksum(1,0xb000,0x0ffc,&chipSum2)) { + ret = 0; + if (hyn_66xxdata->fw_updata_len >= 44*1024) + ret =read_checksum(1,0xc000,0x0ffc,&chipSum3); + } + } + if(ret ==0){ + if (hyn_66xxdata->fw_updata_len >= 44*1024) + totalSum = chipSum1 + chipSum2*2 - 0x55 + chipSum3*2 - 0x55; + else + totalSum = chipSum1 + chipSum2*2 - 0x55; + hyn_66xxdata->boot_is_pass = 1; + } + HYN_INFO("chipSum1:%04x chipSum2:%04x chipSum3:%04x totalSum:%04x",chipSum1,chipSum2,chipSum3,totalSum); + return totalSum; +} + +static int cst66xx_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_check_all,f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + u8 *p_data; + int ret; + struct tp_info *ic = &hyn_66xxdata->hw_info; + + p_data = p_fw + (len >= 44*1024 ? 40*1024:35*1024 ); + f_fw_project_id = U8TO32(p_data[39],p_data[38],p_data[37],p_data[36]); + f_ictype = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]); + f_fw_ver = U8TO32(p_data[35],p_data[34],p_data[33],p_data[32]); + + p_data = p_fw + (len >= 44*1024 ? 44*1024:40*1024 ); + f_checksum = U8TO32(p_data[3],p_data[2],p_data[1],p_data[0]); + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%04x checksum:%04x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + + ret = cst66xx_updata_tpinfo(); //boot checksum pass, communicate failed not updata + if(ret) HYN_ERROR("get tpinfo failed"); + + //check h file + f_check_all = hyn_sum32(0x55,(u32*)p_fw,len/4); + if(f_check_all != f_checksum){ + HYN_INFO(".h file checksum erro:%04x len:%d",f_check_all,len); + return 0; //no need updata + } + + if(hyn_66xxdata->boot_is_pass ==0 //boot failed + //|| (ret && hyn_66xxdata->boot_is_pass)//erro fw needupdata + || ( ret == 0 && f_ictype == ic->fw_chip_type && f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver ) // match new ver .h file + ){ + return 1; //need updata + } + return 0; +} + +static int cst66xx_erase_flash(u16 start_addr, u16 len, u16 type) +{ + int ret = 0; + // HYN_INFO("addr:%04x len:%04x",0xA0060000+U16REV(start_addr),0xA0080000+U16REV(len)); + ret = hyn_wr_reg(hyn_66xxdata,0xA0060000+U16REV(start_addr),4,0,0); //addr + ret |= hyn_wr_reg(hyn_66xxdata,0xA0080000+U16REV(len),4,0,0); //len + ret |= hyn_wr_reg(hyn_66xxdata,0xA00A0000+U16REV(type),4,0,0); //type + ret |= hyn_wr_reg(hyn_66xxdata,0xA018CACA,4,0,0); //key + ret |= hyn_wr_reg(hyn_66xxdata,0xA004E0,3,0,0); //trig + if(ret) return -1; + + mdelay(20); //wait finsh earse flash + ret = cst66xx_wait_ready(100,1,0xA020,0xE088); + return ret; +} + +static int cst66xx_updata_fw(u8 *bin_addr, u16 len) +{ + #define PKG_SIZE (1024) + int i,ret = -1, retry_fw= 4,pak_num; + u8 *i2c_buf , *p_bin_addr; + u16 eep_addr = 0, eep_len; + u32 fw_checksum = 0; + HYN_ENTER(); + i2c_buf = kmalloc(PKG_SIZE + 10, GFP_KERNEL); + HYN_INFO("len = %d",len); + hyn_66xxdata->fw_updata_process = 0; + if(len < cst66xx_BIN_SIZE){ + HYN_ERROR("bin len erro"); + goto UPDATA_END; + } + len = cst66xx_BIN_SIZE; + if(0 == hyn_66xxdata->fw_file_name[0]){ + p_bin_addr = bin_addr + len; + fw_checksum = U8TO32(p_bin_addr[3],p_bin_addr[2],p_bin_addr[1],p_bin_addr[0]); + } + else{ + ret = hyn_copy_for_updata(hyn_66xxdata,i2c_buf,cst66xx_BIN_SIZE,4); + if(ret) goto UPDATA_END; + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + } + HYN_INFO("fw_checksum_all:%04x",fw_checksum); + hyn_irq_set(hyn_66xxdata,DISABLE); + hyn_esdcheck_switch(hyn_66xxdata,DISABLE); + pak_num = len/PKG_SIZE; + while(--retry_fw){ + ret = cst66xx_enter_boot(); + if(ret){ + HYN_INFO("cst66xx_enter_boot fail"); + continue; + } + if(cst66xx_erase_flash(0x0000,0x8000,0x02)) continue; //erase 32k 0x0000~0x8000 + if(cst66xx_erase_flash(0x8000,0x1000,0x01)) continue; //erase 4k 0x8000~0x9000 + if(cst66xx_erase_flash(0xB000,0x3000,0x04)) continue; //erase 12k 0xB000~0xE000 + //start trans fw + eep_addr = 0; + eep_len = 0; + // p_bin_addr = bin_addr; + for (i=0; i>8),4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xA0080004,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,i>=36 ? 0xA00A0300:0xA00A0000,4,0,0); + ret |= hyn_wr_reg(hyn_66xxdata,0xA018CACA,4,0,0); + if(ret) continue; + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x40; + if(0 == hyn_66xxdata->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr+eep_len, PKG_SIZE); + }else{ + ret |= hyn_copy_for_updata(hyn_66xxdata,i2c_buf + 2,eep_len,PKG_SIZE); + } + ret |= hyn_write_data(hyn_66xxdata, i2c_buf,2, PKG_SIZE+2); + msleep(5); + ret |= hyn_wr_reg(hyn_66xxdata, 0xA004E1, 3,0,0); + + eep_len += PKG_SIZE; + eep_addr += PKG_SIZE; + if(0x9000 == eep_addr){ + eep_addr = 0xB000; + } + mdelay(20); //wait finsh + cst66xx_wait_ready(100,1,0xA020,0xE188); + hyn_66xxdata->fw_updata_process = i*100/pak_num; + // HYN_INFO("FB_%d",hyn_66xxdata->fw_updata_process); + } + if(ret) continue; + hyn_66xxdata->hw_info.ic_fw_checksum = cst66xx_read_checksum(); + if(fw_checksum == hyn_66xxdata->hw_info.ic_fw_checksum && 0 != hyn_66xxdata->boot_is_pass){ + break; + } + else{ + ret = -2; + } + } +UPDATA_END: + hyn_set_i2c_addr(hyn_66xxdata,MAIN_I2C_ADDR); + cst66xx_rst(); + if(ret == 0){ + msleep(50); + cst66xx_updata_tpinfo(); + hyn_66xxdata->fw_updata_process = 100; + HYN_INFO("updata_fw success"); + } + else{ + hyn_66xxdata->fw_updata_process |= 0x80; + HYN_ERROR("updata_fw failed fw_checksum:%#x ic_checksum:%#x",fw_checksum,hyn_66xxdata->hw_info.ic_fw_checksum); + } + hyn_irq_set(hyn_66xxdata,ENABLE); + + kfree(i2c_buf); + return ret; +} + +static u32 cst66xx_check_esd(void) +{ + int ok = 0; + u8 i2c_buf[6], retry; + u32 esd_value = 0; + + retry = 4; + while (retry--){ + hyn_wr_reg(hyn_66xxdata,0xD0000D00,4,i2c_buf,0); + udelay(200); + ok = hyn_wr_reg(hyn_66xxdata,0xD0000D00,4,i2c_buf,1); + if((i2c_buf[0] == 0x20 || i2c_buf[0]==0xA0 || i2c_buf[0]==0xA5)&& ok==0){ + break; + } + else{ + ok = -2; + } + msleep(1); + } + if(-2==ok){ //esdcheck failed rest system + hyn_66xxdata->esd_fail_cnt = 3; + esd_value = hyn_66xxdata->esd_last_value; + } + else if(i2c_buf[0]==0xA5){ //old sdk (V4.5) + ok = hyn_wr_reg(hyn_66xxdata,0xD0040400,4,i2c_buf,4); + if(ok){ + mdelay(1); + ok = hyn_wr_reg(hyn_66xxdata,0xD0040400,4,i2c_buf,4); + } + esd_value = ok==0 ? U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]):hyn_66xxdata->esd_last_value; + } + else{ + esd_value = hyn_66xxdata->esd_last_value+1; + } + return esd_value; +} + +static int red_dbg_data(u8 *buf, u16 len ,u32 *cmd_list,u8 type) +{ + struct tp_info *ic = &hyn_66xxdata->hw_info; + int ret = 0; + u16 read_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum)*type; + u16 total_len = (ic->fw_sensor_rxnum*ic->fw_sensor_txnum + ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*type; + if(total_len > len || read_len == 0){ + HYN_ERROR("buf too small or fw_sensor_rxnum fw_sensor_txnum erro"); + return -1; + } + ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //m cap + buf += read_len; + read_len = ic->fw_sensor_rxnum*type; + ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //s rx cap + buf += read_len; + read_len = ic->fw_sensor_txnum*type; + ret |= hyn_wr_reg(hyn_66xxdata,*cmd_list++,0x80|4,buf,read_len); //s tx cap + // ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); //end + return ret < 0 ? -1:total_len; +} + +static int cst66xx_get_dbg_data(u8 *buf, u16 len) +{ + int read_len = -1,ret = 0; + HYN_ENTER(); + switch(hyn_66xxdata->work_mode){ + case DIFF_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD0120000,0xD01A0000,0xD0160000},2); + break; + case RAWDATA_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD0110000,0xD0190000,0xD0150000},2); + break; + case BASELINE_MODE: + read_len = red_dbg_data(buf,len,(u32[]){0xD0130000,0xD01B0000,0xD0170000},2); + break; + case CALIBRATE_MODE:{ + u16 tmp_len = len/2; + len /= 2; + read_len = red_dbg_data(buf+tmp_len,tmp_len,(u32[]){0xD0140000,0xD0180000,0xD01c0000},1); + if(read_len > 0){ + u8 *src_ptr = buf+tmp_len,tmp; + s16 *des_ptr = (s16*)buf; + tmp_len = read_len; + while(tmp_len--){ + tmp = (*src_ptr++)&0x7F; + *des_ptr++ = (tmp & 0x40) ? -(tmp&0x3F):tmp; + } + read_len *= 2; + } + break; + } + default: + HYN_ERROR("work_mode:%d",hyn_66xxdata->work_mode); + break; + } + // HYN_INFO("read_len:%d len:%d",(int)(sizeof(struct ts_frame)+read_len),len); + if(read_len > 0 && len > (sizeof(struct ts_frame)+read_len)){ + ret = cst66xx_report(); + if(ret ==0){ + memcpy(buf+read_len+4,(void*)&hyn_66xxdata->rp_buf,sizeof(struct ts_frame)); + read_len += sizeof(struct ts_frame); + } + } + else{ + hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); //end + } + return read_len; +} + +static int get_fac_test_data(u32 cmd ,u8 *buf, u16 len ,u8 rev) +{ + int ret = 0; + ret = hyn_wr_reg(hyn_66xxdata,cmd,4,0,0); + ret |= hyn_wait_irq_timeout(hyn_66xxdata,100); + ret |= hyn_wr_reg(hyn_66xxdata,0xD0120000,0x80|4,buf+rev,len); + ret |= hyn_wr_reg(hyn_66xxdata,0xD00002AB,4,0,0); + if(ret==0 && rev){ + len /= 2; + while(len--){ + *buf = *(buf+2); + buf += 2; + } + } + return ret; +} + +#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini" +#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log" +#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST|MULTI_SCAP_TEST) + +static int cst66xx_get_test_result(u8 *buf, u16 len) +{ + struct tp_info *ic = &hyn_66xxdata->hw_info; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2; + u16 st_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2; + u8 *rbuf = buf; + int ret = FAC_GET_DATA_FAIL; + HYN_ENTER(); + if((mt_len*3 + st_len*2 + 4) > len || mt_len==0){ + HYN_ERROR("%s", mt_len ? "buf too small":" ic->fw_sensor_rxnum*ic->fw_sensor_txnum=0"); + return FAC_GET_DATA_FAIL; + } + if(get_fac_test_data(0xD0002000,rbuf,mt_len,0)){ //read open high data + HYN_ERROR("read open high failed"); + goto TEST_ERRO; + } + rbuf += mt_len; + if(get_fac_test_data(0xD0002100,rbuf,mt_len,0)){ //read open low data + HYN_ERROR("read open low failed"); + goto TEST_ERRO; + } + rbuf += mt_len; + if(get_fac_test_data(0xD0002300,rbuf,st_len,1)){ //read short test data + HYN_ERROR("read fac short failed"); + goto TEST_ERRO; + } + //must rest + rbuf += st_len; + if(get_fac_test_data(0xD0002500,rbuf,st_len,0)){ ///read scap test data + HYN_ERROR("read scap failed"); + goto TEST_ERRO; + } + ////read data finlish start test + ret = hyn_factory_multitest(hyn_66xxdata ,FACTEST_PATH, buf,(s16*)(rbuf+st_len),FACTEST_ITEM); + +TEST_ERRO: + if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_66xxdata,(s16*)buf,ret,FACTEST_ITEM)){ + HYN_INFO("fac_test log save success"); + } + cst66xx_resum(); + return ret; +} + + +const struct hyn_ts_fuc hyn_cst66xx_fuc = { + .tp_rest = cst66xx_rst, + .tp_report = cst66xx_report, + .tp_supend = cst66xx_supend, + .tp_resum = cst66xx_resum, + .tp_chip_init = cst66xx_init, + .tp_updata_fw = cst66xx_updata_fw, + .tp_set_workmode = cst66xx_set_workmode, + .tp_check_esd = cst66xx_check_esd, + .tp_prox_handle = cst66xx_prox_handle, + .tp_get_dbg_data = cst66xx_get_dbg_data, + .tp_get_test_result = cst66xx_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst7xx.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst7xx.c new file mode 100644 index 000000000000..adf0d68724d5 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst7xx.c @@ -0,0 +1,544 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst7xx.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst7xx_fw.h" + +#define CUSTOM_SENSOR_NUM (20) + +#define BOOT_I2C_ADDR (0x6A) +#define MAIN_I2C_ADDR (0x15) +#define RW_REG_LEN (2) +#define CST7XX_BIN_SIZE (15*1024) +static struct hyn_ts_data *hyn_7xxdata = NULL; + +static int cst7xx_updata_judge(u8 *p_fw, u16 len); +static u32 cst7xx_read_checksum(void); +static int cst7xx_updata_tpinfo(void); +static int cst7xx_enter_boot(void); +static int cst7xx_set_workmode(enum work_mode mode,u8 enable); +static void cst7xx_rst(void); + +static int cst7xx_init(struct hyn_ts_data* ts_data) +{ + int ret = 0; + u8 buf[4]; + HYN_ENTER(); + hyn_7xxdata = ts_data; + ret = cst7xx_enter_boot(); + if(ret == FALSE){ + HYN_ERROR("cst7xx_enter_boot failed"); + return FALSE; + } + hyn_7xxdata->fw_updata_addr = (u8*)fw_bin; + hyn_7xxdata->fw_updata_len = CST7XX_BIN_SIZE; + + hyn_7xxdata->hw_info.ic_fw_checksum = cst7xx_read_checksum(); + + hyn_wr_reg(hyn_7xxdata,0xA006EE,3,buf,0); //exit boot + cst7xx_rst(); + mdelay(50); + hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR); + cst7xx_updata_tpinfo(); + cst7xx_set_workmode(NOMAL_MODE,0); + hyn_7xxdata->need_updata_fw = cst7xx_updata_judge((u8*)fw_bin,CST7XX_BIN_SIZE); + + if(hyn_7xxdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + return TRUE; +} + + +static int cst7xx_enter_boot(void) +{ + uint8_t t; + hyn_set_i2c_addr(hyn_7xxdata,BOOT_I2C_ADDR); + for (t = 5;; t += 2) + { + int ok = FALSE; + uint8_t i2c_buf[4] = {0}; + + if (t >= 15){ + return FALSE; + } + cst7xx_rst(); + mdelay(t); + ok = hyn_wr_reg(hyn_7xxdata, 0xA001AA, 3, i2c_buf, 0); + if(ok == FALSE){ + continue; + } + ok = hyn_wr_reg(hyn_7xxdata, 0xA003, 2, i2c_buf, 1); + if(ok == FALSE){ + continue; + } + if (i2c_buf[0] != 0x55){ + continue; + } + break; + } + return TRUE; +} + + +static int write_code(u8 *bin_addr,uint8_t retry) +{ + uint16_t i,t;//,j; + int ok = FALSE; + u8 i2c_buf[512+2]; + + bin_addr+=6; + hyn_7xxdata->fw_updata_process = 0; + for ( i = 0;i < CST7XX_BIN_SIZE; i += 512) + { + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x14; + + i2c_buf[2] = i; + i2c_buf[3] = i >> 8; + ok = hyn_write_data(hyn_7xxdata, i2c_buf,RW_REG_LEN, 4); + if (ok == FALSE){ + break; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + if(0 == hyn_7xxdata->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr + i, 512); + } + else{ + ok = hyn_copy_for_updata(hyn_7xxdata,i2c_buf + 2,i+6,512); + if(ok)break; + } + ok = hyn_write_data(hyn_7xxdata, i2c_buf,RW_REG_LEN, 514); + if (ok == FALSE){ + break; + } + + ok = hyn_wr_reg(hyn_7xxdata, 0xA004EE, 3,i2c_buf,0); + if (ok == FALSE){ + break; + } + + mdelay(100 * retry); + hyn_7xxdata->fw_updata_process = i*100/CST7XX_BIN_SIZE; + for (t = 0;; t ++) + { + if (t >= 50){ + return FALSE; + } + mdelay(5); + + ok = hyn_wr_reg(hyn_7xxdata,0xA005,2,i2c_buf,1); + if (ok == FALSE){ + continue; + } + if (i2c_buf[0] != 0x55){ + continue; + } + break; + } + } + return ok; +} + + +static uint32_t cst7xx_read_checksum(void) +{ + int ret = -1,time_out,retry = 3; + uint8_t i2c_buf[4] = {0}; + uint32_t value = 0; + hyn_7xxdata->boot_is_pass = 0; + while(retry--){ + ret = hyn_wr_reg(hyn_7xxdata, 0xA00300, 3, i2c_buf, 0); + if(ret) continue; + mdelay(100); + time_out = 100; + while(time_out--){ + mdelay(10); + ret = hyn_wr_reg(hyn_7xxdata, 0xA000, 2, i2c_buf, 1); + if(0==ret && i2c_buf[0] == 1){ + hyn_7xxdata->boot_is_pass = 1; + break; + } + ret = -2; + } + if(ret) continue; + ret = hyn_wr_reg(hyn_7xxdata, 0xA008, 2, i2c_buf, 2); + if(ret == 0){ + value = (i2c_buf[1]<<8)|i2c_buf[0]; + break; + } + } + return value; +} + + + +static int cst7xx_updata_fw(u8 *bin_addr, u16 len) +{ + int retry = 0; + int ok = FALSE,ret = 0; + u8 i2c_buf[4]; + u32 fw_checksum = 0; + // len = len; + HYN_ENTER(); + if(0 == hyn_7xxdata->fw_file_name[0]){ + fw_checksum =U8TO16(bin_addr[5],bin_addr[4]); + } + else{ + ok = hyn_copy_for_updata(hyn_7xxdata,i2c_buf,4,2); + if(ok) goto UPDATA_END; + fw_checksum = U8TO16(i2c_buf[1],i2c_buf[0]); + } + + hyn_irq_set(hyn_7xxdata,DISABLE); + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + + for(retry = 1; retry<10; retry++){ + ret = -1; + ok = cst7xx_enter_boot(); + if (ok == FALSE){ + continue; + } + ok = write_code(bin_addr,retry); + if (ok == FALSE){ + continue; + } + hyn_7xxdata->hw_info.ic_fw_checksum = cst7xx_read_checksum(); + if(fw_checksum != hyn_7xxdata->hw_info.ic_fw_checksum && hyn_7xxdata->boot_is_pass){ + hyn_7xxdata->fw_updata_process |= 0x80; + continue; + } + hyn_7xxdata->fw_updata_process = 100; + ret = 0; + break; + } +UPDATA_END: + hyn_wr_reg(hyn_7xxdata,0xA006EE,3,i2c_buf,0); //exit boot + mdelay(2); + cst7xx_rst(); + mdelay(50); + + hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR); + HYN_INFO("updata_fw %s",ret == 0 ? "success" : "failed"); + if(ret == 0){ + cst7xx_updata_tpinfo(); + } + hyn_irq_set(hyn_7xxdata,ENABLE); + hyn_esdcheck_switch(hyn_7xxdata,ENABLE); + return ret; +} + + +static int cst7xx_updata_tpinfo(void) +{ + u8 buf[8]; + struct tp_info *ic = &hyn_7xxdata->hw_info; + int ret = 0; + + ret = hyn_wr_reg(hyn_7xxdata,0xA6,1,buf,6); + if(ret == FALSE){ + HYN_ERROR("cst7xx_updata_tpinfo failed"); + return FALSE; + } + + ic->fw_sensor_txnum = 2; + ic->fw_sensor_rxnum = CUSTOM_SENSOR_NUM; + ic->fw_key_num = hyn_7xxdata->plat_data.key_num; + ic->fw_res_y = hyn_7xxdata->plat_data.y_resolution; + ic->fw_res_x = hyn_7xxdata->plat_data.x_resolution; + ic->fw_project_id = buf[3]; + ic->fw_chip_type = buf[4]; + ic->fw_ver = buf[0]; + + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return TRUE; +} + +static int cst7xx_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_checksum,f_fw_ver,f_ictype,f_project_id;//f_module_id; + u8 *p_data = p_fw ; + u16 i,check_h =0x55; + struct tp_info *ic = &hyn_7xxdata->hw_info; + + f_checksum = U8TO16(p_data[5],p_data[4]); + p_data += (0x3BF8+6); + f_project_id = p_data[2]; + f_ictype = (p_data[1]<<8)|p_data[0]; + f_fw_ver = (p_data[5]<<8)|p_data[4]; + // f_module_id = p_data[3]; + + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_project_id,f_ictype,f_fw_ver,f_checksum); + + p_data = p_fw+6; + for(i=0;i>15; + check_h <<= 1; + check_h |= tmp; + } + if(check_h != f_checksum){ + HYN_ERROR(".h file is damaged !! check_h:0x%04x f_checksum:0x%04x",check_h,f_checksum); + return 0; + } + + if(hyn_7xxdata->boot_is_pass==0 //emty + || (ic->fw_ver <= f_fw_ver && ic->fw_project_id ==f_project_id && f_checksum != ic->ic_fw_checksum) + ){ + return 1; //need updata + } + return 0; +} + +//------------------------------------------------------------------------------// +static int cst7xx_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = -1; + switch(mode){ + case NOMAL_MODE: + hyn_esdcheck_switch(hyn_7xxdata,ENABLE); + hyn_irq_set(hyn_7xxdata,ENABLE); + ret = hyn_wr_reg(hyn_7xxdata,0xFE00,2,NULL,0); + break; + case GESTURE_MODE: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + ret = hyn_wr_reg(hyn_7xxdata,0xD001,2,NULL,0); + break; + case LP_MODE: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + break; + case DIFF_MODE: + case RAWDATA_MODE: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + ret = hyn_wr_reg(hyn_7xxdata,mode==DIFF_MODE ? 0xBF07:0xBF06,2,NULL,0); + break; + case FAC_TEST_MODE: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + hyn_wr_reg(hyn_7xxdata,0xF001,2,NULL,0); + msleep(50); + break; + case DEEPSLEEP: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + hyn_irq_set(hyn_7xxdata,DISABLE); + ret = hyn_wr_reg(hyn_7xxdata,0xA503,2,NULL,0); + break; + case ENTER_BOOT_MODE: + hyn_esdcheck_switch(hyn_7xxdata,DISABLE); + ret |= cst7xx_enter_boot(); + break; + case CHARGE_EXIT: + case CHARGE_ENTER: + hyn_7xxdata->charge_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_7xxdata,(mode&0x01)? 0xE601:0xE600,2,0,0); //charg mode + mode = hyn_7xxdata->work_mode; //not switch work mode + break; + default : + hyn_esdcheck_switch(hyn_7xxdata,enable); + hyn_7xxdata->work_mode = NOMAL_MODE; + ret = -2; + break; + } + if(ret != -2){ + hyn_7xxdata->work_mode = mode; + } + return ret; +} + +static int cst7xx_prox_handle(u8 cmd) +{ + int ret = 0; + switch(cmd){ + case 1: //enable + hyn_7xxdata->prox_is_enable = 1; + hyn_7xxdata->prox_state = 0; + ret = hyn_wr_reg(hyn_7xxdata,0xB001,2,NULL,0); + break; + case 0: //disable + hyn_7xxdata->prox_is_enable = 0; + hyn_7xxdata->prox_state = 0; + ret = hyn_wr_reg(hyn_7xxdata,0xB000,2,NULL,0); + break; + default: + break; + } + return ret; +} + +static void cst7xx_rst(void) +{ + if(hyn_7xxdata->work_mode==ENTER_BOOT_MODE){ + hyn_set_i2c_addr(hyn_7xxdata,MAIN_I2C_ADDR); + } + gpiod_direction_output(hyn_7xxdata->plat_data.reset_gpio,0); + msleep(10); + gpiod_direction_output(hyn_7xxdata->plat_data.reset_gpio,1); +} + + + +static int cst7xx_supend(void) +{ + HYN_ENTER(); + cst7xx_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst7xx_resum(void) +{ + cst7xx_rst(); + msleep(50); + cst7xx_set_workmode(NOMAL_MODE,0); + return 0; +} + +static int cst7xx_report(void) +{ + uint8_t i = 0; + uint8_t i2c_buf[3+6*MAX_POINTS_REPORT] = {0}; + uint8_t id = 0,index = 0; + struct hyn_plat_data *dt = &hyn_7xxdata->plat_data; + + memset(&hyn_7xxdata->rp_buf,0,sizeof(hyn_7xxdata->rp_buf)); + hyn_7xxdata->rp_buf.report_need = REPORT_NONE; + + + if(hyn_7xxdata->work_mode == GESTURE_MODE){ + static const uint8_t ges_map[][2] = {{0x24,IDX_POWER},{0x22,IDX_UP},{0x23,IDX_DOWN},{0x20,IDX_LEFT},{0x21,IDX_RIGHT}, + {0x34,IDX_C},{0x33,IDX_e},{0x32,IDX_M},{0x30,IDX_O},{0x46,IDX_S},{0x54,IDX_V},{0x31,IDX_W},{0x65,IDX_Z}}; + if(hyn_wr_reg(hyn_7xxdata,0xD3,1,i2c_buf,1)){ + goto FAILD_END; + } + index = sizeof(ges_map)/2; + hyn_7xxdata->gesture_id = IDX_NULL; + for(i=0; igesture_id = ges_map[i][1]; + hyn_7xxdata->rp_buf.report_need = REPORT_GES; + break; + } + } + return TRUE; + } + else{ + int ret = -1,retry = 3; + u8 event = 0; + while(--retry){ + ret = hyn_wr_reg(hyn_7xxdata,0x00,1,i2c_buf,(3+6*2)); + if(ret == 0 && i2c_buf[2] < 3) break; + ret = -1; + } + if(ret){ + goto FAILD_END; + } + if(hyn_7xxdata->prox_is_enable){ + u8 state=0; + if(i2c_buf[1]==0xE0 || i2c_buf[1]==0){ + state = PS_FAR_AWAY; + } + else if(i2c_buf[1]==0xC0){ + state = PS_NEAR; + } + if(hyn_7xxdata->prox_state != state){ + hyn_7xxdata->prox_state = state; + hyn_7xxdata->rp_buf.report_need |= REPORT_PROX; + } + } + hyn_7xxdata->rp_buf.rep_num = i2c_buf[2]&0x0F; + for(i = 0 ; i < 2 ; i++){ + id = (i2c_buf[5 + i*6] & 0xf0)>>4; + event = i2c_buf[3 + i*6]&0xC0; + if(id > 1 || event==0xC0) continue; + hyn_7xxdata->rp_buf.pos_info[index].pos_id = id; + hyn_7xxdata->rp_buf.pos_info[index].event = 0x40 == event ? 0:1; + hyn_7xxdata->rp_buf.pos_info[index].pos_x = ((u16)(i2c_buf[3 + i*6] & 0x0f)<<8) + i2c_buf[4 + i*6]; + hyn_7xxdata->rp_buf.pos_info[index].pos_y = ((u16)(i2c_buf[5 + i*6] & 0x0f)<<8) + i2c_buf[6 + i*6]; + // hyn_7xxdata->rp_buf.pos_info[index].pres_z = (i2c_buf[7 + i*6] <<8) + i2c_buf[8 + i*6] ; + hyn_7xxdata->rp_buf.pos_info[index].pres_z = 3+(hyn_7xxdata->rp_buf.pos_info[index].pos_x&0x03); //press mast chang + index++; + } + if(index){ + hyn_7xxdata->rp_buf.report_need |= REPORT_POS; + } + + if(dt->key_num){ + i = dt->key_num; + while(i){ + i--; + if(dt->key_y_coords ==hyn_7xxdata->rp_buf.pos_info[0].pos_y && dt->key_x_coords[i] == hyn_7xxdata->rp_buf.pos_info[0].pos_x){ + hyn_7xxdata->rp_buf.key_id = i; + hyn_7xxdata->rp_buf.key_state = hyn_7xxdata->rp_buf.pos_info[0].event; + hyn_7xxdata->rp_buf.report_need = REPORT_KEY; + } + } + } + } + return TRUE; + FAILD_END: + HYN_ERROR("read report data failed"); + return FALSE; +} + +static u32 cst7xx_check_esd(void) +{ + int ret = -1; + u8 buf[4]; + ret = hyn_wr_reg(hyn_7xxdata,0xAE,1,buf,2); + return ret ? -1:U8TO16(buf[1],buf[0]); +} + + + +static int cst7xx_get_dbg_data(u8 *buf, u16 len) +{ + int ret = -1,read_len = len; + switch (hyn_7xxdata->work_mode){ + case DIFF_MODE: + ret = hyn_wr_reg(hyn_7xxdata, 0x41, 1,buf,read_len); + break; + case RAWDATA_MODE: + ret = hyn_wr_reg(hyn_7xxdata, 0x61, 1,buf,read_len); + break; + default: + HYN_ERROR("work_mode:%d",hyn_7xxdata->work_mode); + break; + } + return ret==0 ? read_len:-1; +} + + +static int cst7xx_get_test_result(u8 *buf, u16 len) +{ + return 0; +} + + + +const struct hyn_ts_fuc hyn_cst7xx_fuc = { + .tp_rest = cst7xx_rst, + .tp_report = cst7xx_report, + .tp_supend = cst7xx_supend, + .tp_resum = cst7xx_resum, + .tp_chip_init = cst7xx_init, + .tp_updata_fw = cst7xx_updata_fw, + .tp_set_workmode = cst7xx_set_workmode, + .tp_check_esd = cst7xx_check_esd, + .tp_prox_handle = cst7xx_prox_handle, + .tp_get_dbg_data = cst7xx_get_dbg_data, + .tp_get_test_result = cst7xx_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst8xxT.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst8xxT.c new file mode 100644 index 000000000000..f6eb15f33e72 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst8xxT.c @@ -0,0 +1,518 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst8xxT.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst8xxT_fw.h" + + +#define CUSTOM_SENSOR_NUM (10) + +#define BOOT_I2C_ADDR (0x6A) +#define MAIN_I2C_ADDR (0x15) +#define RW_REG_LEN (2) + +#define CST8xxT_BIN_SIZE (15*1024) +static struct hyn_ts_data *hyn_8xxTdata = NULL; + +static int cst8xxT_updata_judge(u8 *p_fw, u16 len); +static u32 cst8xxT_read_checksum(void); +static int cst8xxT_updata_tpinfo(void); +static int cst8xxT_enter_boot(void); +static int cst8xxT_set_workmode(enum work_mode mode,u8 enable); +static void cst8xxT_rst(void); + +static int cst8xxT_init(struct hyn_ts_data* ts_data) +{ + int ret = 0; + u8 buf[4]; + HYN_ENTER(); + hyn_8xxTdata = ts_data; + ret = cst8xxT_enter_boot(); + if(ret == FALSE){ + HYN_ERROR("cst8xxT_enter_boot failed"); + return FALSE; + } + hyn_8xxTdata->fw_updata_addr = (u8*)fw_bin; + hyn_8xxTdata->fw_updata_len = CST8xxT_BIN_SIZE; + + hyn_8xxTdata->hw_info.ic_fw_checksum = cst8xxT_read_checksum(); + if(hyn_8xxTdata->need_updata_fw ==0){ + hyn_wr_reg(hyn_8xxTdata,0xA006EE,3,buf,0); //exit boot + cst8xxT_rst(); + mdelay(50); + hyn_set_i2c_addr(hyn_8xxTdata,MAIN_I2C_ADDR); + cst8xxT_updata_tpinfo(); + cst8xxT_set_workmode(NOMAL_MODE,0); + hyn_8xxTdata->need_updata_fw = cst8xxT_updata_judge((u8*)fw_bin,CST8xxT_BIN_SIZE); + } + if(hyn_8xxTdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + return TRUE; +} + + +static int cst8xxT_enter_boot(void) +{ + uint8_t t; + hyn_set_i2c_addr(hyn_8xxTdata,BOOT_I2C_ADDR); + for (t = 5;; t += 2) + { + int ok = FALSE; + uint8_t i2c_buf[4] = {0}; + + if (t >= 15){ + return FALSE; + } + + cst8xxT_rst(); + mdelay(t); + + ok = hyn_wr_reg(hyn_8xxTdata, 0xA001AB, 3, i2c_buf, 0); + if(ok == FALSE){ + continue; + } + + ok = hyn_wr_reg(hyn_8xxTdata, 0xA003, 2, i2c_buf, 1); + if(ok == FALSE){ + continue; + } + + if (i2c_buf[0] != 0xC1){ + continue; + } + break; + } + return TRUE; +} + + +static int write_code(u8 *bin_addr,uint8_t retry) +{ + uint16_t i,t;//,j; + int ok = FALSE; + u8 i2c_buf[512+2]; + + bin_addr+=6; + + for ( i = 0;i < CST8xxT_BIN_SIZE; i += 512) + { + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x14; + i2c_buf[2] = i; + i2c_buf[3] = i >> 8; + ok = hyn_write_data(hyn_8xxTdata, i2c_buf,RW_REG_LEN, 4); + if (ok == FALSE){ + break; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + if(0 == hyn_8xxTdata->fw_file_name[0]){ + memcpy(i2c_buf + 2, bin_addr + i, 512); + } + else{ + ok = hyn_copy_for_updata(hyn_8xxTdata,i2c_buf + 2,i+6,512); + if(ok)break; + } + ok = hyn_write_data(hyn_8xxTdata, i2c_buf,RW_REG_LEN, 514); + if (ok == FALSE){ + break; + } + + ok = hyn_wr_reg(hyn_8xxTdata, 0xA004EE, 3,i2c_buf,0); + if (ok == FALSE){ + break; + } + + mdelay(100 * retry); + + for (t = 0;; t ++) + { + if (t >= 50){ + return FALSE; + } + mdelay(5); + + ok = hyn_wr_reg(hyn_8xxTdata,0xA005,2,i2c_buf,1); + if (ok == FALSE){ + continue; + } + if (i2c_buf[0] != 0x55){ + continue; + } + break; + } + } + return ok; +} + + +static uint32_t cst8xxT_read_checksum(void) +{ + int ok = FALSE,t; + uint8_t i2c_buf[4] = {0}; + uint32_t value = 0; + int chip_checksum_ok = FALSE; + // firmware checksum + ok = hyn_wr_reg(hyn_8xxTdata, 0xA00300, 3, i2c_buf, 0); + if (ok == FALSE){ + return value; + } + + mdelay(100); + + for (t = 0;; t += 10) + { + if (t >= 1000){ + //return FALSE; + break; + } + + mdelay(10); + + ok = hyn_wr_reg(hyn_8xxTdata, 0xA000, 2, i2c_buf, 1); + if (ok == FALSE){ + continue; + } + + if (i2c_buf[0] == 1){ + chip_checksum_ok = TRUE; + break; + } + else if (i2c_buf[0] == 2){ + chip_checksum_ok = FALSE; + continue; + } + } + + if(chip_checksum_ok == FALSE){ + hyn_8xxTdata->need_updata_fw = 1; + } + else{ + ok = hyn_wr_reg(hyn_8xxTdata, 0xA008, 2, i2c_buf, 2); + if (ok == FALSE){ + //return FALSE; + return value; + } + value = i2c_buf[0]; + value |= (uint16_t)(i2c_buf[1]) << 8; + } + + return value; +} + + +static int cst8xxT_updata_fw(u8 *bin_addr, u16 len) +{ + int retry = 0; + int ok_copy = TRUE; + int ok = FALSE; + u8 i2c_buf[4]; + u32 fw_checksum = 0; + // len = len; + HYN_ENTER(); + if(0 == hyn_8xxTdata->fw_file_name[0]){ + fw_checksum =U8TO16(bin_addr[5],bin_addr[4]); + } + else{ + ok = hyn_copy_for_updata(hyn_8xxTdata,i2c_buf,4,2); + if(ok) goto UPDATA_END; + fw_checksum = U8TO16(i2c_buf[1],i2c_buf[0]); + } + hyn_irq_set(hyn_8xxTdata,DISABLE); + + for(retry = 1; retry<10; retry++){ + ok = cst8xxT_enter_boot(); + if (ok == FALSE){ + continue; + } + + ok = write_code(bin_addr,retry); + if (ok == FALSE){ + continue; + } + + hyn_8xxTdata->hw_info.ic_fw_checksum = cst8xxT_read_checksum(); + if(fw_checksum != hyn_8xxTdata->hw_info.ic_fw_checksum){ + continue; + } + + if(retry>=5){ + ok_copy = FALSE; + break; + } + break; + } + UPDATA_END: + hyn_wr_reg(hyn_8xxTdata,0xA006EE,3,i2c_buf,0); //exit boot + mdelay(2); + cst8xxT_rst(); + mdelay(50); + + hyn_set_i2c_addr(hyn_8xxTdata,MAIN_I2C_ADDR); + if(ok_copy == TRUE){ + cst8xxT_updata_tpinfo(); + HYN_INFO("updata_fw success"); + } + else{ + HYN_ERROR("updata_fw failed"); + } + + hyn_irq_set(hyn_8xxTdata,ENABLE); + + return ok_copy; +} + + + + +static int cst8xxT_updata_tpinfo(void) +{ + u8 buf[8]; + struct tp_info *ic = &hyn_8xxTdata->hw_info; + int ret = 0; + + ret = hyn_wr_reg(hyn_8xxTdata,0xA7,1,buf,4); + if(ret == FALSE){ + HYN_ERROR("cst8xxT_updata_tpinfo failed"); + return FALSE; + } + + ic->fw_sensor_txnum = 2; + ic->fw_sensor_rxnum = CUSTOM_SENSOR_NUM; + ic->fw_key_num = hyn_8xxTdata->plat_data.key_num; + ic->fw_res_y = hyn_8xxTdata->plat_data.y_resolution; + ic->fw_res_x = hyn_8xxTdata->plat_data.x_resolution; + ic->fw_project_id = buf[1]; + ic->fw_chip_type = buf[0]; + ic->fw_ver = buf[2]; + + HYN_INFO("IC_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + return TRUE; +} + +static int cst8xxT_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + u8 *p_data = p_fw ; + struct tp_info *ic = &hyn_8xxTdata->hw_info; + + f_checksum = U8TO16(p_data[5],p_data[4]); + + p_data = p_fw + 6 + CST8xxT_BIN_SIZE - 1 - 15 ; + + f_ictype = p_data[0]; + f_fw_project_id = (p_data[1]<<24) + (p_data[2]<<16) + (p_data[3]<<8) + (p_data[4]<<0); + f_fw_ver = p_data[5]; + + HYN_INFO("Bin_info fw_project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + + if(f_checksum != ic->ic_fw_checksum && f_fw_ver >= ic->fw_ver){ + return 1; //need updata + } + return 0; +} + +//------------------------------------------------------------------------------// + +static int cst8xxT_set_workmode(enum work_mode mode,u8 enable) +{ + int ret = 0; + if(hyn_wr_reg(hyn_8xxTdata,0x00,1,NULL,0)){ //check_lp mode + cst8xxT_rst(); + mdelay(80); + } + switch(mode){ + case NOMAL_MODE: + hyn_esdcheck_switch(hyn_8xxTdata,ENABLE); + hyn_irq_set(hyn_8xxTdata,ENABLE); + break; + case GESTURE_MODE: + hyn_esdcheck_switch(hyn_8xxTdata,DISABLE); + ret = hyn_wr_reg(hyn_8xxTdata,0xE501,2,NULL,0); + break; + case LP_MODE: + break; + case DIFF_MODE: + case RAWDATA_MODE: + hyn_esdcheck_switch(hyn_8xxTdata,DISABLE); + ret = hyn_wr_reg(hyn_8xxTdata,0xFEF8,2,NULL,0); + break; + case FAC_TEST_MODE: + hyn_esdcheck_switch(hyn_8xxTdata,DISABLE); + //hyn_wr_reg(hyn_8xxTdata,0xD119,2,NULL,0); + break; + case DEEPSLEEP: + hyn_esdcheck_switch(hyn_8xxTdata,DISABLE); + hyn_irq_set(hyn_8xxTdata,DISABLE); + ret = hyn_wr_reg(hyn_8xxTdata,0xE503,2,NULL,0); + break; + case CHARGE_EXIT: + case CHARGE_ENTER: + hyn_8xxTdata->charge_is_enable = mode&0x01; + ret = hyn_wr_reg(hyn_8xxTdata,(mode&0x01)? 0xE601:0xE600,2,0,0); //charg mode + mode = hyn_8xxTdata->work_mode; //not switch work mode + HYN_INFO("set_charge:%d",hyn_8xxTdata->charge_is_enable); + break; + default : + ret = -2; + hyn_esdcheck_switch(hyn_8xxTdata,enable); + hyn_8xxTdata->work_mode = NOMAL_MODE; + break; + } + if(ret != -2){ + hyn_8xxTdata->work_mode = mode; + } + return ret; +} + +static void cst8xxT_rst(void) +{ + gpiod_direction_output(hyn_8xxTdata->plat_data.reset_gpio,0); + msleep(11); + gpiod_direction_output(hyn_8xxTdata->plat_data.reset_gpio,1); +} + +static int cst8xxT_supend(void) +{ + HYN_ENTER(); + cst8xxT_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst8xxT_resum(void) +{ + cst8xxT_rst(); + msleep(50); + cst8xxT_set_workmode(NOMAL_MODE,0); + return 0; +} + + +static int cst8xxT_report(void) +{ + uint8_t i = 0; + uint8_t i2c_buf[3+6*MAX_POINTS_REPORT] = {0}; + uint16_t x,y; + uint8_t id = 0,index = 0; + struct hyn_plat_data *dt = &hyn_8xxTdata->plat_data; + + memset(&hyn_8xxTdata->rp_buf,0,sizeof(hyn_8xxTdata->rp_buf)); + hyn_8xxTdata->rp_buf.report_need = REPORT_NONE; + + if(hyn_8xxTdata->work_mode == GESTURE_MODE){ + if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,2)){ + if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,2)) + goto FAILD_END; + } + hyn_8xxTdata->gesture_id = IDX_NULL; + if(i2c_buf[1] == 0x05){ //click + hyn_8xxTdata->gesture_id = IDX_POWER; + hyn_8xxTdata->rp_buf.report_need = REPORT_GES; + } + } + else{ + if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,(3+6*2))){ + if(hyn_wr_reg(hyn_8xxTdata,0x00,1,i2c_buf,3+6*2)) + goto FAILD_END; + } + hyn_8xxTdata->rp_buf.rep_num = i2c_buf[2]; + // HYN_INFO("rep_num = %d",hyn_8xxTdata->rp_buf.rep_num); + for(i = 0 ; i < 2 ; i++) + { + id = (i2c_buf[5 + i*6] & 0xf0)>>4; + if(id > 1) continue; + + x = (i2c_buf[3 + i*6] & 0x0f); + x = (x<<8) + i2c_buf[4 + i*6]; + + y = (i2c_buf[5 + i*6] & 0x0f); + y = (y<<8) + i2c_buf[6 + i*6]; + + hyn_8xxTdata->rp_buf.pos_info[index].pos_id = id; + hyn_8xxTdata->rp_buf.pos_info[index].event = (i2c_buf[3 + i*6] & 0x40) ? 0:1; + hyn_8xxTdata->rp_buf.pos_info[index].pos_x = x ; + hyn_8xxTdata->rp_buf.pos_info[index].pos_y = y ; + // hyn_8xxTdata->rp_buf.pos_info[index].pres_z = (i2c_buf[7 + i*6] <<8) + i2c_buf[8 + i*6] ; + hyn_8xxTdata->rp_buf.pos_info[index].pres_z = 3+(x&0x03); //press mast chang + index++; + } + if(index != 0 || hyn_8xxTdata->rp_buf.rep_num==0) hyn_8xxTdata->rp_buf.report_need = REPORT_POS; + if(dt->key_num){ + i = dt->key_num; + while(i){ + i--; + if(dt->key_y_coords ==hyn_8xxTdata->rp_buf.pos_info[0].pos_y && dt->key_x_coords[i] == hyn_8xxTdata->rp_buf.pos_info[0].pos_x){ + hyn_8xxTdata->rp_buf.key_id = i; + hyn_8xxTdata->rp_buf.key_state = hyn_8xxTdata->rp_buf.pos_info[0].event; + hyn_8xxTdata->rp_buf.report_need = REPORT_KEY; + } + } + } + } + return TRUE; + FAILD_END: + HYN_ERROR("read report data failed"); + return FALSE; +} + +static u32 cst8xxT_check_esd(void) +{ + return TRUE; +} + +static int cst8xxT_prox_handle(u8 cmd) +{ + return TRUE; +} + + +static int cst8xxT_get_dbg_data(u8 *buf, u16 len) +{ + int ret = -1,read_len = len; + switch (hyn_8xxTdata->work_mode){ + case DIFF_MODE: + ret = hyn_wr_reg(hyn_8xxTdata, 0x41, 1,buf,read_len); + break; + case RAWDATA_MODE: + ret = hyn_wr_reg(hyn_8xxTdata, 0x61, 1,buf,read_len); + break; + default: + HYN_ERROR("work_mode:%d",hyn_8xxTdata->work_mode); + break; + } + return ret==0 ? read_len:-1; +} + +static int cst8xxT_get_test_result(u8 *buf, u16 len) +{ + return 0; +} + +const struct hyn_ts_fuc hyn_cst8xxT_fuc = { + .tp_rest = cst8xxT_rst, + .tp_report = cst8xxT_report, + .tp_supend = cst8xxT_supend, + .tp_resum = cst8xxT_resum, + .tp_chip_init = cst8xxT_init, + .tp_updata_fw = cst8xxT_updata_fw, + .tp_set_workmode = cst8xxT_set_workmode, + .tp_check_esd = cst8xxT_check_esd, + .tp_prox_handle = cst8xxT_prox_handle, + .tp_get_dbg_data = cst8xxT_get_dbg_data, + .tp_get_test_result = cst8xxT_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst92xx.c b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst92xx.c new file mode 100644 index 000000000000..15b54a025ec7 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_chips/hyn_cst92xx.c @@ -0,0 +1,994 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_chips/hyn_cst92xx.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include "cst92xx_fw.h" + +#define BOOT_I2C_ADDR (0x5A) +#define MAIN_I2C_ADDR (0x5A) +#define RW_REG_LEN (2) + +#define CST92XX_BIN_SIZE (0x7F80) + +#define HYNITRON_PROGRAM_PAGE_SIZE (128) + +static struct hyn_ts_data *hyn_92xxdata = NULL; + +#if 0 +static const struct hyn_chip_series hyn_92xx_fw[] = { + {0xCACA9217,0xffffffff,"cst9217",(u8*)fw_bin},//if PART_NO_EN==0 use default chip + {0xCACA9220,0xffffffff,"cst9220",(u8*)fw_bin}, + {0,0,"",NULL} +}; +#endif + +static int cst92xx_updata_judge(u8 *p_fw, u16 len); +static u32 cst92xx_read_checksum(void); +static int cst92xx_updata_tpinfo(void); +static int cst92xx_enter_boot(void); +static void cst92xx_rst(void); +static int cst92xx_set_workmode(enum work_mode mode,u8 enable); +static int cst92xx_read_chip_id(void); + +static int cst92xx_init(struct hyn_ts_data* ts_data) +{ + int ret = 0; + HYN_ENTER(); + hyn_92xxdata = ts_data; + hyn_set_i2c_addr(hyn_92xxdata,BOOT_I2C_ADDR); + ret = cst92xx_read_chip_id(); + if(ret == FALSE){ + HYN_INFO("cst92xx_read_chip_id failed"); + return FALSE; + } + ret = cst92xx_updata_tpinfo(); + if(ret == FALSE){ + HYN_INFO("cst92xx_updata_tpinfo failed"); + } + + hyn_92xxdata->fw_updata_addr = (u8*)fw_bin; + hyn_92xxdata->fw_updata_len = CST92XX_BIN_SIZE; + hyn_92xxdata->need_updata_fw = cst92xx_updata_judge((u8*)fw_bin,CST92XX_BIN_SIZE); + if(hyn_92xxdata->need_updata_fw){ + HYN_INFO("need updata FW !!!"); + } + cst92xx_rst(); + msleep(40); + + HYN_INFO("cst92xx_init done !!!"); + return TRUE; +} + + +static int cst92xx_enter_boot(void) +{ + int ok = FALSE,t; + uint8_t i2c_buf[4] = {0}; + + for (t = 10;; t += 2) + { + if (t >= 30){ + return FALSE; + } + + cst92xx_rst(); + mdelay(t); + + ok = hyn_wr_reg(hyn_92xxdata, 0xA001AA, 3, i2c_buf, 0); + if(ok == FALSE){ + continue; + } + + mdelay(1); + + ok = hyn_wr_reg(hyn_92xxdata, 0xA002, 2, i2c_buf, 2); + if(ok == FALSE){ + continue; + } + + if ((i2c_buf[0] == 0x55) && (i2c_buf[1] == 0xB0)) { + break; + } + } + + ok = hyn_wr_reg(hyn_92xxdata, 0xA00100, 3, i2c_buf, 0); + if(ok == FALSE){ + return FALSE; + } + + return TRUE; +} + +static int erase_all_mem(void) +{ + int ok = FALSE,t; + u8 i2c_buf[8]; + + //erase_all_mem + ok = hyn_wr_reg(hyn_92xxdata, 0xA0140000, 4, i2c_buf, 0); + if (ok == FALSE){ + return FALSE; + } + ok = hyn_wr_reg(hyn_92xxdata, 0xA00C807F, 4, i2c_buf, 0); + if (ok == FALSE){ + return FALSE; + } + ok = hyn_wr_reg(hyn_92xxdata, 0xA004EC, 3, i2c_buf, 0); + if (ok == FALSE){ + return FALSE; + } + + mdelay(300); + for (t = 0;; t += 10) { + if (t >= 1000) { + return FALSE; + } + + mdelay(10); + + ok = hyn_wr_reg(hyn_92xxdata, 0xA005, 2, i2c_buf, 1); + if (ok == FALSE) { + continue; + } + + if (i2c_buf[0] == 0x88) { + break; + } + } + + return TRUE; +} + + + + +static int write_mem_page(uint16_t addr, uint8_t *buf, uint16_t len) +{ + int ok = TRUE, t; + uint8_t *i2c_buf; + + i2c_buf = kmalloc(1024 + 2, GFP_KERNEL); + memset(i2c_buf, 0, 1024 + 2); + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x0C; + i2c_buf[2] = len; + i2c_buf[3] = len >> 8; + //ok = hyn_i2c_write_r16(HYN_BOOT_I2C_ADDR, 0xA00C, i2c_buf, 2); + ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, 4); + if(ok == FALSE){ + goto out; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x14; + i2c_buf[2] = addr; + i2c_buf[3] = addr >> 8; + ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, 4); + if(ok == FALSE) { + goto out; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x18; + memcpy(i2c_buf + 2, buf, len); + ok = hyn_write_data(hyn_92xxdata, i2c_buf,RW_REG_LEN, len+2); + if(ok == FALSE){ + goto out; + } + + ok = hyn_wr_reg(hyn_92xxdata,0xA004EE,3,i2c_buf,0); + if(ok == FALSE){ + goto out; + } + + for (t = 0;; t += 10) { + if (t >= 1000) { + goto out; + } + + mdelay(5); + + ok = hyn_wr_reg(hyn_92xxdata,0xA005,2,i2c_buf,1); + if(ok == FALSE){ + continue; + } + + if (i2c_buf[0] == 0x55) { + break; + } + } + +out: + kfree(i2c_buf); + return ok; + +} + + +static int write_code(u8 *bin_addr,uint8_t retry) +{ + uint8_t data[HYNITRON_PROGRAM_PAGE_SIZE+4];//= (uint8_t *)bin_addr; + uint16_t addr = 0; + uint16_t remain_len = CST92XX_BIN_SIZE; + int ret; + + while (remain_len > 0) { + uint16_t cur_len = remain_len; + if (cur_len > HYNITRON_PROGRAM_PAGE_SIZE) { + cur_len = HYNITRON_PROGRAM_PAGE_SIZE; + } + + if(0 == hyn_92xxdata->fw_file_name[0]){ + memcpy(data, bin_addr + addr, HYNITRON_PROGRAM_PAGE_SIZE); + }else{ + ret = hyn_copy_for_updata(hyn_92xxdata,data,addr,HYNITRON_PROGRAM_PAGE_SIZE); + if(ret == FALSE){ + HYN_ERROR("hyn_copy_for_updata error"); + return FALSE; + } + } + //HYN_INFO("write_code addr 0x%x 0x%x",addr,*data); + if (write_mem_page(addr, data, cur_len) == FALSE) { + return FALSE; + } + //data += cur_len; + addr += cur_len; + remain_len -= cur_len; + } + return TRUE; +} + + +static uint32_t cst92xx_read_checksum(void) +{ + int ok = FALSE; + uint8_t i2c_buf[4] = {0}; + uint32_t chip_checksum = 0; + uint8_t retry = 5; + + hyn_92xxdata->boot_is_pass = 0; + ok = hyn_wr_reg(hyn_92xxdata,0xA00300,3,i2c_buf,0); + if (ok == FALSE) { + return FALSE; + } + mdelay(2); + while(retry--){ + mdelay(5); + ok = hyn_wr_reg(hyn_92xxdata,0xA000,2,i2c_buf,1); + if (ok == FALSE) { + continue; + } + if(i2c_buf[0]!=0) break; + } + + mdelay(1); + if(i2c_buf[0] == 0x01){ + hyn_92xxdata->boot_is_pass = 1; + memset(i2c_buf,0,sizeof(i2c_buf)); + ok = hyn_wr_reg(hyn_92xxdata,0xA008,2,i2c_buf,4); + if (ok == FALSE) { + return FALSE; + } + + chip_checksum = ((uint32_t)(i2c_buf[0])) | + (((uint32_t)(i2c_buf[1])) << 8) | + (((uint32_t)(i2c_buf[2])) << 16) | + (((uint32_t)(i2c_buf[3])) << 24); + } + else{ + hyn_92xxdata->need_updata_fw = 1; + } + + return chip_checksum; +} + + +static int cst92xx_updata_fw(u8 *bin_addr, u16 len) +{ + #define CHECKSUM_OFFECT (0x7F6C) + int retry = 0; + int ok_copy = TRUE; + int ok = FALSE; + u8 i2c_buf[4]; + + u32 fw_checksum=0; + HYN_ENTER(); + + if(len < CST92XX_BIN_SIZE){ + HYN_ERROR("len = %d",len); + goto UPDATA_END; + } + // if(len > CST92XX_BIN_SIZE) len = CST92XX_BIN_SIZE; + + if(0 != hyn_92xxdata->fw_file_name[0]){ + //node to update + ok = hyn_copy_for_updata(hyn_92xxdata,i2c_buf,CST92XX_BIN_SIZE-20,4); + fw_checksum = U8TO32(i2c_buf[3],i2c_buf[2],i2c_buf[1],i2c_buf[0]); + if(hyn_92xxdata->hw_info.ic_fw_checksum == fw_checksum || ok != 0){ + HYN_INFO("no update,fw_checksum is same:0x%04x",fw_checksum); + goto UPDATA_END; + } + }else{ + fw_checksum = U8TO32(bin_addr[CHECKSUM_OFFECT+3],bin_addr[CHECKSUM_OFFECT+2],bin_addr[CHECKSUM_OFFECT+1],bin_addr[CHECKSUM_OFFECT+0]); + } + HYN_INFO("updating fw checksum:0x%04x",fw_checksum); + + hyn_irq_set(hyn_92xxdata,DISABLE); + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + hyn_set_i2c_addr(hyn_92xxdata,BOOT_I2C_ADDR); + + HYN_INFO("updata_fw start"); + for(retry = 1; retry<5; retry++){ + hyn_92xxdata->fw_updata_process = 0; + ok = cst92xx_enter_boot(); + if (ok == FALSE){ + continue; + } + hyn_92xxdata->fw_updata_process = 10; + ok = erase_all_mem(); + if (ok == FALSE){ + continue; + } + hyn_92xxdata->fw_updata_process = 20; + ok = write_code(bin_addr,retry); + if (ok == FALSE){ + continue; + } + hyn_92xxdata->fw_updata_process = 30; + hyn_92xxdata->hw_info.ic_fw_checksum = cst92xx_read_checksum(); + if(fw_checksum != hyn_92xxdata->hw_info.ic_fw_checksum){ + HYN_INFO("out data fw checksum err:0x%04x",hyn_92xxdata->hw_info.ic_fw_checksum); + hyn_92xxdata->fw_updata_process |= 0x80; + continue; + } + hyn_92xxdata->fw_updata_process = 100; + if(retry>=5){ + ok_copy = FALSE; + break; + } + break; + } + + hyn_wr_reg(hyn_92xxdata,0xA006EE,3,i2c_buf,0); //exit boot + mdelay(2); + +UPDATA_END: + cst92xx_rst(); + mdelay(50); + + hyn_set_i2c_addr(hyn_92xxdata,MAIN_I2C_ADDR); + + if(ok_copy == TRUE){ + cst92xx_updata_tpinfo(); + HYN_INFO("updata_fw success"); + } + else{ + HYN_INFO("updata_fw failed"); + } + + hyn_irq_set(hyn_92xxdata,ENABLE); + + return ok_copy; +} +static int16_t read_word_from_mem(uint8_t type, uint16_t addr, uint32_t *value) +{ + int16_t ret = 0; + uint8_t i2c_buf[4] = {0},t; + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x10; + i2c_buf[2] = type; + ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,3); + if (ret) + { + return -1; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x0C; + i2c_buf[2] = addr; + i2c_buf[3] = addr >> 8; + ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,4); + if (ret) + { + return -1; + } + + i2c_buf[0] = 0xA0; + i2c_buf[1] = 0x04; + i2c_buf[2] = 0xE4; + ret = hyn_write_data(hyn_92xxdata,i2c_buf,2,3); + if (ret) + { + return -1; + } + + for (t = 0;; t++) + { + if (t >= 100) + { + return -1; + } + ret =hyn_wr_reg(hyn_92xxdata,0xA004,2,i2c_buf,1); + if (ret) + { + continue; + } + if (i2c_buf[0] == 0x00) + { + break; + } + } + ret =hyn_wr_reg(hyn_92xxdata,0xA018,2,i2c_buf,4); + if (ret) + { + return -1; + } + *value = ((uint32_t)(i2c_buf[0])) | + (((uint32_t)(i2c_buf[1])) << 8) | + (((uint32_t)(i2c_buf[2])) << 16) | + (((uint32_t)(i2c_buf[3])) << 24); + + return 0; +} +static int cst92xx_read_chip_id(void) +{ + int16_t ret = 0; + uint8_t retry = 3; + uint32_t partno_chip_type = 0, module_id = 0; + + ret = cst92xx_enter_boot(); + if (ret == FALSE) + { + HYN_ERROR("enter_bootloader error"); + return -1; + } + for (; retry > 0; retry--) + { + // partno + ret = read_word_from_mem(1, 0x077C, &partno_chip_type); + if (ret) + { + continue; + } + // module id + ret = read_word_from_mem(0, 0x7FC0, &module_id); + if (ret) + { + continue; + } + if ((partno_chip_type >> 16) == 0xCACA) + { + partno_chip_type &= 0xffff; + break; + } + } + cst92xx_rst(); + msleep(30); + HYN_INFO("partno_chip_type: 0x%04x", partno_chip_type); + HYN_INFO("module_id: 0x%04x", module_id); + if ((partno_chip_type != 0x9217) && (partno_chip_type != 0x9220)) + { + HYN_ERROR("partno_chip_type error 0x%04x", partno_chip_type); + //return -1; + } + return 0; +} + +static int cst92xx_updata_tpinfo(void) +{ + u8 buf[30]; + struct tp_info *ic = &hyn_92xxdata->hw_info; + int ret = 0; + + cst92xx_set_workmode(0xff,DISABLE); + ret = hyn_wr_reg(hyn_92xxdata,0xD101,2,buf,0); + if(ret == FALSE){ + return FALSE; + } + mdelay(5); + + //firmware_project_id firmware_ic_type + ret = hyn_wr_reg(hyn_92xxdata,0xD1F4,2,buf,28); + if(ret == FALSE){ + return FALSE; + } + ic->fw_project_id = ((uint16_t)buf[17] <<8) + buf[16]; + ic->fw_chip_type = ((uint16_t)buf[19] <<8) + buf[18]; + + //firmware_version + ic->fw_ver = (buf[23]<<24)|(buf[22]<<16)|(buf[21]<<8)|buf[20]; + + //tx_num rx_num key_num + ic->fw_sensor_txnum = ((uint16_t)buf[1]<<8) + buf[0]; + ic->fw_sensor_rxnum = buf[2]; + ic->fw_key_num = buf[3]; + + ic->fw_res_y = (buf[7]<<8)|buf[6]; + ic->fw_res_x = (buf[5]<<8)|buf[4]; + + //fw_checksum + ic->ic_fw_checksum = (buf[27]<<24)|(buf[26]<<16)|(buf[25]<<8)|buf[24]; + + HYN_INFO("IC_info project_id:%04x ictype:%04x fw_ver:%x checksum:%#x",ic->fw_project_id,ic->fw_chip_type,ic->fw_ver,ic->ic_fw_checksum); + + cst92xx_set_workmode(NOMAL_MODE,ENABLE); + + return TRUE; +} + +static int cst92xx_updata_judge(u8 *p_fw, u16 len) +{ + u32 f_checksum,f_fw_ver,f_ictype,f_fw_project_id; + u8 *p_data = p_fw + len - 28; //7F64 + struct tp_info *ic = &hyn_92xxdata->hw_info; + int ret; + + ret = cst92xx_enter_boot(); + if (ret == FALSE){ + HYN_INFO("cst92xx_enter_boot fail,need update"); + return 1; + } + hyn_92xxdata->hw_info.ic_fw_checksum = cst92xx_read_checksum(); + if(hyn_92xxdata->boot_is_pass == 0){ + HYN_INFO("boot_is_pass %d,need force update",hyn_92xxdata->boot_is_pass); + return 1; //need updata + } + + f_fw_project_id = U8TO16(p_data[1],p_data[0]); + f_ictype = U8TO16(p_data[3],p_data[2]); + + f_fw_ver = U8TO16(p_data[7],p_data[6]); + f_fw_ver = (f_fw_ver<<16)|U8TO16(p_data[5],p_data[4]); + + f_checksum = U8TO16(p_data[11],p_data[10]); + f_checksum = (f_checksum << 16)|U8TO16(p_data[9],p_data[8]); + + + HYN_INFO("Bin_info project_id:0x%04x ictype:0x%04x fw_ver:0x%x checksum:0x%x",f_fw_project_id,f_ictype,f_fw_ver,f_checksum); + if(f_ictype != ic->fw_chip_type || f_fw_project_id != ic->fw_project_id){ + HYN_ERROR("not update,please confirm: ic_type 0x%04x,ic_project_id 0x%04x",ic->fw_chip_type,ic->fw_project_id); + return 0; //not updata + } + if(f_checksum != ic->ic_fw_checksum && f_fw_ver > ic->fw_ver){ + HYN_INFO("need update!"); + return 1; //need updata + } + HYN_INFO("cst92xx_updata_judge done, no need update"); + return 0; +} + +//------------------------------------------------------------------------------// + +static int cst92xx_set_workmode(enum work_mode mode,u8 enable) +{ + int ok = FALSE; + uint8_t i2c_buf[4] = {0}; + uint8_t i = 0; + hyn_92xxdata->work_mode = mode; + + for(i=0;i<3;i++) + { + ok = hyn_wr_reg(hyn_92xxdata,0xD11E,2,i2c_buf,0); + if (ok == FALSE) { + msleep(1); + continue; + } + msleep(1); + ok = hyn_wr_reg(hyn_92xxdata,0x0002,2,i2c_buf,2); + if (ok == FALSE) { + msleep(1); + continue; + } + if(i2c_buf[1] == 0x1E){ + break; + } + } + + switch(mode){ + case NOMAL_MODE: + hyn_irq_set(hyn_92xxdata,ENABLE); + hyn_esdcheck_switch(hyn_92xxdata,ENABLE); + ok = hyn_wr_reg(hyn_92xxdata,0xD109,2,i2c_buf,0); + break; + case GESTURE_MODE: + hyn_esdcheck_switch(hyn_92xxdata,ENABLE); + ok = hyn_wr_reg(hyn_92xxdata,0xD104,2,i2c_buf,0); + break; + case LP_MODE: + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + ok = hyn_wr_reg(hyn_92xxdata,0xD107,2,i2c_buf,0); + break; + case DIFF_MODE: + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + ok = hyn_wr_reg(hyn_92xxdata,0xD10D,2,i2c_buf,0); + break; + case RAWDATA_MODE: + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + ok = hyn_wr_reg(hyn_92xxdata,0xD10A,2,i2c_buf,0); + break; + case FAC_TEST_MODE: + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + hyn_wr_reg(hyn_92xxdata,0xD114,2,i2c_buf,0); + msleep(50); + break; + case DEEPSLEEP: + hyn_esdcheck_switch(hyn_92xxdata,DISABLE); + hyn_wr_reg(hyn_92xxdata,0xD105,2,i2c_buf,0); + break; + default : + hyn_92xxdata->work_mode = NOMAL_MODE; + hyn_esdcheck_switch(hyn_92xxdata,enable); + ok = -2; + break; + } + if(ok != -2){ + hyn_92xxdata->work_mode = mode; + } + HYN_INFO("set_workmode:%d ret:%d",mode,ok); + return ok; +} + +static void cst92xx_rst(void) +{ + gpiod_direction_output(hyn_92xxdata->plat_data.reset_gpio,0); + msleep(8); + gpiod_direction_output(hyn_92xxdata->plat_data.reset_gpio,1); +} + + + +static int cst92xx_supend(void) +{ + HYN_ENTER(); + cst92xx_set_workmode(DEEPSLEEP,0); + return 0; +} + +static int cst92xx_resum(void) +{ + cst92xx_rst(); + msleep(50); + cst92xx_set_workmode(NOMAL_MODE,1); + return 0; +} + + +static int cst92xx_report(void) +{ + int ok = FALSE; + uint8_t i2c_buf[MAX_POINTS_REPORT*5+5] = {0}; + uint8_t finger_num = 0; + uint8_t key_state=0,key_id = 0; + + hyn_92xxdata->rp_buf.report_need = REPORT_NONE; + + ok = hyn_wr_reg(hyn_92xxdata,0xD000,2,i2c_buf,sizeof(i2c_buf)); + if (ok == FALSE){ + return FALSE; + } + + ok = hyn_wr_reg(hyn_92xxdata,0xD000AB,3,i2c_buf,0); + if (ok == FALSE){ + return FALSE; + } + + + if (i2c_buf[6] != 0xAB) { + HYN_INFO("fail buf[6]=0x%02x",i2c_buf[6]); + return FALSE; + } + + finger_num = i2c_buf[5] & 0x7F; + + if (finger_num > MAX_POINTS_REPORT) { + HYN_INFO("fail finger_num=%d",finger_num); + return TRUE; + } + hyn_92xxdata->rp_buf.rep_num = finger_num; + + + if ((i2c_buf[5] & 0x80) == 0x80) { // button + uint8_t *data = i2c_buf + finger_num * 5; + if (finger_num > 0) { + data += 2; + } + key_state = data[0];//0x83:按键有触�? 0x80:按键�?�? + key_id = data[1]; // data[1]; :0x17 0x27 0x37 + + if(key_state&0x80){ + hyn_92xxdata->rp_buf.report_need |= REPORT_KEY; + if((key_id == hyn_92xxdata->rp_buf.key_id || 0 == hyn_92xxdata->rp_buf.key_state)&& key_state == 0x83){ + hyn_92xxdata->rp_buf.key_id = key_id; + hyn_92xxdata->rp_buf.key_state = 1; + } + else{ + hyn_92xxdata->rp_buf.key_state = 0; + } + } + } + else//pos + { + uint8_t index = 0,i; + if((i2c_buf[4]&0xF0) > 0){ + if((i2c_buf[4]&0x80) == 0x80) + hyn_92xxdata->gesture_id = 14;//KEY_POWER;// palm + else if(i2c_buf[4]&0x70) + hyn_92xxdata->gesture_id = 14;//GESTURE wakeup + HYN_INFO("i2c_buf[4]=0x%x,gesture_id=0x%x",i2c_buf[4],hyn_92xxdata->gesture_id); + hyn_92xxdata->rp_buf.report_need |= REPORT_GES; + return TRUE; + } + + hyn_92xxdata->rp_buf.report_need |= REPORT_POS; + if (finger_num > 0) { + uint8_t *data = i2c_buf; + //uint8_t *data_ges = i2c_buf + finger_num * 5 + 2; + uint8_t id = data[0] >> 4; + uint8_t switch_ = data[0] & 0x0F; + uint16_t x = ((uint16_t)(data[1]) << 4) | (data[3] >> 4); + uint16_t y = ((uint16_t)(data[2]) << 4) | (data[3] & 0x0F); + uint16_t z = (data[3] & 0x1F) + 0x03; + + HYN_INFO("finger=%d id=%d x=%d y=%d z=%d",finger_num,id,x,y,z); + + if (id < MAX_POINTS_REPORT) { + hyn_92xxdata->rp_buf.pos_info[index].pos_id = id; + hyn_92xxdata->rp_buf.pos_info[index].event = (switch_ == 0x06 || switch_ == 0x07) ? 1 : 0; + hyn_92xxdata->rp_buf.pos_info[index].pos_x = x; + hyn_92xxdata->rp_buf.pos_info[index].pos_y = y; + hyn_92xxdata->rp_buf.pos_info[index].pres_z = z; + index++; + } + + + } + + for (i = 1; i < finger_num; i++) { + uint8_t *data = i2c_buf+5*i+2; + uint8_t id = data[0] >> 4; + uint8_t switch_ = data[0] & 0x0F; + uint16_t x = ((uint16_t)(data[1]) << 4) | (data[3] >> 4); + uint16_t y = ((uint16_t)(data[2]) << 4) | (data[3] & 0x0F); + uint16_t z = (data[4] & 0x7F); + + if (id < MAX_POINTS_REPORT) { + hyn_92xxdata->rp_buf.pos_info[index].pos_id = id; + hyn_92xxdata->rp_buf.pos_info[index].event = (switch_ == 0x06) ? 1 : 0; + hyn_92xxdata->rp_buf.pos_info[index].pos_x = x; + hyn_92xxdata->rp_buf.pos_info[index].pos_y = y; + hyn_92xxdata->rp_buf.pos_info[index].pres_z = z; + index++; + } + } + } + + return TRUE; +} +#if 0 +static u32 cst92xx_check_esd(void) +{ + int ret = 0; + uint8_t retry=3; + u8 buf[6]; + HYN_ENTER(); + while (retry--) + { + ret = hyn_wr_reg(hyn_92xxdata,0xD040,2,buf,0); + ret = hyn_wr_reg(hyn_92xxdata,0xD040,2,buf,6); + if(ret ==0 && hyn_sum16(0xA5,buf,4)==U8TO16(buf[4],buf[5])){ + ret = U8TO32(buf[0],buf[1],buf[2],buf[3]); + break; + } + } + + + return ret; +} +#endif + +static u32 cst92xx_check_esd(void) +{ + + int16_t ok = FALSE; + uint8_t i2c_buf[6], retry; + uint8_t flag = 0; + uint32_t esd_value = 0; + + retry = 4; + flag = 0; + while (retry--){ + hyn_wr_reg(hyn_92xxdata,0xD048,2,i2c_buf,0); + udelay(200); + ok = hyn_wr_reg(hyn_92xxdata,0xD048,2,i2c_buf,2); + if (ok == FALSE){ + msleep(1); + continue; + } else + { + // if (( (i2c_buf[0] & 0xF0) == 0x20 || (i2c_buf[0] & 0xF0) == 0xA0 ) && (i2c_buf[0] & 0x0F) < 10) + if ((i2c_buf[0] == 0x20) || (i2c_buf[0] == 0xA0)) + { + flag = 1; + esd_value = i2c_buf[0]; + break; + } else { + HYN_INFO("ESD data NA,need retry: 0x%x ", i2c_buf[0]); + msleep(2); + continue; + } + } + } + HYN_INFO("ESD data:%d,0x%04x,0x%04x", flag, esd_value, hyn_92xxdata->esd_last_value); + + if (flag == 0){ + hyn_power_source_ctrl(hyn_92xxdata, 0); + mdelay(2); + hyn_power_source_ctrl(hyn_92xxdata, 1); + mdelay(2); + cst92xx_rst(); + msleep(40); + esd_value = 0; + hyn_92xxdata->esd_last_value = 0; + HYN_INFO("esd_check power reset ic"); + } + if ((hyn_92xxdata->work_mode == GESTURE_MODE) && (esd_value != 0xA0)) + { + ok = hyn_wr_reg(hyn_92xxdata,0xD104,2,0,0); + if (ok == FALSE){ + HYN_ERROR("enter_sleep failed"); + } + } + + hyn_92xxdata->esd_last_value = esd_value; + return esd_value; +} + +static int cst92xx_prox_handle(u8 cmd) +{ + return TRUE; +} + + +static int cst92xx_get_dbg_data(u8 *buf, u16 len) +{ + int ret = -1; + u16 read_len = (hyn_92xxdata->hw_info.fw_sensor_txnum * hyn_92xxdata->hw_info.fw_sensor_rxnum)*2; + u16 total_len = read_len + (hyn_92xxdata->hw_info.fw_sensor_txnum + hyn_92xxdata->hw_info.fw_sensor_rxnum)*2; + HYN_ENTER(); + if(total_len > len){ + HYN_ERROR("buf too small"); + return -1; + } + switch(hyn_92xxdata->work_mode){ + case DIFF_MODE: + case RAWDATA_MODE: + ret = hyn_wr_reg(hyn_92xxdata,0x1000,2,buf,read_len); //mt + + buf += read_len; + read_len = hyn_92xxdata->hw_info.fw_sensor_rxnum*2; + ret |= hyn_wr_reg(hyn_92xxdata,0x7000,2,buf,read_len); //rx + + buf += read_len; + read_len = hyn_92xxdata->hw_info.fw_sensor_txnum*2; + ret |= hyn_wr_reg(hyn_92xxdata,0x7200,2,buf,read_len); //tx + + ret |= hyn_wr_reg(hyn_92xxdata,0x000500,3,0,0); //end + break; + default: + HYN_ERROR("work_mode:%d",hyn_92xxdata->work_mode); + break; + } + return ret==0 ? total_len:-1; +} + + +#define FACTEST_PATH "/sdcard/hyn_fac_test_cfg.ini" +#define FACTEST_LOG_PATH "/sdcard/hyn_fac_test.log" +#define FACTEST_ITEM (MULTI_OPEN_TEST|MULTI_SHORT_TEST) + +static int cst92xx_get_test_result(u8 *buf, u16 len) +{ + int ret = 0,timeout; + struct tp_info *ic = &hyn_92xxdata->hw_info; + u16 scap_len = (ic->fw_sensor_txnum + ic->fw_sensor_rxnum)*2; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum*2,i = 0; + u16 *raw_s; + + HYN_ENTER(); + if((mt_len*3 + scap_len) > len || mt_len==0){ + HYN_ERROR("buf too small"); + return FAC_GET_DATA_FAIL; + } + HYN_INFO("---open_higdrv---"); + timeout = 500; + hyn_wr_reg(hyn_92xxdata,0xD110,2,buf,0); ////test open high + while(--timeout){ //wait rise edge + if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break; + msleep(10); + } + if(hyn_wr_reg(hyn_92xxdata,0x3000,2,buf,mt_len)){ //open high + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read open high failed"); + goto selftest_end; + } + hyn_wr_reg(hyn_92xxdata,0x000005,3,buf,0); + + HYN_INFO("---open_low---"); + timeout = 500; + hyn_wr_reg(hyn_92xxdata,0xD111,2,buf,0); ////test open low + while(--timeout){ //wait rise edge + if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break; + msleep(10); + } + if(hyn_wr_reg(hyn_92xxdata,0x1000,2,buf + mt_len,mt_len)){ //open low + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read open low failed"); + goto selftest_end; + } + hyn_wr_reg(hyn_92xxdata,0x000005,3,buf,0); + + //short test + HYN_INFO("---short---"); + timeout = 500; + hyn_wr_reg(hyn_92xxdata,0xD112,2,buf,0); //// short test + while(--timeout){ //wait rise edge + if(hyn_wait_irq_timeout(hyn_92xxdata,100) == 0) break; + msleep(10); + } + if(hyn_wr_reg(hyn_92xxdata,0x5000,2,buf+(mt_len*2),scap_len)){ + ret = FAC_GET_DATA_FAIL; + HYN_ERROR("read fac short failed"); + goto selftest_end; + } + else{ + raw_s = (u16*)(buf + mt_len*2); + HYN_INFO("raw_s start data = %d",*(raw_s)); + for(i = 0; i< ic->fw_sensor_rxnum+ic->fw_sensor_txnum; i++){ + HYN_INFO("short raw data = %d %d",i,*(raw_s+i)); + if(U16REV((u16)*raw_s) != 0) *raw_s = 2000 / U16REV((u16)*raw_s); + else *raw_s =0; + HYN_INFO("short reprocess data = %d %d",i,*(raw_s+i)); + raw_s++; + } + } + + //read data finlish start test + ret = hyn_factory_multitest(hyn_92xxdata ,FACTEST_PATH, buf,(s16*)(buf+scap_len+mt_len*2),FACTEST_ITEM); + +selftest_end: + if(0 == hyn_fac_test_log_save(FACTEST_LOG_PATH,hyn_92xxdata,(s16*)buf,ret,FACTEST_ITEM)){ + HYN_INFO("fac_test log save success"); + } + cst92xx_rst(); + msleep(40); + return ret; +} + +const struct hyn_ts_fuc hyn_cst92xx_fuc = { + .tp_rest = cst92xx_rst, + .tp_report = cst92xx_report, + .tp_supend = cst92xx_supend, + .tp_resum = cst92xx_resum, + .tp_chip_init = cst92xx_init, + .tp_updata_fw = cst92xx_updata_fw, + .tp_set_workmode = cst92xx_set_workmode, + .tp_check_esd = cst92xx_check_esd, + .tp_prox_handle = cst92xx_prox_handle, + .tp_get_dbg_data = cst92xx_get_dbg_data, + .tp_get_test_result = cst92xx_get_test_result +}; diff --git a/drivers/input/touchscreen/hyn/hyn_core.c b/drivers/input/touchscreen/hyn/hyn_core.c new file mode 100644 index 000000000000..a509c19841fa --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_core.c @@ -0,0 +1,983 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_core.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "hyn_core.h" +#define HYN_DRIVER_NAME "hyn_ts" + +u8 hyn_log_level; +static struct hyn_ts_data *hyn_data = NULL; +static const struct hyn_ts_fuc* hyn_fun = NULL; +static const struct of_device_id hyn_of_match_table[] = { + {.compatible = "hyn,66xx", .data = &hyn_cst66xx_fuc,}, /*support 36xx 35xx 66xx 68xx 148E*/ + {.compatible = "hyn,36xxes", .data = &hyn_cst36xxes_fuc,}, /*support 154es 3654es 3640es*/ + {.compatible = "hyn,3240", .data = &hyn_cst3240_fuc,}, /*support 3240 */ + {.compatible = "hyn,92xx", .data = &hyn_cst92xx_fuc,}, /*support 9217、9220 */ + {.compatible = "hyn,3xx", .data = &hyn_cst3xx_fuc,}, /*support 340 348 328 128 140 148*/ + {.compatible = "hyn,7xx", .data = &hyn_cst7xx_fuc,}, /*support 726 826 836u*/ + {.compatible = "hyn,8xxt", .data = &hyn_cst8xxT_fuc,}, /*support 816t 816d 820 08C*/ + {.compatible = "hyn,226se", .data = &hyn_cst226se_fuc,}, /*support 226se 8922*/ + {}, +}; +MODULE_DEVICE_TABLE(of, hyn_of_match_table); + +static int hyn_check_ic(struct hyn_ts_data *ts_data) +{ + const struct of_device_id *of_dev; + of_dev = of_match_device(hyn_of_match_table,ts_data->dev); + if (!of_dev) { + return -1; + } + hyn_fun = of_dev->data; + if (IS_ERR_OR_NULL(hyn_fun) || IS_ERR_OR_NULL(hyn_fun->tp_chip_init) + || hyn_fun->tp_chip_init(ts_data)) { + return -2; + } + ts_data->hyn_fuc_used = hyn_fun; + return 0; +} + +static int hyn_parse_dt(struct hyn_ts_data *ts_data) +{ + int ret = 0; + struct device *dev = ts_data->dev; + struct hyn_plat_data* dt = &ts_data->plat_data; + HYN_ENTER(); + if (dev->of_node) { + u32 buf[8]; + struct device_node *np = dev->of_node; +//vcc supply + dt->vdd_i2c = NULL; + dt->vdd_ana = NULL; + if (of_property_read_bool(np,"vdd_ana-supply")) { + dt->vdd_ana = regulator_get(dev, "vdd_ana"); + if (IS_ERR_OR_NULL(dt->vdd_ana)) { + dt->vdd_ana = NULL; + HYN_ERROR("regulator_get vdd_ana failed"); + } + } + else{ + HYN_INFO("vdd_ana not config"); + } + +//iovcc supply + if (of_property_read_bool(np,"vcc_i2c-supply")) { + dt->vdd_i2c = regulator_get(dev, "vcc_i2c"); + if (IS_ERR_OR_NULL(dt->vdd_i2c)) { + dt->vdd_i2c = NULL; + HYN_ERROR("regulator_get vdd_i2c failed"); + } + } + else{ + HYN_INFO("vdd_i2c not config"); + } + +//gpio info + dt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(dt->reset_gpio)) { + ret = PTR_ERR(dt->reset_gpio); + HYN_ERROR("failed to request reset GPIO: %d\n", ret); + return ret; + } + + dt->irq_gpio = devm_gpiod_get(dev, "irq", GPIOD_ASIS); + if (IS_ERR(dt->irq_gpio)) { + ret = PTR_ERR(dt->irq_gpio); + HYN_ERROR("failed to request irq GPIO: %d\n", ret); + return ret; + } +//pin_ctl + ret =-1; + dt->pinctl = devm_pinctrl_get(dev); + if (!IS_ERR_OR_NULL(dt->pinctl)) { + dt->pin_active = pinctrl_lookup_state(dt->pinctl, "ts_active"); + dt->pin_suspend= pinctrl_lookup_state(dt->pinctl, "ts_suspend"); + if (!IS_ERR_OR_NULL(dt->pin_active) && !IS_ERR_OR_NULL(dt->pin_suspend)) { + ret = 0; + } + } + if (ret) { + HYN_INFO("pinctrl not config or can't find \"ts-active\" \"ts_suspend\""); + dt->pinctl = NULL; + dt->pin_active = NULL; + dt->pin_suspend= NULL; + } + +// point info + ret = of_property_read_u32(np, "max-touch-number", &dt->max_touch_num); + ret |= of_property_read_u32(np, "pos-swap", &dt->swap_xy); + ret |= of_property_read_u32(np, "posx-reverse", &dt->reverse_x); + ret |= of_property_read_u32(np, "posy-reverse", &dt->reverse_y); + ret |= of_property_read_u32_array(np, "display-coords", buf, 4); + dt->x_resolution = buf[2]; + dt->y_resolution = buf[3]; + HYN_INFO("dts x_res = %d,y_res = %d,touch-number = %d swap_xy = %d reversex = %d reversey = %d", + dt->x_resolution,dt->y_resolution,dt->max_touch_num,dt->swap_xy,dt->reverse_x,dt->reverse_y); + if (ret < 0) { + HYN_ERROR("dts get screen failed"); + return -EINVAL; + } + +// key info + ret = of_property_read_u32(np, "key-number", &dt->key_num); + if (ret>=0 && dt->key_num && dt->key_num<=8) { + ret |= of_property_read_u32(np, "key-y-coord", &dt->key_y_coords); + ret |= of_property_read_u32_array(np, "key-x-coords", dt->key_x_coords, dt->key_num); + ret |= of_property_read_u32_array(np, "keys", dt->key_code, dt->key_num); + if (ret < 0) { + HYN_ERROR("dts get screen failed"); + return -EINVAL; + } + } + else{ + HYN_INFO("key not config"); + dt->key_num = 0; + } + return 0; + } + else{ + HYN_ERROR("dts match failed"); + return -ENODEV; + } +} + +static int hyn_poweron(struct hyn_ts_data *ts_data) +{ + int ret = 0; + struct hyn_plat_data* dt = &ts_data->plat_data; + if (!IS_ERR_OR_NULL(hyn_data->plat_data.pinctl)) { + if (pinctrl_select_state(dt->pinctl, dt->pin_active)) { + HYN_ERROR("pin active set failed"); + ret = -EPROBE_DEFER; + goto GPIO_SET_FAILE; + } + } + + if (!IS_ERR_OR_NULL(dt->vdd_ana)) { + if (regulator_count_voltages(dt->vdd_ana) > 0) { + if (regulator_set_voltage(dt->vdd_ana, 2800000, 3300000)) { + HYN_ERROR("set voltage vdd_ana failed"); + } + } + } + + if (!IS_ERR_OR_NULL(dt->vdd_i2c)) { + if (regulator_count_voltages(dt->vdd_i2c) > 0) { + if (regulator_set_voltage(dt->vdd_i2c, 1800000, 1800000)) { + HYN_ERROR("set voltage vdd_i2c failed"); + } + } + } + if (hyn_power_source_ctrl(hyn_data, 1)) { + HYN_ERROR("enable power failed"); + } + mdelay(5); + gpiod_direction_output(dt->reset_gpio, 1); + return 0; +GPIO_SET_FAILE: + return ret; +} + +static int hyn_input_dev_init(struct hyn_ts_data *ts_data) +{ + int key_num = 0;//,ret =0; + struct hyn_plat_data *dt = &ts_data->plat_data; + struct input_dev *input_dev; + + HYN_ENTER(); + input_dev = input_allocate_device(); + if (!input_dev) { + HYN_ERROR("Failed to allocate memory for input device"); + return -ENOMEM; + } + input_dev->name = HYN_DRIVER_NAME; + input_dev->id.bustype = ts_data->bus_type; + input_dev->dev.parent = ts_data->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); + + for (key_num = 0; key_num < dt->key_num; key_num++) + input_set_capability(input_dev, EV_KEY, dt->key_code[key_num]); +#if HYN_MT_PROTOCOL_B_EN + set_bit(BTN_TOOL_FINGER,input_dev->keybit); + //input_mt_init_slots(input_dev, dt->max_touch_num+1); + input_mt_init_slots(input_dev, dt->max_touch_num+1, INPUT_MT_DIRECT); +#else + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); +#endif + + input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, dt->max_touch_num, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, dt->x_resolution,0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, dt->y_resolution,0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0); + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0); + + ts_data->input_dev = input_dev; + + return 0; +} + +static void release_all_finger(struct hyn_ts_data *ts_data) +{ + HYN_ENTER(); + if (ts_data->report_id_flg) { +#if HYN_MT_PROTOCOL_B_EN + u8 i; + for(i=0; i< ts_data->plat_data.max_touch_num; i++) { + if (ts_data->report_id_flg & (1UL<input_dev, i); + input_report_abs(ts_data->input_dev, ABS_MT_TRACKING_ID, -1); + input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, false); + } + } + input_report_key(ts_data->input_dev, BTN_TOUCH, 0); +#else + input_report_key(ts_data->input_dev, BTN_TOUCH, 0); + input_mt_sync(ts_data->input_dev); +#endif + } + ts_data->report_id_flg = 0; +} + +static void touch_updata(u8 idx,u8 event) +{ + struct ts_frame *rep_frame = &hyn_data->rp_buf; + struct input_dev *dev = hyn_data->input_dev; + u16 zpress = rep_frame->pos_info[idx].pres_z; + if (zpress < 10) { + zpress = zpress+(rep_frame->pos_info[idx].pos_x&0x03) + (rep_frame->pos_info[idx].pos_y&0x03); + } + if (event) { + hyn_data->report_id_flg |= (1UL<< rep_frame->pos_info[idx].pos_id); + } +#if HYN_MT_PROTOCOL_B_EN + if (event) { + input_report_key(dev, BTN_TOUCH, 1); + input_mt_slot(dev, rep_frame->pos_info[idx].pos_id); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, 1); + input_report_abs(dev, ABS_MT_TRACKING_ID, rep_frame->pos_info[idx].pos_id); + input_report_abs(dev, ABS_MT_POSITION_X, rep_frame->pos_info[idx].pos_x); + input_report_abs(dev, ABS_MT_POSITION_Y, rep_frame->pos_info[idx].pos_y); + input_report_abs(dev, ABS_MT_TOUCH_MAJOR, zpress>>3); + input_report_abs(dev, ABS_MT_WIDTH_MAJOR, zpress>>3); + input_report_abs(dev, ABS_MT_PRESSURE, zpress); + } + else{ + input_mt_slot(dev, rep_frame->pos_info[idx].pos_id); + input_report_abs(dev, ABS_MT_TRACKING_ID, -1); + input_mt_report_slot_state(dev, MT_TOOL_FINGER, 0); + } +#else + if (event) { + input_report_key(dev, BTN_TOUCH, 1); + input_report_abs(dev, ABS_MT_PRESSURE, zpress); + input_report_abs(dev, ABS_MT_TRACKING_ID, rep_frame->pos_info[idx].pos_id); + input_report_abs(dev, ABS_MT_TOUCH_MAJOR, zpress>>3); + // input_report_abs(dev, ABS_MT_WIDTH_MAJOR, zpress>>3); + input_report_abs(dev, ABS_MT_POSITION_X, rep_frame->pos_info[idx].pos_x); + input_report_abs(dev, ABS_MT_POSITION_Y, rep_frame->pos_info[idx].pos_y); + input_mt_sync(dev); + } +#endif +} + +static void hyn_irq_report_work(struct work_struct *work) +{ + struct hyn_ts_data *ts_data = hyn_data; + struct ts_frame *rep_frame = &hyn_data->rp_buf; + struct input_dev *dev = hyn_data->input_dev; + struct hyn_plat_data *dt = &hyn_data->plat_data; + u16 xpos,ypos; + int reprot_state_clr = 0; + if (hyn_fun->tp_report()) { + HYN_INFO("Ignore illegal data"); + return; + } + mutex_lock(&ts_data->mutex_report); + if (rep_frame->report_need & REPORT_KEY) { //key +#if KEY_USED_POS_REPORT + rep_frame->pos_info[0].pos_id = 0; + rep_frame->pos_info[0].pos_x = dt->key_x_coords[rep_frame->key_id]; + rep_frame->pos_info[0].pos_y = dt->key_y_coords; + rep_frame->pos_info[0].pres_z = 100; + touch_updata(0,rep_frame->key_state ? 1:0); +#else + input_report_key(dev,dt->key_code[rep_frame->key_id],rep_frame->key_state ? 1:0); +#endif + if (rep_frame->key_state==0) { + reprot_state_clr = 1; + } + input_sync(dev); + HYN_INFO2("report keyid:%d keycode:%d",rep_frame->key_id,dt->key_code[rep_frame->key_id]); + } + + if (rep_frame->report_need & REPORT_POS) { //pos + u8 i; + if (rep_frame->rep_num == 0) { + release_all_finger(ts_data); + reprot_state_clr = 1; + } + else{ + u8 touch_down = 0; + ts_data->report_id_flg = 0; + for(i = 0; i < rep_frame->rep_num; i++) { + HYN_INFO2("id,%d,xy,%d,%d",rep_frame->pos_info[i].pos_id,rep_frame->pos_info[i].pos_x,rep_frame->pos_info[i].pos_y); + if (dt->swap_xy) { + xpos = rep_frame->pos_info[i].pos_y; + ypos = rep_frame->pos_info[i].pos_x; + } + else{ + xpos = rep_frame->pos_info[i].pos_x; + ypos = rep_frame->pos_info[i].pos_y; + } + if (ypos > dt->y_resolution || xpos > dt->x_resolution) { + HYN_ERROR("Please check dts or FW config,maybe resolution or origin issue!!!"); + } + if (rep_frame->pos_info[i].pos_id >= ts_data->plat_data.max_touch_num) { + continue; + } + if (dt->reverse_x) { + xpos = dt->x_resolution-xpos; + } + if (dt->reverse_y) { + ypos = dt->y_resolution-ypos; + } + rep_frame->pos_info[i].pos_x = xpos; + rep_frame->pos_info[i].pos_y = ypos; + touch_updata(i,rep_frame->pos_info[i].event? 1:0); + if (rep_frame->pos_info[i].event) touch_down++; + } + if (touch_down==0) { + reprot_state_clr = 1; + input_report_key(dev, BTN_TOUCH, 0); +#if HYN_MT_PROTOCOL_B_EN==0 + input_mt_sync(dev); +#endif + } + } + input_sync(dev); + } + if (rep_frame->report_need & REPORT_PROX) { + hyn_proximity_report(ts_data->prox_state); + reprot_state_clr = 1; + } +#if (HYN_GESTURE_EN) + if (rep_frame->report_need & REPORT_GES) { + hyn_gesture_report(ts_data); + reprot_state_clr = 1; + } +#endif + if (reprot_state_clr) { + rep_frame->report_need = REPORT_NONE; + } + mutex_unlock(&ts_data->mutex_report); +} + +static void hyn_esdcheck_work(struct work_struct *work) +{ +#if ESD_CHECK_EN + int ret; + HYN_ENTER(); + if (hyn_data->esd_block_cnt==0) { + ret = hyn_fun->tp_check_esd(); + HYN_INFO("esd:%04x",ret); + if (hyn_data->esd_last_value != ret) { + hyn_data->esd_fail_cnt = 0; + hyn_data->esd_last_value = ret; + } + else{ + hyn_data->esd_fail_cnt++; + if (hyn_data->esd_fail_cnt > 2) { + hyn_data->esd_fail_cnt = 0; + hyn_power_source_ctrl(hyn_data,0); + mdelay(1); + hyn_power_source_ctrl(hyn_data,1); + hyn_fun->tp_rest(); + if (hyn_data->prox_is_enable) { + hyn_fun->tp_prox_handle(1); + } + else if (hyn_data->gesture_is_enable) { + hyn_fun->tp_set_workmode(GESTURE_MODE,1); + } + if (hyn_data->charge_is_enable) { + hyn_fun->tp_set_workmode(CHARGE_ENTER,1); + } + if (hyn_data->glove_is_enable) { + hyn_fun->tp_set_workmode(GLOVE_ENTER,1); + } + } + } + } + else{ + hyn_data->esd_block_cnt--; + } + queue_delayed_work(hyn_data->hyn_workqueue, &hyn_data->esdcheck_work, + msecs_to_jiffies(1000)); +#endif +} + +static void hyn_resume(struct device *dev) +{ + int ret = 0; + struct ts_frame *rep_frame; + struct hyn_plat_data *dt; + HYN_ENTER(); + if (IS_ERR_OR_NULL(hyn_data)) { + return; + } + rep_frame = &hyn_data->rp_buf; + dt = &hyn_data->plat_data; +#if (HYN_WAKE_LOCK_EN==1) + wake_unlock(&hyn_data->tp_wakelock); +#endif + if (!IS_ERR_OR_NULL(dt->pinctl)) { + pinctrl_select_state(dt->pinctl, dt->pin_active); + } + hyn_power_source_ctrl(hyn_data, 1); + hyn_fun->tp_resum(); + //Condition recovery + if (hyn_data->prox_is_enable) { + hyn_fun->tp_prox_handle(1); + } else if (hyn_data->gesture_is_enable) { + hyn_irq_set(hyn_data,DISABLE); + ret = disable_irq_wake(hyn_data->gpio_irq); + ret |= irq_set_irq_type(hyn_data->gpio_irq,dt->irq_flags); + if (ret < 0) { + HYN_ERROR("gesture disable_irq_wake failed"); + } + } + if (hyn_data->charge_is_enable) { + hyn_fun->tp_set_workmode(CHARGE_ENTER,1); + } + if (hyn_data->glove_is_enable) { + hyn_fun->tp_set_workmode(GLOVE_ENTER,1); + } + //compensate for lifting + if (rep_frame->report_need & REPORT_KEY) { + input_report_key(hyn_data->input_dev,dt->key_code[rep_frame->key_id],0); + } + if (rep_frame->report_need & REPORT_POS) { + release_all_finger(hyn_data); + input_sync(hyn_data->input_dev); + } + rep_frame->report_need = REPORT_NONE; + hyn_irq_set(hyn_data,ENABLE); +} + +static __maybe_unused void hyn_suspend(struct device *dev) +{ + int ret = 0; + HYN_ENTER(); + if (IS_ERR_OR_NULL(hyn_data)) { + return; + } +#if (HYN_WAKE_LOCK_EN==1) + wake_lock(&hyn_data->tp_wakelock); +#endif + if (hyn_data->prox_is_enable ==1) { + } else if (hyn_data->gesture_is_enable) { + hyn_irq_set(hyn_data,DISABLE); + ret = enable_irq_wake(hyn_data->gpio_irq); + ret |= irq_set_irq_type(hyn_data->gpio_irq,IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND|IRQF_ONESHOT); + if (ret < 0) { + HYN_ERROR("gesture irq_set_irq failed"); + } + hyn_fun->tp_set_workmode(GESTURE_MODE,1); + hyn_irq_set(hyn_data,ENABLE); + hyn_power_source_ctrl(hyn_data, 1); + } else { + hyn_irq_set(hyn_data,DISABLE); + hyn_fun->tp_supend(); + if (!IS_ERR_OR_NULL(hyn_data->plat_data.pinctl)) { + pinctrl_select_state(hyn_data->plat_data.pinctl, hyn_data->plat_data.pin_suspend); + } + hyn_power_source_ctrl(hyn_data, 0); + } +} + +static void hyn_updata_fw_work(struct work_struct *work) +{ + if (!IS_ERR_OR_NULL(hyn_data->fw_updata_addr)) { + hyn_fun->tp_updata_fw(hyn_data->fw_updata_addr,hyn_data->fw_updata_len); + } + else{ + HYN_ERROR("fw_updata_addr is erro"); + } +} + +static void hyn_resume_work(struct work_struct *work) +{ + if (IS_ERR_OR_NULL(hyn_data)) { + return; + } + hyn_resume(hyn_data->dev); +} + +static irqreturn_t hyn_irq_handler(int irq, void *data) +{ + atomic_set(&hyn_data->hyn_irq_flg,1); + if (hyn_data->work_mode < DIFF_MODE) { + // queue_work(hyn_data->hyn_workqueue,&hyn_data->work_report); + hyn_data->esd_block_cnt = 2; + flush_workqueue(hyn_data->hyn_workqueue); + hyn_irq_report_work(NULL); + } + else{ + wake_up(&hyn_data->wait_irq); + } + return IRQ_HANDLED; +} + +#if defined(CONFIG_FB)// || defined(CONFIG_DRM) +#ifndef FB_EARLY_EVENT_BLANK +#define FB_EARLY_EVENT_BLANK FB_EVENT_BLANK +#endif +static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + if (IS_ERR_OR_NULL(data)) { + HYN_INFO("data is invlid don't handle"); + return 0; + } + { +#if defined(CONFIG_FB) + int blank_value = *((int *)(((struct fb_event *)data)->data)); + const unsigned long event_enum[2] = {FB_EARLY_EVENT_BLANK, FB_EVENT_BLANK}; + const int blank_enum[2] = {FB_BLANK_POWERDOWN, FB_BLANK_UNBLANK}; +// #elif defined(CONFIG_DRM) +// #if defined(CONFIG_DRM_PANEL) +// int blank_value = *((int *)(((struct drm_panel_notifier *)data)->data)); +// const unsigned long event_enum[2] = {DRM_PANEL_EARLY_EVENT_BLANK, DRM_PANEL_EVENT_BLANK}; +// const int blank_enum[2] = {DRM_PANEL_BLANK_POWERDOWN, DRM_PANEL_BLANK_UNBLANK}; +// #else //CONFIG_DRM_PANEL +// int blank_value = *((int *)(((struct msm_drm_notifier *)data)->data)); +// const unsigned long event_enum[2] = {MSM_DRM_EARLY_EVENT_BLANK, MSM_DRM_EVENT_BLANK}; +// const int blank_enum[2] = {MSM_DRM_BLANK_POWERDOWN, MSM_DRM_BLANK_UNBLANK}; +// #endif //CONFIG_DRM_PANEL +#endif //CONFIG_DRM + + HYN_INFO("notifier,event:%lu,blank:%d", event, blank_value); + if (hyn_data->old_fb_state == blank_value || (event != event_enum[0] && event != event_enum[1])) { + HYN_INFO("don't care"); + return 0; + } + + if (blank_enum[1] == blank_value) { + queue_work(hyn_data->hyn_workqueue, &hyn_data->work_resume); + } else{ + cancel_work_sync(&hyn_data->work_resume); + hyn_suspend(hyn_data->dev); + } + + hyn_data->old_fb_state = blank_value; + return 0; + } +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void hyn_ts_early_suspend(struct early_suspend *handler) +{ + hyn_suspend(hyn_data->dev); +} +static void hyn_ts_late_resume(struct early_suspend *handler) +{ + hyn_resume(hyn_data->dev); +} +#endif + +#ifdef I2C_PORT +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static void hyn_ts_remove(struct i2c_client *client); +#else +static int hyn_ts_remove(struct i2c_client *client); +#endif +static int hyn_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +#else + +#ifdef CONFIG_BUS_SPI +static struct mt_chip_conf hyn_mt_spi_conf = { + .setuptime = 100, + .holdtime = 100, + .high_time = 25, + .low_time = 25, + .cs_idletime = 2, + .ulthgh_thrsh = 0, + .cpol = 0, + .cpha = 0, + .rx_mlsb = 1, + .tx_mlsb = 1, + .tx_endian = 0, + .rx_endian = 0, + .com_mod = DMA_TRANSFER,/*FIFO_TRANSFER,*/ + .pause = 1, /*0 : twice cs 1: one cs*/ + .finish_intr = 1, + .deassert = 0, + .ulthigh = 0, + .tckdly = 0, +}; +#endif + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static void hyn_ts_remove(struct spi_device *client); +#else +static int hyn_ts_remove(struct spi_device *client); +#endif +static int hyn_ts_probe(struct spi_device *client) +#endif +{ + int ret = 0; + u16 bus_type; + struct hyn_ts_data *ts_data = 0; + + HYN_ENTER(); + HYN_INFO(HYN_DRIVER_VERSION); +#ifdef I2C_PORT + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + HYN_ERROR("I2C not supported"); + return -ENODEV; + } + bus_type = BUS_I2C; +#else + client->mode = SPI_MODE; + client->max_speed_hz = SPI_CLOCK_FREQ; + client->bits_per_word = 8; + +#ifdef CONFIG_BUS_SPI + client->controller_data = (void *)&hyn_mt_spi_conf; +#endif + + if (spi_setup(client) < 0) { + HYN_ERROR("SPI not supported"); + return -ENODEV; + } + bus_type = BUS_SPI; +#endif + if (!IS_ERR_OR_NULL(hyn_data)) { + HYN_ERROR("other dev is insmode"); + return -ENOMEM; + } + ts_data = kzalloc(sizeof(*ts_data), GFP_KERNEL); + if (!ts_data) { + HYN_ERROR("alloc ts data failed"); + return -ENOMEM; + } + ts_data->bus_type = bus_type; + ts_data->rp_buf.key_id = 0xFF; + ts_data->work_mode = NOMAL_MODE; + hyn_log_level = 0; + + hyn_data = ts_data; + ts_data->client = client; + ts_data->dev = &client->dev; + dev_set_drvdata(ts_data->dev, ts_data); + + #if (I2C_USE_DMA==2) + ts_data->dev->coherent_dma_mask = DMA_BIT_MASK(32); + ts_data->dma_buff_va = (u8 *)dma_alloc_coherent(ts_data->dev, + 2048, &ts_data->dma_buff_pa, GFP_KERNEL); + if (!ts_data->dma_buff_va) { + HYN_ERROR("Allocate I2C DMA Buffer fail"); + } + #endif + ret = hyn_parse_dt(ts_data); + if (ret) { + HYN_ERROR("hyn_parse_dt failed"); + goto FREE_RESOURCE; + } + + ret = hyn_poweron(ts_data); + if (ret) { + HYN_ERROR("hyn_poweron failed"); + goto FREE_RESOURCE; + } + // spin_lock_init(&ts_data->irq_lock); + mutex_init(&ts_data->mutex_report); + mutex_init(&ts_data->mutex_bus); + mutex_init(&ts_data->mutex_fs); + init_waitqueue_head(&ts_data->wait_irq); + + ret = hyn_check_ic(ts_data); + if (ret) { + HYN_ERROR("hyn_check_ic failed"); + goto FREE_RESOURCE; + } + + INIT_WORK(&ts_data->work_report,hyn_irq_report_work); + INIT_WORK(&ts_data->work_updata_fw,hyn_updata_fw_work); + INIT_WORK(&ts_data->work_resume,hyn_resume_work); + INIT_DELAYED_WORK(&ts_data->esdcheck_work,hyn_esdcheck_work); + + ts_data->hyn_workqueue = create_singlethread_workqueue("hyn_wq"); + if (IS_ERR_OR_NULL(ts_data->hyn_workqueue)) { + HYN_ERROR("create work queue failed"); + ret = -ENOMEM; + goto FREE_RESOURCE; + } + + ret = hyn_input_dev_init(ts_data); + if (ret) { + if (!IS_ERR_OR_NULL(ts_data->input_dev)) { + input_set_drvdata(ts_data->input_dev, NULL); + input_free_device(ts_data->input_dev); + ts_data->input_dev = NULL; + } + HYN_ERROR("hyn_input_dev_init failed"); + goto FREE_RESOURCE; + } + ret = input_register_device(ts_data->input_dev); + if (ret) { + HYN_ERROR("input_register_device failed"); + goto FREE_RESOURCE; + } + +#if (HYN_WAKE_LOCK_EN==1) + wake_lock_init(&ts_data->tp_wakelock, WAKE_LOCK_SUSPEND, "suspend_tp_lock"); +#endif + +#if (HYN_GESTURE_EN) + ret = hyn_gesture_init(ts_data); + if (ret) { + HYN_ERROR("gesture_init failed"); + goto FREE_RESOURCE; + } +#endif + + ts_data->gpio_irq = gpiod_to_irq(ts_data->plat_data.irq_gpio); + if (ts_data->gpio_irq < 0) { + HYN_ERROR("failed to get gpio irq\n"); + ret = ts_data->gpio_irq; + goto FREE_RESOURCE; + } + ts_data->plat_data.irq_flags = irqd_get_trigger_type(irq_get_irq_data(ts_data->gpio_irq)); + ret = devm_request_threaded_irq(ts_data->dev, ts_data->gpio_irq, NULL, hyn_irq_handler, + (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), HYN_DRIVER_NAME, + ts_data); + if (ret) { + HYN_ERROR("devm_request_threaded_irq failed"); + goto FREE_RESOURCE; + } + atomic_set(&ts_data->irq_is_disable,ENABLE); + hyn_irq_set(ts_data , DISABLE); + +#if defined(CONFIG_FB) + HYN_INFO("fb_notif_register"); + ts_data->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts_data->fb_notif); + if (ret) { + HYN_ERROR("register fb_notifier failed: %d", ret); + } +// #elif defined(CONFIG_DRM) +// ts_data->fb_notif.notifier_call = fb_notifier_callback; +// #if defined(CONFIG_DRM_PANEL) +// HYN_INFO("drm_panel register"); +// { +// int i,count; +// struct device_node *node; +// struct drm_panel *panel; +// struct device_node *np = ts_data->dev->of_node; +// count = of_count_phandle_with_args(np, "panel", NULL); +// ts_data->active_panel = NULL; +// if (count > 0) { +// for (i = 0; i < count; i++) { +// node = of_parse_phandle(np, "panel", i); +// panel = of_drm_find_panel(node); +// of_node_put(node); +// if (!IS_ERR(panel)) { +// ts_data->active_panel = panel; +// break; +// } +// } +// } +// if (IS_ERR_OR_NULL(ts_data->active_panel)) { +// HYN_ERROR("node can't not find DRM panel "); +// } +// } +// if (!IS_ERR_OR_NULL(ts_data->active_panel)) { +// ret = drm_panel_notifier_register(ts_data->active_panel,&ts_data->fb_notif); +// if (ret < 0) { +// HYN_ERROR("drm_panel_notifier_register failed: %d", ret); +// } +// } +// #else +// HYN_INFO("msm_drm_register"); +// ret = msm_drm_register_client(&ts_data->fb_notif); +// if (ret < 0) { +// HYN_ERROR("msm_drm_register_client failed: %d", ret); +// } +// #endif +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts_data->early_suspend.suspend = hyn_ts_early_suspend; + ts_data->early_suspend.resume = hyn_ts_late_resume; + register_early_suspend(&ts_data->early_suspend); +#endif + hyn_create_sysfs(ts_data); +#if (HYN_APK_DEBUG_EN) + hyn_tool_fs_int(ts_data); +#endif + hyn_proximity_int(ts_data); + hyn_irq_set(ts_data,ENABLE); + hyn_esdcheck_switch(ts_data,ENABLE); + +#if HYN_POWER_ON_UPDATA + if (ts_data->need_updata_fw) { + queue_work(ts_data->hyn_workqueue,&ts_data->work_updata_fw); + } +#endif + return 0; +FREE_RESOURCE: + hyn_ts_remove(client); + return ret; +} + + +#ifdef I2C_PORT +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static void hyn_ts_remove(struct i2c_client *client) +#else +static int hyn_ts_remove(struct i2c_client *client) +#endif +#else +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static void hyn_ts_remove(struct spi_device *client) +#else +static int hyn_ts_remove(struct spi_device *client) +#endif +#endif +{ + struct hyn_ts_data *ts_data = hyn_data; + HYN_ENTER(); + if (!IS_ERR_OR_NULL(ts_data)) { + if (ts_data->hyn_workqueue) { + flush_workqueue(ts_data->hyn_workqueue); + hyn_esdcheck_switch(ts_data,DISABLE); + destroy_workqueue(ts_data->hyn_workqueue); + } + HYN_INFO2("ts_remove1"); +#if (HYN_APK_DEBUG_EN) + hyn_tool_fs_exit(); +#endif + hyn_proximity_exit(); +#if (HYN_GESTURE_EN) + hyn_gesture_exit(ts_data); +#endif + hyn_release_sysfs(ts_data); + HYN_INFO2("ts_remove2"); + if (!IS_ERR_OR_NULL(ts_data->input_dev)) { + input_unregister_device(ts_data->input_dev); + } + HYN_INFO2("ts_remove3"); +#if 0 +#if defined(CONFIG_FB) + fb_unregister_client(&ts_data->fb_notif); +// #elif defined(CONFIG_DRM) +// #if defined(CONFIG_DRM_PANEL) +// if (!IS_ERR_OR_NULL(ts_data->active_panel)) +// drm_panel_notifier_unregister(ts_data->active_panel, &ts_data->fb_notif); +// #else +// msm_drm_unregister_client(&ts_data->fb_notif); +// #endif +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts_data->early_suspend); +#endif +#endif + hyn_power_source_ctrl(hyn_data, 0); + if (!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)) { + regulator_put(ts_data->plat_data.vdd_ana); + } + if (!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)) { + regulator_put(ts_data->plat_data.vdd_i2c); + } + HYN_INFO2("ts_remove4"); +#if (I2C_USE_DMA==2) + if (!IS_ERR_OR_NULL(ts_data->dma_buff_va)) { + dma_free_coherent(NULL, 2048, ts_data->dma_buff_va, ts_data->dma_buff_pa); + } +#endif + kfree(ts_data); + hyn_data = NULL; + HYN_INFO2("ts_remove5"); + } +#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE + return 0; +#endif +} + +#ifdef I2C_PORT +static const struct i2c_device_id hyn_id_table[] = { + {.name = HYN_DRIVER_NAME, .driver_data = 0,}, + {}, +}; + +static struct i2c_driver hyn_ts_driver = { + .probe = hyn_ts_probe, + .remove = hyn_ts_remove, + .driver = { + .name = HYN_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = hyn_of_match_table, + }, + .id_table = hyn_id_table, +}; +#else +static struct spi_driver hyn_ts_driver = { + .driver = { + .name = HYN_DRIVER_NAME, + .of_match_table = hyn_of_match_table, + .owner = THIS_MODULE, + }, + .probe = hyn_ts_probe, + .remove = hyn_ts_remove, +}; +#endif + +static int __init hyn_ts_init(void) +{ + int ret = 0; + HYN_ENTER(); +#ifdef I2C_PORT + ret = i2c_add_driver(&hyn_ts_driver); +#else + ret = spi_register_driver(&hyn_ts_driver); +#endif + if (ret) { + HYN_ERROR("add i2c driver failed"); + return -ENODEV; + } + return 0; +} + +static void __exit hyn_ts_exit(void) +{ + HYN_ENTER(); +#ifdef I2C_PORT + i2c_del_driver(&hyn_ts_driver); +#else + spi_unregister_driver(&hyn_ts_driver); +#endif +} + +late_initcall(hyn_ts_init); +// module_init(hyn_ts_init); +module_exit(hyn_ts_exit); + +MODULE_AUTHOR("Hynitron Driver Team"); +MODULE_DESCRIPTION("Hynitron Touchscreen Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/hyn/hyn_core.h b/drivers/input/touchscreen/hyn/hyn_core.h new file mode 100644 index 000000000000..99d509a03ae5 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_core.h @@ -0,0 +1,386 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_core.h + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 HYNITRON_CORE_H +#define HYNITRON_CORE_H + +#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 +#include +#include +#include +#include +#include + +// #include +#include +#include +#include +#include +#include +#include "hyn_cfg.h" + +#ifdef CONFIG_BUS_SPI +#include "mt_spi.h" +#endif + +#if (HYN_WAKE_LOCK_EN == 1) +#include +#endif + +#if defined(CONFIG_FB) +#include +#include +// #elif defined(CONFIG_DRM) +// #include +// #if defined(CONFIG_DRM_PANEL) +// #include +// #endif +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif + +// #define __noscs __attribute__((__no_sanitize__("shadow-call-stack"))) + +extern u8 hyn_log_level; +#define HYN_INFO(fmt, args...) printk(KERN_INFO "[HYN]"fmt"\n", ##args) +#define HYN_INFO2(fmt, args...) if (hyn_log_level > 0) printk(KERN_INFO "[HYN]"fmt"\n", ##args) +#define HYN_INFO3(fmt, args...) if (hyn_log_level > 1) printk(KERN_INFO "[HYN]"fmt"\n", ##args) +#define HYN_INFO4(fmt, args...) if (hyn_log_level > 2) printk(KERN_INFO "[HYN]"fmt"\n", ##args) +#define HYN_ERROR(fmt, args...) printk(KERN_ERR "[HYN][Error]%s:"fmt"\n", __func__, ##args) +#define HYN_ENTER() HYN_INFO2("[enter]%s\n", __func__) + +#if HYN_GKI_VER +// MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); +#endif + +// #define IS_ERR_OR_NULL(x) (x <= 0) +#define U8TO16(x1,x2) ((((x1)&0xFF)<<8)|((x2)&0xFF)) +#define U8TO32(x1,x2,x3,x4) ((((x1)&0xFF)<<24)|(((x2)&0xFF)<<16)|(((x3)&0xFF)<<8)|((x4)&0xFF)) +#define U16REV(x) ((((x)<<8)&0xFF00)|(((x)>>8)&0x00FF)) + +#undef NULL +#undef FALSE +#undef TRUE +#undef DISABLE +#undef ENABLE +#define NULL ((void*)0) +#define FALSE (-1) +#define TRUE (0) +#define DISABLE (0) +#define ENABLE (1) + +#define PS_FAR_AWAY 1 +#define PS_NEAR 0 + +#define MULTI_OPEN_TEST (0x80) +#define MULTI_SHORT_TEST (0x01) +#define MULTI_SCAP_TEST (0x02) + +#if HYN_GKI_VER +#define hyn_fs_write(...) +#define hyn_fs_read(...) +#else +#define hyn_fs_write kernel_write +#define hyn_fs_read kernel_read +#endif + +enum work_mode{ + NOMAL_MODE = 0, + GESTURE_MODE = 1, + LP_MODE = 2, + DEEPSLEEP = 3, + DIFF_MODE = 4, + RAWDATA_MODE = 5, + BASELINE_MODE = 6, + CALIBRATE_MODE = 7, + FAC_TEST_MODE = 8, + GLOVE_EXIT = 0x10, + GLOVE_ENTER = 0x11, + CHARGE_EXIT = 0x12, + CHARGE_ENTER = 0x13, + ENTER_BOOT_MODE = 0xCA, +}; + +enum report_typ{ + REPORT_NONE = 0, + REPORT_POS = 0x01, + REPORT_KEY = 0x02, + REPORT_GES = 0x04, + REPORT_PROX = 0x08 +}; + +enum fac_test_ero{ + FAC_TEST_PASS = 0, + FAC_GET_DATA_FAIL = -1, + FAC_GET_CFG_FAIL = -4, + FAC_TEST_OPENL_FAIL = -5, + FAC_TEST_OPENH_FAIL = -7, + FAC_TEST_SHORT_FAIL = -6, + FAC_TEST_SCAP_FAIL = -8, +}; + +enum ges_idx{ + IDX_U = 0, + IDX_UP, + IDX_DOWN, + IDX_LEFT, + IDX_RIGHT, + IDX_O, + IDX_e, + IDX_M, + IDX_L, + IDX_W, + IDX_S, + IDX_V, + IDX_C, + IDX_Z, + IDX_POWER, + IDX_NULL = 0xFF, +}; + + +struct hyn_plat_data { + struct regulator *vdd_ana; + struct regulator *vdd_i2c; + + struct gpio_desc *reset_gpio; + struct gpio_desc *irq_gpio; + unsigned long irq_flags; + + struct pinctrl *pinctl; + struct pinctrl_state *pin_active; + struct pinctrl_state *pin_suspend; + + u32 x_resolution; + u32 y_resolution; + int swap_xy; + int reverse_x; + int reverse_y; + + int max_touch_num; + int key_num; + u32 key_x_coords[8]; // max support 8 keys + u32 key_y_coords; + u32 key_code[8]; +}; + +struct hyn_chip_series { + u32 part_no; + u32 moudle_id; + u8* chip_name; + u8* fw_bin; +}; + +#define MAX_POINTS_REPORT (10) +struct ts_frame { + u8 rep_num; + enum report_typ report_need; + u8 key_id; + u8 key_state; + struct { + u8 pos_id; + u8 event; + u16 pos_x; + u16 pos_y; + u16 pres_z; + } pos_info[MAX_POINTS_REPORT]; +}; + +struct tp_info { + u8 fw_sensor_txnum; + u8 fw_sensor_rxnum; + u8 fw_key_num; + u8 reserve; + u16 fw_res_y; + u16 fw_res_x; + u32 fw_boot_time; + u32 fw_project_id; + u32 fw_chip_type; + u32 fw_ver; + u32 ic_fw_checksum; + u32 fw_module_id; +}; + + +struct hyn_ts_data { + u16 bus_type; +#ifdef I2C_PORT + struct i2c_client *client; +#else + struct spi_device *client; +#endif + struct device *dev; + struct input_dev *input_dev; + struct workqueue_struct *hyn_workqueue; + int gpio_irq; + int esd_fail_cnt; + u32 esd_last_value; + int esd_block_cnt; + int report_id_flg; + enum work_mode work_mode; + + int power_is_on; + atomic_t irq_is_disable; + atomic_t hyn_irq_flg; + // spinlock_t irq_lock; + struct mutex mutex_report; + struct mutex mutex_bus; + struct mutex mutex_fs; +#if (HYN_WAKE_LOCK_EN==1) + struct wake_lock tp_wakelock; +#endif + +#if (I2C_USE_DMA==2) + u8 *dma_buff_va; + dma_addr_t dma_buff_pa; +#endif + struct hyn_plat_data plat_data; + struct tp_info hw_info; + struct ts_frame rp_buf; + + struct work_struct work_report; + struct work_struct work_resume; + struct delayed_work esdcheck_work; + + struct work_struct work_updata_fw; + int boot_is_pass; + int need_updata_fw; + u8 fw_file_name[128]; + u8 *fw_updata_addr; + int fw_updata_len; + int fw_dump_state; + u8 fw_updata_process; + u8 host_cmd_save[16]; + wait_queue_head_t wait_irq; + + u8 log_level; + u8 prox_is_enable; + u8 prox_state; + + u8 gesture_is_enable; + u8 gesture_id; + const void *hyn_fuc_used; + + u8 charge_is_enable; + u8 glove_is_enable; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; + int old_fb_state; +// #elif defined(CONFIG_DRM) +// struct notifier_block fb_notif; +// int old_fb_state; +// #if defined(CONFIG_DRM_PANEL) +// struct drm_panel *active_panel; +// #endif +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + struct kobject *sys_node; +}; + +struct hyn_ts_fuc{ + void (*tp_rest)(void); + int (*tp_report)(void); + int (*tp_supend)(void); + int (*tp_resum)(void); + int (*tp_chip_init)(struct hyn_ts_data *ts_data); + int (*tp_updata_fw)(u8 *bin_addr, u16 len); + int (*tp_set_workmode)(enum work_mode mode,u8 enable); + u32 (*tp_check_esd)(void); + int (*tp_prox_handle)(u8 cmd); + int (*tp_get_dbg_data)(u8 *buf,u16 len); + int (*tp_get_test_result)(u8 *buf,u16 len); +}; + +int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len); +int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len); +int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen); + +void hyn_irq_set(struct hyn_ts_data *ts_data, u8 value); +void hyn_esdcheck_switch(struct hyn_ts_data *ts_data, u8 enable); +int hyn_copy_for_updata(struct hyn_ts_data *ts_data,u8 *buf,u32 offset,u16 len); +int hyn_get_word(u8 **sc_str, u8* ds_str); +void hyn_set_i2c_addr(struct hyn_ts_data *ts_data,u8 addr); + +int hyn_proc_fs_int(struct hyn_ts_data *ts_data); +void hyn_proc_fs_exit(void); +int hyn_tool_fs_int(struct hyn_ts_data *ts_data); +void hyn_tool_fs_exit(void); + +int hyn_create_sysfs(struct hyn_ts_data *ts_data); +void hyn_release_sysfs(struct hyn_ts_data *ts_data); +int hyn_gesture_init(struct hyn_ts_data *ts_data); +void hyn_gesture_report(struct hyn_ts_data *ts_data); +void hyn_gesture_exit(struct hyn_ts_data *ts_data); + +int hyn_proximity_exit(void); +int hyn_proximity_int(struct hyn_ts_data *ts_data); +int hyn_proximity_report(u8 proximity_value); + +int hyn_wait_irq_timeout(struct hyn_ts_data *ts_data,int msec); +int hyn_factory_multitest(struct hyn_ts_data *ts_data ,char *cfg_path, u8 *data,s16 *test_th,u8 test_item); +int hyn_fac_test_log_save(char *log_name,struct hyn_ts_data *ts_data,s16 *test_data, int test_ret, u8 test_item); +int hyn_str_2_num(char *str,u8 type); +u16 hyn_sum16(int val, u8* buf,u16 len); +u32 hyn_sum32(int val, u32* buf,u16 len); + +int hyn_power_source_ctrl(struct hyn_ts_data *ts_data, int enable); + +//ic type +extern const struct hyn_ts_fuc hyn_cst3xx_fuc; +extern const struct hyn_ts_fuc hyn_cst66xx_fuc; +extern const struct hyn_ts_fuc hyn_cst7xx_fuc; +extern const struct hyn_ts_fuc hyn_cst8xxT_fuc; +extern const struct hyn_ts_fuc hyn_cst92xx_fuc; +extern const struct hyn_ts_fuc hyn_cst3240_fuc; +extern const struct hyn_ts_fuc hyn_cst226se_fuc; +extern const struct hyn_ts_fuc hyn_cst36xxes_fuc; + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_fs_node.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_fs_node.c new file mode 100644 index 000000000000..76040ef2b2ef --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_fs_node.c @@ -0,0 +1,345 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_fs_node.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" +#include +#include + + +static struct hyn_ts_data *hyn_fs_data = NULL; + +//echo fd /sdcard/app.bin +//echo w d1 01 +//echo w d1 01 r 2 +//echo w 1 2 3 4 5 +//echo rst +#define DEBUG_BUF_SIZE (256) + +static ssize_t hyn_dbg_show(struct device *dev,struct device_attribute *attr,char *buf) +{ + ssize_t len = 0; + int ret = -1; + u8 *kbuf =NULL; + u16 i; + HYN_ENTER(); + mutex_lock(&hyn_fs_data->mutex_fs); + kbuf = kzalloc(DEBUG_BUF_SIZE, GFP_KERNEL); + + if(hyn_fs_data->host_cmd_save[0]==0x5A){ + if(hyn_fs_data->host_cmd_save[1] > 4) hyn_fs_data->host_cmd_save[1] = 4; + len = hyn_fs_data->host_cmd_save[6]; + if(len != 0 && hyn_fs_data->host_cmd_save[1] !=0){ + u32 reg; + reg = hyn_fs_data->host_cmd_save[2]; + i = 0; + while(++i < hyn_fs_data->host_cmd_save[1]){ + reg <<= 8; + reg |= hyn_fs_data->host_cmd_save[2+i]; + } + ret = hyn_wr_reg(hyn_fs_data,reg,hyn_fs_data->host_cmd_save[1],kbuf,(u16)len); + } + } + else if(hyn_fs_data->host_cmd_save[0]==0x7A){ + len = hyn_fs_data->host_cmd_save[6]; + ret = hyn_read_data(hyn_fs_data,kbuf,(u16)len); + } + + if(ret ==0){ + ssize_t cnt_char = 0; + for(i = 0; i< len; i++){ + ret = sprintf(buf+cnt_char,"0x%02x ",*(kbuf+i)); + cnt_char += ret; + } + buf[cnt_char] = '\n'; + ret = cnt_char+1; + } + else{ + sprintf(buf,"fs read failed\n"); + ret = 13; + } + + if(!IS_ERR_OR_NULL(kbuf)) kfree(kbuf); + mutex_unlock(&hyn_fs_data->mutex_fs); + + return ret; +} + +static ssize_t hyn_dbg_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) +{ + u16 rec_len; + u8 str[128]; + u8 *next_ptr; + int val; + const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used; + int ret = 0; + HYN_ENTER(); + mutex_lock(&hyn_fs_data->mutex_fs); + rec_len = strlen(buf); + HYN_INFO("rec_len =%d",rec_len); + // HYN_INFO("%ddata:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",(int)count,buf[0], buf[1],buf[2], buf[3],buf[4], buf[5],buf[6],buf[7]); + if(rec_len < 1 || rec_len > DEBUG_BUF_SIZE){ + HYN_INFO("erro write len"); + goto END; + } + next_ptr = (u8*)buf; + str[0] = '\0'; + hyn_get_word(&next_ptr,str); + if(0 == strcmp(str,"fd")){ //updata fw + hyn_get_word(&next_ptr,str); + if(strlen(str)<4){ + strcpy(str,"/sdcard/app.bin"); + } + HYN_INFO("filename = %s",str); + strcpy(hyn_fs_data->fw_file_name,str); + hyn_fun->tp_updata_fw(hyn_fs_data->fw_updata_addr,hyn_fs_data->fw_updata_len); + // if(0 == hyn_read_fw_file(str, &pdata, &bin_len)){ + // ret = hyn_fun->tp_updata_fw(pdata,bin_len); + // kfree(pdata); + // } + } + else if(0 == strcmp(str,"w")){ + u8 i = 0; + u8 *kbuf = kzalloc(count/2, GFP_KERNEL); + hyn_fs_data->host_cmd_save[0] = 0; + hyn_fs_data->host_cmd_save[1] = 0xA5; + hyn_fs_data->host_cmd_save[6] = 0; + while(1){ + str[0] = '\0'; + ret = hyn_get_word(&next_ptr,str); + // next_ptr += ret; + HYN_INFO("read =%s ,len =%d",str,(int)strlen(str)); + if(0 == strcmp(str,"r")){ + ret = hyn_get_word(&next_ptr,str); + val = hyn_str_2_num(str,16); + if(ret < 0x100){ + hyn_fs_data->host_cmd_save[0] = 0x5A; + hyn_fs_data->host_cmd_save[1] = i>4 ? 4:i; + hyn_fs_data->host_cmd_save[6] = val; + memcpy(&hyn_fs_data->host_cmd_save[2],kbuf,4); + i = 0; + } + break; + } + if(ret == 0 || strlen(str)==0 || strlen(str)>2){ + break; + } + val = hyn_str_2_num(str,16); + if(val > 0xFF) break; + *(kbuf+i) = val; + HYN_INFO(" %02x",val); + i++; + } + if(i){ + hyn_write_data(hyn_fs_data,kbuf,2,i); + } + kfree(kbuf); + } + else if(0 == strcmp(str,"r")){ + hyn_get_word(&next_ptr,str); + val = hyn_str_2_num(str,16); + if(val < 0x100){ + hyn_fs_data->host_cmd_save[0] = 0x7A; + hyn_fs_data->host_cmd_save[6] = val; + } + } + else if(0 == strcmp(str,"rst")){ + hyn_fun->tp_rest(); + } + else if(0 == strcmp(str,"log")){ + hyn_get_word(&next_ptr,str); + hyn_log_level = (u8)(str[0]-'0'); + } + else if(0 == strcmp(str,"workmode")){ + ret = hyn_get_word(&next_ptr,str); + if(ret){ + u8 mode = (u8)(str[0]-'0'); + ret = hyn_get_word(&next_ptr,str); + if(ret) hyn_fun->tp_set_workmode(mode,str[0]=='0'? 0:1); + } + } +END: + mutex_unlock(&hyn_fs_data->mutex_fs); + return count; +} + +///// +///cat hyntpfwver +static ssize_t hyn_tpfwver_show(struct device *dev, struct device_attribute *attr,char *buf) +{ + ssize_t num_read = 0; + HYN_ENTER(); + num_read = snprintf(buf, 128, "fw_version:0x%02X,chip_type:0x%02X,checksum:0x%02X,project_id:%04x\n", + hyn_fs_data->hw_info.fw_ver, + hyn_fs_data->hw_info.fw_chip_type, + hyn_fs_data->hw_info.ic_fw_checksum, + hyn_fs_data->hw_info.fw_project_id + ); + return num_read; +} + +static ssize_t hyn_tpfwver_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) +{ + /*place holder for future use*/ + return -EPERM; +} + +///cat hynselftest +static ssize_t hyn_selftest_show(struct device *dev, struct device_attribute *attr,char *buf) +{ + ssize_t num_read = 0; + u8 *rbuf = NULL; + const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used; + int ret = 0; + int max_len = hyn_fs_data->hw_info.fw_sensor_rxnum*hyn_fs_data->hw_info.fw_sensor_txnum*2 + + (hyn_fs_data->hw_info.fw_sensor_rxnum + hyn_fs_data->hw_info.fw_sensor_txnum)*4; + HYN_ENTER(); + max_len = max_len*3; + rbuf = kzalloc(max_len, GFP_KERNEL); + if(rbuf == NULL){ + HYN_ERROR("zalloc GFP_KERNEL memory[%d] failed.\n",max_len); + return -ENOMEM; + } + hyn_fun->tp_set_workmode(FAC_TEST_MODE,0); + ret = hyn_fun->tp_get_test_result(rbuf,max_len); + num_read = snprintf(buf, 128, "module selftest %s ret:%d\r\n", + ret==0 ? "pass":"failed", ret); + if(!IS_ERR_OR_NULL(rbuf)){ + kfree(rbuf); + } + return num_read; +} + +static ssize_t hyn_selftest_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) +{ + /*place reserver*/ + return -EPERM; +} + +//hyndumpfw +static ssize_t hyn_dumpfw_show(struct device *dev,struct device_attribute *attr,char *buf) +{ + HYN_ENTER(); + return (ssize_t)snprintf(buf, 128, "place reserver"); +} + +static ssize_t hyn_dumpfw_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) +{ + u8 str[16]={'\0'}; + int max_len = hyn_fs_data->fw_updata_len+64; + if(count<10){ + memcpy(str,buf,count); + if(str[count-1]==0x0A) str[count-1] = '\0'; + } + // HYN_INFO("state[%d]: %d,%s",(int)count,hyn_fs_data->fw_dump_state,str); + if(0 == strcmp(str,"fwstart")){ + hyn_fs_data->fw_dump_state = 0; + hyn_fs_data->fw_updata_addr = vmalloc(max_len); + if(hyn_fs_data->fw_updata_addr == NULL){ + HYN_ERROR("vmalloc memory[%d] failed.\n",max_len); + hyn_fs_data->fw_dump_state=-1; + return -EPERM; + } + else{ + HYN_INFO("vmalloc memory[%d] success",max_len); + } + } + else if(0 == strcmp(str,"fwend")){ + if(hyn_fs_data->fw_dump_state >= 0){ + const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used; + memset(hyn_fs_data->fw_file_name,0,sizeof(hyn_fs_data->fw_file_name)); + hyn_fun->tp_updata_fw(hyn_fs_data->fw_updata_addr,hyn_fs_data->fw_updata_len); + vfree(hyn_fs_data->fw_updata_addr); + } + hyn_fs_data->fw_dump_state = -2; + } + else if(hyn_fs_data->fw_dump_state >=0 && (hyn_fs_data->fw_dump_state + count) < max_len){ + memcpy(hyn_fs_data->fw_updata_addr+hyn_fs_data->fw_dump_state,buf,count); + hyn_fs_data->fw_dump_state += count; + } + return count; +} + +///// +///cat hyntpfwver +static ssize_t hyn_mode_show(struct device *dev, struct device_attribute *attr,char *buf) +{ + ssize_t num_read = 0; + HYN_ENTER(); + num_read = snprintf(buf, 128, "is_charge:%d, is_glove:%d",hyn_fs_data->charge_is_enable,hyn_fs_data->glove_is_enable); + return num_read; +} + +static ssize_t hyn_mode_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count) +{ + const struct hyn_ts_fuc* hyn_fun = hyn_fs_data->hyn_fuc_used; + HYN_ENTER(); + HYN_INFO("wlen:%d,%c%c",(int)count,buf[0],buf[1]); + if(buf[0]=='c' || buf[0]=='C'){ + hyn_fun->tp_set_workmode(buf[1]=='1' ? CHARGE_ENTER:CHARGE_EXIT,1); + } + else if(buf[0]=='g' || buf[0]=='G'){ + hyn_fun->tp_set_workmode(buf[1]=='1' ? GLOVE_ENTER:GLOVE_EXIT,1); + } + return count; +} + + +static DEVICE_ATTR(hyntpfwver, S_IRUGO | S_IWUSR, hyn_tpfwver_show, hyn_tpfwver_store); +static DEVICE_ATTR(hyntpdbg, S_IRUGO | S_IWUSR, hyn_dbg_show, hyn_dbg_store); +static DEVICE_ATTR(hynselftest, S_IRUGO | S_IWUSR, hyn_selftest_show, hyn_selftest_store); +static DEVICE_ATTR(hyndumpfw, S_IRUGO | S_IWUSR, hyn_dumpfw_show, hyn_dumpfw_store); +static DEVICE_ATTR(hynswitchmode, S_IRUGO | S_IWUSR, hyn_mode_show, hyn_mode_store); + +static struct attribute *hyn_attributes[] = { + &dev_attr_hynswitchmode.attr, + &dev_attr_hyndumpfw.attr, + &dev_attr_hyntpdbg.attr, + &dev_attr_hynselftest.attr, + &dev_attr_hyntpfwver.attr, + NULL +}; + +static struct attribute_group hyn_attribute_group = { + .attrs = hyn_attributes +}; + +int hyn_create_sysfs(struct hyn_ts_data *ts_data) +{ + int ret = 0; + hyn_fs_data = ts_data; + hyn_fs_data->fw_dump_state = -1; + ts_data->sys_node = &ts_data->dev->kobj;//kobject_create_and_add("hynitron_debug", NULL); + if(IS_ERR_OR_NULL(ts_data->sys_node)){ + HYN_ERROR("kobject_create_and_add failed"); + return -1; + } + ret = sysfs_create_group(ts_data->sys_node, &hyn_attribute_group); + // if(ret){ + // kobject_put(ts_data->sys_node); + // return -1; + // } + HYN_INFO("sys_node creat success ,GKI version is [%s]",HYN_GKI_VER ? "enable":"disable"); + return ret; +} + +void hyn_release_sysfs(struct hyn_ts_data *ts_data) +{ + if(!IS_ERR_OR_NULL(ts_data->sys_node)){ + sysfs_remove_group(ts_data->sys_node, &hyn_attribute_group); + //kobject_put(ts_data->sys_node); + ts_data->sys_node = NULL; + } +} diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_gesture.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_gesture.c new file mode 100644 index 000000000000..1d15652011e5 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_gesture.c @@ -0,0 +1,106 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_gesture.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + +static const u8 gesture_key[] = {KEY_U,KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT, + KEY_O,KEY_E, KEY_M, KEY_L, KEY_W, + KEY_S,KEY_V, KEY_C, KEY_Z, KEY_POWER}; + +static struct hyn_ts_data *gesture_data = NULL; + + +/* sysfs gesture node + * read example: cat hyn_gesture_mode ---read gesture mode + * write example:echo 01 > hyn_gesture_mode ---write gesture mode to 01 + */ + +static ssize_t hyn_gesture_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + int count; + HYN_ENTER(); + mutex_lock(&gesture_data->mutex_fs); + count = sprintf(buf, "Gesture Mode: %s\n", gesture_data->gesture_is_enable ? "On" : "Off"); + count += sprintf(buf + count, "Reg = %d\n", gesture_data->gesture_id); + mutex_unlock(&gesture_data->mutex_fs); + return count; +} + +static ssize_t hyn_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + HYN_ENTER(); + mutex_lock(&gesture_data->mutex_fs); + if (buf[0]==1){ + HYN_INFO("[GESTURE]enable gesture"); + gesture_data->gesture_is_enable= ENABLE; + }else if (buf[0]==0){ + HYN_INFO("[GESTURE]disable gesture"); + gesture_data->gesture_is_enable = DISABLE; + } + mutex_unlock(&gesture_data->mutex_fs); + return count; +} + +static DEVICE_ATTR (hyn_gesture_mode, S_IRUGO|S_IWUSR, hyn_gesture_show, hyn_gesture_store); +static struct attribute *hyn_gesture_mode_attrs[] = +{ + &dev_attr_hyn_gesture_mode.attr, + NULL, +}; + +static struct attribute_group hyn_gesture_group = +{ + .attrs = hyn_gesture_mode_attrs, +}; + +int hyn_gesture_init(struct hyn_ts_data *ts_data) +{ + u8 i; + int ret = -1; + struct input_dev *dev = ts_data->input_dev; + HYN_ENTER(); + gesture_data = ts_data; + for(i = 0; i< sizeof(gesture_key); i++){ + input_set_capability(dev, EV_KEY, gesture_key[i]); + __set_bit(gesture_key[i], dev->keybit); + } + + ts_data->gesture_id = 0xFF; + ts_data->gesture_is_enable = ENABLE; + + ret = sysfs_create_group(&ts_data->dev->kobj, &hyn_gesture_group); + if(ret){ + HYN_ERROR("ges_sys_node creat failed"); + } + return ret; +} + +void hyn_gesture_report(struct hyn_ts_data *ts_data) +{ + struct input_dev *dev = ts_data->input_dev;//ges_input_dev;//ts_data->input_dev; + if(ts_data->gesture_id < sizeof(gesture_key)){ + input_report_key(dev, gesture_key[ts_data->gesture_id], 1); + input_sync(dev); + input_report_key(dev, gesture_key[ts_data->gesture_id], 0); + input_sync(dev); + HYN_INFO("fw gesture idx:%d key value:%d",ts_data->gesture_id,gesture_key[ts_data->gesture_id]); + } +} + +void hyn_gesture_exit(struct hyn_ts_data *ts_data) +{ + sysfs_remove_group(&ts_data->dev->kobj, &hyn_gesture_group); +} diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_i2c.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_i2c.c new file mode 100644 index 000000000000..7790f78bf57d --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_i2c.c @@ -0,0 +1,240 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_i2c.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + +#ifdef I2C_PORT + +#if (I2C_USE_DMA==1) + +int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len) +{ + int ret = -1; + struct i2c_msg i2c_msg; + mutex_lock(&ts_data->mutex_bus); + i2c_msg.addr = ts_data->client->addr; + i2c_msg.flags = I2C_M_RD; + i2c_msg.len = len; + i2c_msg.buf = buf; + ret = i2c_transfer(ts_data->client->adapter, &i2c_msg, 1); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len) +{ + int ret = 0; + struct i2c_msg i2c_msg; + u8 cmd_len = reg_len&0x0F; + if(cmd_len > 4) return -1; + mutex_lock(&ts_data->mutex_bus); + i2c_msg.addr = ts_data->client->addr; + i2c_msg.flags = 0; + i2c_msg.len = len; + i2c_msg.buf = buf; + ret = i2c_transfer(ts_data->client->adapter, &i2c_msg, 1); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen) +{ + int ret = 0,i=0; + struct i2c_msg i2c_msg[2]; + u8 wbuf[4]; + u8 cmd_len = reg_len&0x0F; + if(cmd_len==0 || cmd_len > 4) return -1; + mutex_lock(&ts_data->mutex_bus); + memset(wbuf,0,sizeof(wbuf)); + i = cmd_len; + while(i){ + i--; + wbuf[i] = reg_addr; + reg_addr >>= 8; + } + i2c_msg[0].addr = ts_data->client->addr; + i2c_msg[0].flags = 0; + i2c_msg[0].len = cmd_len; + i2c_msg[0].buf = wbuf; + ret = i2c_transfer(ts_data->client->adapter, &i2c_msg[0], 1); + if(rlen){ + i2c_msg[1].addr = ts_data->client->addr; + i2c_msg[1].flags = I2C_M_RD; + i2c_msg[1].buf = rbuf; + i2c_msg[1].len = rlen; + ret |= i2c_transfer(ts_data->client->adapter, &i2c_msg[1], 1); + } + // ret = i2c_transfer(ts_data->client->adapter, i2c_msg, rlen ? 2:1); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +#elif (I2C_USE_DMA==2) + +int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len) +{ + int ret = 0; + mutex_lock(&ts_data->mutex_bus); + ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG); + memcpy(ts_data->dma_buff_va,buf, len); + ret = i2c_master_send(ts_data->client, (u8 *)ts_data->dma_buff_pa, len); + ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len) +{ + int ret = 0; + mutex_lock(&ts_data->mutex_bus); + ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG); + ret = i2c_master_recv(ts_data->client, (u8 *)ts_data->dma_buff_pa, len); + memcpy(buf, ts_data->dma_buff_va, len); + ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen) +{ + int ret = 0,i=0; + u8 wbuf[4]; + mutex_lock(&ts_data->mutex_bus); + reg_len = reg_len&0x0F; + memset(wbuf,0,sizeof(wbuf)); + i = reg_len; + while(i){ + i--; + wbuf[i] = reg_addr; + reg_addr >>= 8; + } + ts_data->client->addr = ((ts_data->client->addr & I2C_MASK_FLAG) | I2C_DMA_FLAG); + memcpy(ts_data->dma_buff_va,wbuf, reg_len); + ret = i2c_master_send(ts_data->client, (u8 *)ts_data->dma_buff_pa, reg_len); + if(rlen){ + ret |= i2c_master_recv(ts_data->client, (u8 *)ts_data->dma_buff_pa, rlen); + memcpy(rbuf, ts_data->dma_buff_va, rlen); + } + ts_data->client->addr = ts_data->client->addr& I2C_MASK_FLAG & (~I2C_DMA_FLAG); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +#else //0 + +int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len) +{ + int ret = -1; + mutex_lock(&ts_data->mutex_bus); + while(len){ + if(len > HYN_TRANSFER_LIMIT_LEN){ + ret = i2c_master_recv(ts_data->client, buf, HYN_TRANSFER_LIMIT_LEN); + len -= HYN_TRANSFER_LIMIT_LEN; + buf += HYN_TRANSFER_LIMIT_LEN; + } + else{ + ret = i2c_master_recv(ts_data->client, buf, len); + len = 0; + } + if (ret < 0) { + break; + } + } + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} +int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len) +{ + int ret = 0; + u8 cmd_len = reg_len&0x0F; + if(cmd_len > 4) return -1; + mutex_lock(&ts_data->mutex_bus); +#if HYN_TRANSFER_LIMIT_LEN < 1048 + if(len > HYN_TRANSFER_LIMIT_LEN){ + u32 reg = U8TO32(buf[0],buf[1],buf[2],buf[3])>>((4-cmd_len)*8); + u8 w_buf[HYN_TRANSFER_LIMIT_LEN],i; + u16 step = HYN_TRANSFER_LIMIT_LEN-cmd_len; + u16 w_len = 0; + buf += cmd_len; + len -= cmd_len; + while(len){ + i = cmd_len; + while(i--){ + w_buf[cmd_len-1-i] = reg>>(i*8); + } + memcpy(&w_buf[cmd_len],buf,step); + if(0==(reg_len&0x80)){ + reg += step; + } + else{ + reg = (reg&0xffff0000)|((reg>>8)&0xff)|((reg<<8)&0xff00); + reg += step; + reg = (reg&0xffff0000)|((reg>>8)&0xff)|((reg<<8)&0xff00); + } + buf += step; + if(len > step){ + w_len = HYN_TRANSFER_LIMIT_LEN; + len -= step; + } + else{ + w_len = len+cmd_len; + len = 0; + } + ret = i2c_master_send(ts_data->client, w_buf, w_len); + if(ret < 0) break; + } + }else +#endif + { + ret = i2c_master_send(ts_data->client, buf, len); + } + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} + +int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen) +{ + int ret = 0,i=0; + u8 wbuf[4]; + u8 cmd_len = reg_len&0x0F; + if(cmd_len==0 || cmd_len > 4) return -1; + mutex_lock(&ts_data->mutex_bus); + do{ + i = cmd_len-1; + do{ + wbuf[cmd_len-1-i] = reg_addr>>(i*8); + }while(i--); + ret = i2c_master_send(ts_data->client, wbuf, cmd_len); + if(rlen){ + ret |= i2c_master_recv(ts_data->client, rbuf, rlen < HYN_TRANSFER_LIMIT_LEN ? rlen : HYN_TRANSFER_LIMIT_LEN); + } + if(ret < 0 || rlen <= HYN_TRANSFER_LIMIT_LEN) break; + rbuf += HYN_TRANSFER_LIMIT_LEN; + rlen -= HYN_TRANSFER_LIMIT_LEN; + if(0==(reg_len&0x80)){ + reg_addr += HYN_TRANSFER_LIMIT_LEN; + } + else{ + reg_addr = (reg_addr&0xffff0000)|((reg_addr>>8)&0xff)|((reg_addr<<8)&0xff00); + reg_addr += HYN_TRANSFER_LIMIT_LEN; + reg_addr = (reg_addr&0xffff0000)|((reg_addr>>8)&0xff)|((reg_addr<<8)&0xff00); + } + }while(1); + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? -1:0; +} +#endif +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_prox.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_prox.c new file mode 100644 index 000000000000..b2bd79721c65 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_prox.c @@ -0,0 +1,394 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_prox.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + + +static struct hyn_ts_data *hyn_prox_data = NULL; +static const struct hyn_ts_fuc* hyn_prox_fun = NULL; + + +#if (HYN_PROX_TYEP==4) //Spread + +#include +#include +#include + +#define CTP_IOCTL_MAGIC 0x13 +#define CTP_IOCTL_PROX_ON _IOW(CTP_IOCTL_MAGIC, 1, int) +#define CTP_IOCTL_PROX_OFF _IOW(CTP_IOCTL_MAGIC, 2, int) +#define CTP_PROXIMITY_DEVICE_NAME "ltr_558als" //match HAL name + +static long hyn_ioctl_operate(struct file *file, unsigned int cmd, unsigned long arg) +{ + HYN_INFO("prox_ioctl_operate %d!\n", cmd); + switch(cmd) + { + case CTP_IOCTL_PROX_ON: + hyn_prox_fun->tp_prox_handle(1); + break; + case CTP_IOCTL_PROX_OFF: + hyn_prox_fun->tp_prox_handle(0); + break; + default: + HYN_ERROR("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd)); + return -EINVAL; + } + return 0; +} + +static struct file_operations hyn_proximity_fops = { + .owner = THIS_MODULE, + .open = NULL, + .release = NULL, + .unlocked_ioctl = hyn_ioctl_operate +}; + +struct miscdevice hyn_proximity_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = CTP_PROXIMITY_DEVICE_NAME, //match the hal's name + .fops = &hyn_proximity_fops, + .mode = 0x666, +}; + +int hyn_proximity_int(struct hyn_ts_data *ts_data) +{ + HYN_ENTER(); + int ret; + hyn_prox_data = ts_data; + hyn_prox_fun = ts_data->hyn_fuc_used; + hyn_prox_data->prox_is_enable = 0; + ret = misc_register(&hyn_proximity_misc); + if (ret < 0){ + HYN_ERROR("%s: could not register misc device\n", __func__); + goto misc_device_failed; + } + input_set_abs_params(hyn_prox_data->input_dev, ABS_DISTANCE, 0, 1, 0, 0); + return 0; + misc_device_failed: + return ret; +} + +int hyn_proximity_report(u8 proximity_value) +{ + HYN_ENTER(); + input_report_abs(hyn_prox_data->input_dev, ABS_DISTANCE, proximity_value); + input_mt_sync(hyn_prox_data->input_dev); + input_sync(hyn_prox_data->input_dev); + return 0; +} + +int hyn_proximity_exit(void) +{ + HYN_ENTER(); + misc_deregister(&hyn_proximity_misc); + return 0; +} + +#elif (HYN_PROX_TYEP==3) //alps sensor +#include +//#include +#include +#include + +static int ps_open_report_data(int open) +{ + /* should queue work to report event if is_report_input_direct=true */ + return 0; +} + +/* if use this type of enable , Psensor only enabled but not report inputEvent to HAL */ +static int ps_enable_nodata(int en) +{ + int ret = 0; + HYN_INFO("[PROXIMITY]SENSOR_ENABLE value = %d", en); + /* Enable proximity */ + ret = hyn_prox_fun->tp_prox_handle(en); + return ret; +} + +static int ps_set_delay(u64 ns) +{ + return 0; +} + +static int ps_flush(void) +{ + return ps_flush_report(); +} + +static int ps_batch(int flag, int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs) +{ + int value = 0; + + value = (int)samplingPeriodNs / 1000 / 1000; + return 0; +} + +static int ps_get_data(int *value, int *status) +{ + *value = (int)hyn_prox_data->prox_state; + HYN_INFO("fts_proximity_data.detect = %d\n", *value); + *status = SENSOR_STATUS_ACCURACY_MEDIUM; + return 0; +} + +static int ps_calibration(int type, int value) +{ + return 0; +} + +static int ps_threshold_setting(int type, int value[2]) +{ + return 0; +} + +int ps_local_init(void) +{ + int err = 0; + struct ps_control_path ps_ctl = { 0 }; + struct ps_data_path ps_data = { 0 }; + HYN_ENTER(); + ps_ctl.is_use_common_factory = false; + ps_ctl.open_report_data = ps_open_report_data; + ps_ctl.enable_nodata = ps_enable_nodata; + ps_ctl.batch = ps_batch; + ps_ctl.flush = ps_flush; + ps_ctl.set_delay = ps_set_delay; + ps_ctl.ps_calibration = ps_calibration; + ps_ctl.ps_threshold_setting = ps_threshold_setting; + ps_ctl.is_report_input_direct = true; + ps_ctl.is_support_batch = false; + err = ps_register_control_path(&ps_ctl); + HYN_INFO("psregister control_path %s = %d\n",err? "fail":"success", err); + ps_data.get_data = ps_get_data; + ps_data.vender_div = 100; + err = ps_register_data_path(&ps_data); + HYN_INFO("psregister data_path %s = %d\n",err? "fail":"success", err); + + return err; +} +int ps_local_uninit(void) +{ + return 0; +} + +struct alsps_init_info ps_init_info = { + .name = "hyn_ts", + .init = ps_local_init, + .uninit = ps_local_uninit, +}; + + +int hyn_proximity_int(struct hyn_ts_data *ts_data) +{ + int ret = 0; + HYN_ENTER(); + hyn_prox_data = ts_data; + hyn_prox_fun = ts_data->hyn_fuc_used; + hyn_prox_data->prox_is_enable = 0; + hyn_prox_data->prox_state = PS_FAR_AWAY; + alsps_driver_add(&ps_init_info); + // ps_local_init(); + HYN_INFO("hyn_proximity_int exit"); + return ret; +} + +int hyn_proximity_report(u8 proximity_value) +{ + int ret; + ret = ps_report_interrupt_data(proximity_value); + return ret; +} + +int hyn_proximity_exit(void) +{ + HYN_ENTER(); + return 0; +} + +#elif (HYN_PROX_TYEP==2)//mtk sensor + +#include +#include +#include + +#define SENSOR_DELAY 0 +#define SENSOR_ENABLE 0 +#define SENSOR_GET_DATA 0 +#define SENSOR_STATUS_ACCURACY_MEDIUM 0 + +struct hwmsen_object obj_ps; + +static int hyn_proximiy_operate(void* self, uint32_t command, void* buff_in, int size_in, + void* buff_out, int size_out, int* actualout) +{ + int err = 0,value; + HYN_INFO("prox command = 0x%02X\n", command); + switch (command) + { + case SENSOR_DELAY: + if((buff_in == NULL) || (size_in < sizeof(int))){ + HYN_ERROR("Set delay parameter error!\n"); + err = -EINVAL; + } + // Do nothing + break; + + case SENSOR_ENABLE: + if((buff_in == NULL) || (size_in < sizeof(int))){ + HYN_ERROR("Enable sensor parameter error!\n"); + err = -EINVAL; + }else{ + value = *(int *)buff_in; + hyn_prox_fun->tp_prox_handle(value > 0 ? 1 : 0); + } + break; + + case SENSOR_GET_DATA: + if((buff_out == NULL)){ + HYN_ERROR("get sensor data parameter error!\n"); + err = -EINVAL; + }else{ + hyn_proximity_report(hyn_prox_data->prox_state); + } + break; + default: + HYN_ERROR("proxmy sensor operate function no this parameter %d!\n", command); + err = -1; + break; + } + return err; +} + +int hyn_proximity_int(struct hyn_ts_data *ts_data) +{ + HYN_ENTER(); + int ret; + hyn_prox_data = ts_data; + hyn_prox_fun = ts_data->hyn_fuc_used; + hyn_prox_data->prox_is_enable = 0; + obj_ps.polling = 0;//interrupt mode + obj_ps.sensor_operate = hyn_proximiy_operate; + ret = hwmsen_attach(ID_PROXIMITY, &obj_ps); + return ret; +} + +int hyn_proximity_report(u8 proximity_value) +{ + HYN_ENTER(); + int ret=0; + struct hwm_sensor_data sensor_data; + sensor_data.values[0] = proximity_value; + sensor_data.value_divide = 1; + sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM; + ret = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data); + if (ret){ + HYN_ERROR(" proxi call hwmsen_get_interrupt_data failed= %d\n", err); + } + return ret; +} + +int hyn_proximity_exit(void) +{ + HYN_ENTER(); + return 0; +} + +#elif (HYN_PROX_TYEP==1)//default sensor + +static ssize_t hyn_prox_show(struct device *dev,struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "proximity is %s value:%d\n",hyn_prox_data->prox_is_enable ? "enable":"disable" ,hyn_prox_data->prox_state); +} + +/* Allow users to enable/disable prox */ +static ssize_t hyn_prox_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count) +{ + unsigned long enable; + enable = simple_strtoul(buf, NULL, 10); + hyn_prox_fun->tp_prox_handle(enable > 0 ? 1 : 0); + return count; +} + +static DEVICE_ATTR (hyn_prox_enable, S_IRUGO|S_IWUSR, hyn_prox_show, hyn_prox_store); +static struct attribute *hyn_prox_enable_attrs[] = +{ + &dev_attr_hyn_prox_enable.attr, + NULL, +}; + +static struct attribute_group hyn_prox_group = +{ + .attrs = hyn_prox_enable_attrs, +}; + +int hyn_proximity_int(struct hyn_ts_data *ts_data) +{ + HYN_ENTER(); + int ret; + hyn_prox_data = ts_data; + hyn_prox_fun = ts_data->hyn_fuc_used; + hyn_prox_data->prox_is_enable = 0; + __set_bit(KEY_SLEEP, hyn_prox_data->input_dev->evbit); + __set_bit(KEY_WAKEUP, hyn_prox_data->input_dev->evbit); + + ret = sysfs_create_group(&ts_data->dev->kobj, &hyn_prox_group); + if(ret){ + HYN_ERROR("prox_sys_node creat failed"); + } + return ret; +} + +int hyn_proximity_report(u8 proximity_value) +{ + HYN_ENTER(); + int keycode = proximity_value ? KEY_SLEEP:KEY_WAKEUP; + input_report_key(hyn_prox_data->input_dev, keycode, 1); + input_sync(hyn_prox_data->input_dev); + input_report_key(hyn_prox_data->input_dev, keycode, 0); + input_sync(hyn_prox_data->input_dev); + return 0; +} + +int hyn_proximity_exit(void) +{ + HYN_ENTER(); + sysfs_remove_group(&hyn_prox_data->dev->kobj, &hyn_prox_group); + return 0; +} +#elif (HYN_PROX_TYEP==0) +int hyn_proximity_int(struct hyn_ts_data *ts_data) +{ + HYN_ENTER(); + hyn_prox_data = ts_data; + hyn_prox_fun = ts_data->hyn_fuc_used; + return 0; +} + +int hyn_proximity_report(u8 proximity_value) +{ + HYN_ENTER(); + return 0; +} + +int hyn_proximity_exit(void) +{ + HYN_ENTER(); + return 0; +} + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_spi.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_spi.c new file mode 100644 index 000000000000..8de02cfe374c --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_spi.c @@ -0,0 +1,100 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_spi.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + +#ifndef I2C_PORT + +int hyn_write_data(struct hyn_ts_data *ts_data, u8 *buf, u8 reg_len, u16 len) +{ + struct spi_message msg; + struct spi_transfer transfer[1] = { {0} }; + int ret; + mutex_lock(&ts_data->mutex_bus); + + spi_message_init(&msg); + transfer[0].len = len; + transfer[0].delay_usecs = SPI_DELAY_CS; + transfer[0].tx_buf = buf; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); + ret = spi_sync(ts_data->client, &msg); + + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? ret:0; +} + +int hyn_read_data(struct hyn_ts_data *ts_data,u8 *buf, u16 len) +{ + struct spi_message msg; + struct spi_transfer transfer[1] = { {0} }; + int ret; + mutex_lock(&ts_data->mutex_bus); + + spi_message_init(&msg); + transfer[0].len = len; + transfer[0].delay_usecs = SPI_DELAY_CS; + transfer[0].tx_buf = NULL; + transfer[0].rx_buf = buf; + spi_message_add_tail(&transfer[0], &msg); + ret = spi_sync(ts_data->client, &msg); + + mutex_unlock(&ts_data->mutex_bus); + return ret < 0 ? ret:0; +} + +int hyn_wr_reg(struct hyn_ts_data *ts_data, u32 reg_addr, u8 reg_len, u8 *rbuf, u16 rlen) +{ + int ret = 0,i=0; + struct spi_message msg; + struct spi_transfer transfer[2] = { {0}, {0} }; + u8 cmd[4]; + mutex_lock(&ts_data->mutex_bus); + reg_len = reg_len&0x0F; + memset(cmd,0,sizeof(cmd)); + i = reg_len; + while(i){ + i--; + cmd[i] = reg_addr; + reg_addr >>= 8; + } + spi_message_init(&msg); + transfer[0].len = reg_len; + transfer[0].tx_buf = cmd; + transfer[0].rx_buf = NULL; + spi_message_add_tail(&transfer[0], &msg); + ret = spi_sync(ts_data->client, &msg); + if (ret < 0) { + mutex_unlock(&ts_data->mutex_bus); + return ret; + } + udelay(20); + if (rlen > 0) { + spi_message_init(&msg); + transfer[1].len = rlen; + transfer[1].delay_usecs = SPI_DELAY_CS; + transfer[1].tx_buf = NULL; + transfer[1].rx_buf = rbuf; + spi_message_add_tail(&transfer[1], &msg); + ret = spi_sync(ts_data->client, &msg); + } + + mutex_unlock(&ts_data->mutex_bus); + + return ret < 0 ? ret:0; +} + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_tool.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_tool.c new file mode 100644 index 000000000000..4b7bdce6b9bb --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_tool.c @@ -0,0 +1,352 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_tool.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + +#if HYN_APK_DEBUG_EN + +#define HYN_PROC_DIR_NAME "hyn_apk_tool" +#define HYN_PROC_NODE_NAME "fops_nod" + +static struct hyn_ts_data *hyn_tool_data = NULL; +static const struct hyn_ts_fuc* hyn_tool_fun = NULL; + +static struct proc_dir_entry *g_tool_dir = NULL; +static struct proc_dir_entry *g_tool_node = NULL; + +static int misc_state = -1; + +#define READ_TPINF (0x0A) +#define WRITE_IIC (0x1A) //len +#define READ_REG (0x2A) +#define READ_IIC (0x3A) +#define SET_WORK_MODE (0x7A) +#define RESET_IC (0xCA) +#define UPDATA_FW (0xAC) + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) +static int hyn_proc_tool_read(char *user_buf, char **start, off_t off, int count, int *eof, void *f_pos) +{ + unsigned char *buf = NULL; + int ret_len = 0,ret = 0,copy_len = 0; + int mt_total_len = hyn_tool_data->hw_info.fw_sensor_rxnum*hyn_tool_data->hw_info.fw_sensor_txnum*2 + + (hyn_tool_data->hw_info.fw_sensor_rxnum + hyn_tool_data->hw_info.fw_sensor_txnum)*2; + u8 *cmd = hyn_tool_data->host_cmd_save; + mutex_lock(&hyn_tool_data->mutex_fs); + + if(*f_pos != 0){ + goto tool_read_end; + } + ret_len = (mt_total_len + sizeof(struct ts_frame))*2; + // if(ret_len > count){ + // ret_len = count; + // } + if(hyn_tool_data->work_mode == FAC_TEST_MODE){ + ret_len += mt_total_len; + } + copy_len = ret_len > count ? count:ret_len; + buf = kzalloc(ret_len, GFP_KERNEL); + // buf = kzalloc(ret_len, GFP_KERNEL); + if(buf == NULL){ + HYN_ERROR("zalloc GFP_KERNEL memory failed.\n"); + goto tool_read_end; + } + if(DIFF_MODE <= hyn_tool_data->work_mode && FAC_TEST_MODE >= hyn_tool_data->work_mode){ + wait_event_interruptible_timeout(hyn_tool_data->wait_irq,(atomic_read(&hyn_tool_data->hyn_irq_flg)==1),msecs_to_jiffies(500)); // + atomic_set(&hyn_tool_data->hyn_irq_flg,0); + if(hyn_tool_data->work_mode == FAC_TEST_MODE){ + if(NULL != hyn_tool_fun->tp_get_test_result){ + u8 restut[4]; + if(buf == NULL){ + HYN_ERROR("zalloc GFP_KERNEL memory failed.\n"); + goto tool_read_end; + } + *(int*)&restut = hyn_tool_fun->tp_get_test_result(buf,ret_len); + HYN_INFO("test ret = %d",ret); + memcpy(user_buf,restut,4); + memcpy(user_buf+4,buf,copy_len-4); + } + } + else{ + ret = hyn_tool_fun->tp_get_dbg_data(buf,ret_len); + if(ret > 0) + memcpy(user_buf,buf,copy_len); + } + } + else{ + if(cmd[0] == READ_REG){ //0:head 1~4:reg 5:reg_len 6~7:read_len + u32 reg_addr = U8TO32(cmd[4],cmd[3],cmd[2],cmd[1]); //eg (read A1 A2 len 256):2A 00 00 A1 A2 02 FF 00 + ret = hyn_wr_reg(hyn_tool_data,reg_addr,cmd[5],buf,copy_len); + memcpy(user_buf,buf,copy_len); + } + else if(cmd[0] == READ_IIC){ //0:head 1~2:read_len + ret = hyn_read_data(hyn_tool_data,buf,copy_len); + memcpy(user_buf,buf,copy_len); + } + else if(cmd[0] == READ_TPINF){ + memcpy(user_buf,&hyn_tool_data->hw_info,sizeof(hyn_tool_data->hw_info)); + } + else if(cmd[0] == UPDATA_FW){ + ret_len = sizeof(hyn_tool_data->fw_updata_process); + memcpy(user_buf,&hyn_tool_data->fw_updata_process,copy_len); + msleep(1); + } + } +tool_read_end: + if(!IS_ERR_OR_NULL(buf)){ + kfree(buf); + } + mutex_unlock(&hyn_tool_data->mutex_fs); + // HYN_INFO("count = %d copy len = %d ret = %d\r\n",(int)count,ret_len,ret); + return count; +} +#else + +static int hyn_proc_tool_open(struct inode *pinode, struct file *pfile) +{ + HYN_ENTER(); + return 0; +} + +static ssize_t hyn_proc_tool_read(struct file *page,char __user *user_buf, size_t count, loff_t *f_pos) +{ + unsigned char *buf = NULL; + int ret_len = 0,ret = 0,copy_len = 0; + int mt_total_len = hyn_tool_data->hw_info.fw_sensor_rxnum*hyn_tool_data->hw_info.fw_sensor_txnum*2 + + (hyn_tool_data->hw_info.fw_sensor_rxnum + hyn_tool_data->hw_info.fw_sensor_txnum)*2; + u8 *cmd = hyn_tool_data->host_cmd_save; + mutex_lock(&hyn_tool_data->mutex_fs); + + if(*f_pos != 0){ + goto tool_read_end; + } + ret_len = (mt_total_len + sizeof(struct ts_frame))*2; + // if(ret_len > count){ + // ret_len = count; + // } + if(hyn_tool_data->work_mode == FAC_TEST_MODE){ + ret_len += mt_total_len; + } + copy_len = ret_len > count ? count:ret_len; + buf = kzalloc(ret_len, GFP_KERNEL); + // buf = kzalloc(ret_len, GFP_KERNEL); + if(buf == NULL){ + HYN_ERROR("zalloc GFP_KERNEL memory failed.\n"); + goto tool_read_end; + } + if(DIFF_MODE <= hyn_tool_data->work_mode && FAC_TEST_MODE >= hyn_tool_data->work_mode){ + wait_event_interruptible_timeout(hyn_tool_data->wait_irq,(atomic_read(&hyn_tool_data->hyn_irq_flg)==1),msecs_to_jiffies(500)); // + atomic_set(&hyn_tool_data->hyn_irq_flg,0); + if(hyn_tool_data->work_mode == FAC_TEST_MODE){ + if(NULL != hyn_tool_fun->tp_get_test_result){ + u8 restut[4]; + if(buf == NULL){ + HYN_ERROR("zalloc GFP_KERNEL memory failed.\n"); + goto tool_read_end; + } + *(int*)&restut = hyn_tool_fun->tp_get_test_result(buf,ret_len); + HYN_INFO("test ret = %d",ret); + ret = copy_to_user(user_buf,restut,4); + ret |= copy_to_user(user_buf+4,buf,copy_len-4); + if (ret) + HYN_INFO("FAC_TEST_MODE copy_to_user ret = %d",ret); + } + } + else{ + ret = hyn_tool_fun->tp_get_dbg_data(buf,ret_len); + if(ret > 0) { + ret = copy_to_user(user_buf,buf,copy_len); + if (ret) + HYN_INFO("other work_mode copy_to_user ret = %d",ret); + } + } + } + else{ + if(cmd[0] == READ_REG){ //0:head 1~4:reg 5:reg_len 6~7:read_len + u32 reg_addr = U8TO32(cmd[4],cmd[3],cmd[2],cmd[1]); //eg (read A1 A2 len 256):2A 00 00 A1 A2 02 FF 00 + hyn_wr_reg(hyn_tool_data,reg_addr,cmd[5],buf,copy_len); + ret = copy_to_user(user_buf,buf,copy_len); + if (ret) + HYN_INFO("READ_REG copy_to_user ret = %d",ret); + } + else if(cmd[0] == READ_IIC){ //0:head 1~2:read_len + hyn_read_data(hyn_tool_data,buf,copy_len); + ret = copy_to_user(user_buf,buf,copy_len); + if (ret) + HYN_INFO("READ_IIC copy_to_user ret = %d",ret); + } + else if(cmd[0] == READ_TPINF){ + ret = copy_to_user(user_buf,&hyn_tool_data->hw_info,sizeof(hyn_tool_data->hw_info)); + if (ret) + HYN_INFO("READ_TPINF copy_to_user ret = %d",ret); + } + else if(cmd[0] == UPDATA_FW){ + // ret_len = sizeof(hyn_tool_data->fw_updata_process); + ret = copy_to_user(user_buf,&hyn_tool_data->fw_updata_process,copy_len); + if (ret) + HYN_INFO("UPDATA_FW copy_to_user ret = %d",ret); + msleep(1); + } + } +tool_read_end: + if(!IS_ERR_OR_NULL(buf)){ + kfree(buf); + } + mutex_unlock(&hyn_tool_data->mutex_fs); + // HYN_INFO("count = %d copy len = %d ret = %d\r\n",(int)count,ret_len,ret); + return count; +} +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) +static int hyn_proc_tool_write(struct file *file, const char __user *buffer,size_t count, void *data) +#else +static ssize_t hyn_proc_tool_write(struct file *file, const char __user *buffer,size_t count, loff_t *data) +#endif +{ + u8 *cmd = NULL; + int ret = 0; + HYN_ENTER(); + mutex_lock(&hyn_tool_data->mutex_fs); + #define MAX_W_SIZE (1024+8) + if(count > MAX_W_SIZE){ + ret = -1; + HYN_ERROR("count > MAX_W_SIZE\n"); + goto ERRO_WEND; + } + cmd = kzalloc(count, GFP_KERNEL); + if(IS_ERR_OR_NULL(cmd)){ + ret = -1; + HYN_ERROR("kzalloc failed\n"); + goto ERRO_WEND; + } + if(copy_from_user(cmd, buffer, count)){ + ret = -1; + HYN_ERROR("copy data from user space failed.\n"); + goto ERRO_WEND; + } + memcpy(hyn_tool_data->host_cmd_save,cmd,count host_cmd_save) ? count:sizeof(hyn_tool_data->host_cmd_save)); + HYN_INFO("cmd:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x***len:%d ", cmd[0], cmd[1],cmd[2], cmd[3],cmd[4], cmd[5],cmd[6], cmd[7],(u16)count); + + switch(cmd[0]){ + case UPDATA_FW: // apk download bin + HYN_INFO("updata file_name =%s",&cmd[1]); + snprintf(hyn_tool_data->fw_file_name, sizeof(hyn_tool_data->fw_file_name), "%127.127s", &cmd[1]); + hyn_tool_data->fw_updata_process = 0; + if(0==queue_work(hyn_tool_data->hyn_workqueue,&hyn_tool_data->work_updata_fw)){ + HYN_ERROR("queue_work work_updata_fw failed"); + } + break; + case SET_WORK_MODE:// + atomic_set(&hyn_tool_data->hyn_irq_flg,0); + ret = hyn_tool_fun->tp_set_workmode(cmd[1],0); + break; + case RESET_IC: + hyn_tool_fun->tp_rest(); + break; + case WRITE_IIC: // + ret = hyn_write_data(hyn_tool_data,&cmd[1],2,count-1); + break; + default: + break; + } +ERRO_WEND: + if(!IS_ERR_OR_NULL(cmd)){ + kfree(cmd); + } + mutex_unlock(&hyn_tool_data->mutex_fs); + return ret == 0 ? count:-1; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) +static const struct file_operations proc_tool_fops = { + .owner = THIS_MODULE, + .open = hyn_proc_tool_open, + .read = hyn_proc_tool_read, + .write = hyn_proc_tool_write, +}; + +static struct miscdevice hyn_tool_dev = { + .fops = &proc_tool_fops, + .minor = MISC_DYNAMIC_MINOR, + .name = HYN_PROC_DIR_NAME, + .mode = S_IFREG|S_IRWXUGO, +}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) +static const struct proc_ops proc_tool_ops = { ////>=5.06 + .proc_read = hyn_proc_tool_read, + .proc_write = hyn_proc_tool_write, +}; +#endif +#endif + + + +int hyn_tool_fs_int(struct hyn_ts_data *ts_data) +{ + int ret = 0; + hyn_tool_data = ts_data; + hyn_tool_fun = ts_data->hyn_fuc_used; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) + ret = misc_register(&hyn_tool_dev); + misc_state = ret; + HYN_INFO("hyn_tool_dev register %s",ret ? "failed":"success"); +#endif + g_tool_dir = proc_mkdir(HYN_PROC_DIR_NAME, NULL); + if (IS_ERR_OR_NULL(g_tool_dir)){ + HYN_INFO("proc_mkdir %s failed.\n",HYN_PROC_DIR_NAME); + return -1; + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) + g_tool_node = create_proc_entry(HYN_PROC_NODE_NAME, 0644, g_tool_dir); + g_tool_node->write_proc = hyn_proc_tool_write; + g_tool_node->read_proc = hyn_proc_tool_read; +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) //>=3.10 + g_tool_node = proc_create(HYN_PROC_NODE_NAME, 0644|S_IFREG, g_tool_dir, &proc_tool_fops); + //proc_create_data(HYN_PROC_NODE_NAME, 0644 | S_IFREG, g_tool_dir, (void *)&proc_tool_fops, (void *)ts_data->client); +#else + g_tool_node = proc_create(HYN_PROC_NODE_NAME, 0644|S_IFREG, g_tool_dir, &proc_tool_ops); +#endif + if (IS_ERR_OR_NULL(g_tool_node)) { + HYN_INFO("proc_create %s failed.\n",HYN_PROC_NODE_NAME); + remove_proc_entry(HYN_PROC_DIR_NAME, NULL); + return -ENOMEM; + } + HYN_INFO("apk node creat success"); + return 0; +} + +void hyn_tool_fs_exit(void) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) + if(!IS_ERR_OR_NULL(g_tool_dir)){ + remove_proc_entry(HYN_PROC_DIR_NAME, NULL); + } +#else + if(!IS_ERR_OR_NULL(g_tool_dir)){ + proc_remove(g_tool_dir); + } + if(0==misc_state){ + misc_deregister(&hyn_tool_dev); + } +#endif +} + +#endif diff --git a/drivers/input/touchscreen/hyn/hyn_lib/hyn_ts_ext.c b/drivers/input/touchscreen/hyn/hyn_lib/hyn_ts_ext.c new file mode 100644 index 000000000000..e174eec2a474 --- /dev/null +++ b/drivers/input/touchscreen/hyn/hyn_lib/hyn_ts_ext.c @@ -0,0 +1,518 @@ +/* + * drivers/input/touchscreen/hyn_driver_release/hyn_lib/hyn_ts_ext.c + * + * hynitron TouchScreen driver. + * + * Copyright (c) 2025 hynitron + * + * 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 "../hyn_core.h" + +int hyn_power_source_ctrl(struct hyn_ts_data *ts_data, int enable) +{ + int ret = 0; + HYN_ENTER(); + if(IS_ERR_OR_NULL(ts_data) || IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){ + return ret; + } + if(ts_data->power_is_on != enable){ + if(enable){ + if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){ + ret |= regulator_enable(ts_data->plat_data.vdd_ana); + } + if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)){ + ret |= regulator_enable(ts_data->plat_data.vdd_i2c); + } + } + else{ + if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_ana)){ + ret |= regulator_disable(ts_data->plat_data.vdd_ana); + } + if(!IS_ERR_OR_NULL(ts_data->plat_data.vdd_i2c)){ + ret |= regulator_disable(ts_data->plat_data.vdd_i2c); + } + } + ts_data->power_is_on = enable; + } + if(ret) + HYN_ERROR("set vdd %s regulator failed,ret=%d",enable ? "off":"on",ret); + return ret; +} + +void hyn_irq_set(struct hyn_ts_data *ts_data, u8 value) +{ + // HYN_ENTER(); + if(atomic_read(&ts_data->irq_is_disable) != value){ + if(value ==0){ + disable_irq(ts_data->gpio_irq); + msleep(1); //wait switch + } + else{ + enable_irq(ts_data->gpio_irq); + } + atomic_set(&ts_data->irq_is_disable,value); + // HYN_INFO("IRQ %d",value); + } +} + +void hyn_set_i2c_addr(struct hyn_ts_data *ts_data,u8 addr) +{ +#ifdef I2C_PORT + ts_data->client->addr = addr; +#endif +} + +u16 hyn_sum16(int val, u8* buf,u16 len) +{ + u16 sum = val; + while(len--) sum += *buf++; + return sum; +} + +u32 hyn_sum32(int val, u32* buf,u16 len) +{ + u32 sum = val; + while(len--) sum += *buf++; + return sum; +} + +void hyn_esdcheck_switch(struct hyn_ts_data *ts_data, u8 enable) +{ +#if ESD_CHECK_EN + if(IS_ERR_OR_NULL(ts_data->hyn_workqueue) || IS_ERR_OR_NULL(&ts_data->esdcheck_work)) return; + if(enable){ + ts_data->esd_fail_cnt = 0; + queue_delayed_work(ts_data->hyn_workqueue, &ts_data->esdcheck_work, + msecs_to_jiffies(1000)); + } + else{ + cancel_delayed_work_sync(&ts_data->esdcheck_work); + } +#endif +} + +int hyn_copy_for_updata(struct hyn_ts_data *ts_data,u8 *buf,u32 offset,u16 len) +{ + int ret = -1; +#if (HYN_GKI_VER==0) + struct file *fp; + loff_t pos; + u8 *pdata; + + // HYN_ENTER(); + + if(strlen(ts_data->fw_file_name) == 0) + return ret; + fp = filp_open(ts_data->fw_file_name,O_RDONLY, 0);// + if (IS_ERR(fp)) { + HYN_INFO("open file %s failed \r\n", ts_data->fw_file_name); + return -EIO; + } + + // fp->f_op->llseek(fp, offset, 0); + fp->f_op->llseek(fp, 0, 0); + pdata = kzalloc(len, GFP_KERNEL); + if(IS_ERR_OR_NULL(pdata)){ + HYN_ERROR("kzalloc failed"); + filp_close(fp, NULL); + return -1; + } + pos = offset; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0) + { + mm_segment_t old_fs; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret=vfs_read(fp, pdata, len, &pos); + set_fs(old_fs); + } +#else + ret = hyn_fs_read(fp,pdata, len,&pos); +#endif + filp_close(fp, NULL); + // HYN_INFO("rlen = %d nlen = %d",ret,len); + if(ret <= len){ + memcpy(buf,pdata,len); + ret = 0; + } + else{ + ret = -3; + } + kfree(pdata); +#endif + return ret; +} + +int hyn_wait_irq_timeout(struct hyn_ts_data *ts_data,int msec) +{ + atomic_set(&ts_data->hyn_irq_flg,0); + while(msec--){ + msleep(1); + if(atomic_read(&ts_data->hyn_irq_flg)==1){ + atomic_set(&ts_data->hyn_irq_flg,0); + msec = -1; + break; + } + } + return msec == -1 ? 0:-1; +} + +#define MAX_WROD_LEN (64) +int hyn_get_word(u8**sc_str, u8* ds_str) +{ + u8 ch,cnt = 0,nul_flg = 0; + while(1){ + ch = **sc_str; + *sc_str += 1; + if((ch==' '&& nul_flg) || ch=='\t' || ch=='\0' || (ch=='\r' && **sc_str == '\n') || ch=='\n'|| ch==','|| ch=='=' || cnt>=MAX_WROD_LEN){ + *ds_str++ = '\0'; + break; + } + if(ch >= 'A' && ch <= 'Z') ch = ch + 'a' - 'A'; + if(ch!=' '){ + *ds_str++ = ch; + nul_flg = 1; + } + cnt++; + } + return cnt; +} + +int hyn_str_2_num(char *str,u8 type) +{ + int ret = 0,step = 0,flg = 0,cnt = 15; + char ch; + while(*str != '\0' && --cnt){ + ch = *str++; + if(ch==' ') continue; + else if(ch=='-' && step==0){ + flg = 1; + continue; + } + if(type == 10){ + if(ch <= '9' && ch >= '0'){ + step++; + ret *= 10; + ret += (ch - '0'); + } + else{ + cnt = 0; + break; + } + } + else{ + if(ch <= '9' && ch >= '0'){ + step++; + ret *= 16; + ret += (ch - '0'); + } + else if(ch <= 'f' && ch >= 'a'){ + step++; + ret *= 16; + ret += (10 + ch - 'a'); + } + else{ + cnt = 0; + break; + } + } + } + // if(cnt == 0 || step==0)HYN_ERROR("failed"); + return (cnt == 0 || step==0) ? 0xAC5AC5AC : (flg ? -ret:ret); +} + +static int hyn_get_threshold(char *filename,char *match_string,s16 *pstore, u16 len) +{ + int ret = 0; + HYN_ENTER(); +#if (HYN_GKI_VER==0) + { + u8 *buf = NULL,*ptr = NULL; + u8 tmp_word[66]; + u16 i; + int dec,cnt; + off_t fsize; + struct file *fp; + loff_t pos; + + if(strlen(filename) == 0) + return ret; + + fp = filp_open(filename, O_RDONLY, 0); + if (IS_ERR(fp)) { + HYN_INFO("error occurred while opening file %s.\n", filename); + return -EIO; + } + fp->f_op->llseek(fp, 0, 0); + fsize = fp->f_inode->i_size; + buf = vmalloc(fsize); + if(IS_ERR_OR_NULL(buf)){ + HYN_ERROR("vmalloc failed"); + filp_close(fp, NULL); + return -1; + } + pos = 0; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0) + {mm_segment_t old_fs; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret=vfs_read(fp,buf, fsize, &pos); + set_fs(old_fs);} +#else + ret = hyn_fs_read(fp,buf,fsize,&pos); +#endif + HYN_INFO("read %s %s.ret:%d.\n",filename,ret==fsize ? "success":"failed",ret); + filp_close(fp, NULL); + +////read finsh start match key string + i = fsize; + ptr = buf; + while(--i){ + if(*ptr++ == '\n'){ + cnt = strlen(match_string); + while(--cnt){ + if(ptr[cnt]!= match_string[cnt]){ + break; + } + } + if(cnt == 0 && ptr[0]== match_string[0]){ + // HYN_INFO("match %s",match_string); + break; //ignor idx 0,1 + } + } + } + if(i == 0){ + ret = -1; + goto MATCH_FAIL1; + } + +///////match key string end + i = 0; + while(i<10){ + cnt = hyn_get_word(&ptr,tmp_word); + if(cnt==0){ + i++; + continue; + } + // HYN_INFO("@@%s",tmp_word); + dec = hyn_str_2_num(tmp_word,10); + if(dec == 0xAC5AC5AC) continue; + *pstore = dec; + pstore++; + i = 0; + if(--len == 0) break; + } + ret = len ? -1:0; + +MATCH_FAIL1: + if(!IS_ERR_OR_NULL(buf)) vfree(buf); + } +#endif + return ret; +} + + +int hyn_factory_multitest(struct hyn_ts_data *ts_data ,char *cfg_path, u8 *data,s16 *test_th,u8 test_item) +{ + int ret = 0; + struct tp_info *ic = &ts_data->hw_info; + u16 mt_len = ic->fw_sensor_rxnum*ic->fw_sensor_txnum,i=0; + u16 st_len = ic->fw_sensor_txnum + ic->fw_sensor_rxnum; + s16 *raw_h,*raw_l,*raw_s,*scap_p,tmp=0; + raw_h = (s16*)data; + raw_l = raw_h + mt_len; + raw_s = raw_l + mt_len; + scap_p = raw_s + st_len; + + if(test_item & MULTI_OPEN_TEST){ + //judge low TH + HYN_INFO("check MULTI_OPEN_TEST OpenMin"); + if(hyn_get_threshold(cfg_path,"TX0OpenMin",test_th,mt_len)){ + HYN_ERROR("read threshold failed"); + return FAC_GET_CFG_FAIL; + } + for(i = mt_len; i< mt_len; i++){ + if(*(raw_h+i)-*(raw_l+i) < test_th[i]) break; + } + if(i == mt_len){ + HYN_INFO("open low pass"); + } + else{ + HYN_ERROR("open low test failed row= %d clo= %d %d<(th)%d" + ,i/ic->fw_sensor_rxnum,i%ic->fw_sensor_rxnum,*(raw_h+i)-*(raw_l+i),test_th[i]); + return FAC_TEST_OPENL_FAIL; + } + //judge high TH + HYN_INFO("check MULTI_OPEN_TEST OpenMax"); + if(hyn_get_threshold(cfg_path,"TX0OpenMax",test_th,mt_len)){ + HYN_ERROR("read threshold failed"); + return FAC_GET_CFG_FAIL; + } + for(i = 0; i< mt_len; i++){ + if(*(raw_h+i)-*(raw_l+i) > test_th[i]) break; + } + if(i == mt_len){ + HYN_INFO("open high pass"); + } + else{ + HYN_ERROR("open high test failed row= %d clo= %d %d>(th)%d" + ,i/ic->fw_sensor_rxnum,i%ic->fw_sensor_rxnum,*(raw_h+i)-*(raw_l+i),test_th[i]); + return FAC_TEST_OPENH_FAIL; + } + } + + if(test_item & MULTI_SHORT_TEST){ + //judge short TH + if(hyn_get_threshold(cfg_path,"FactoryTxShortTh",&tmp,1)){ + HYN_ERROR("read threshold failed"); + return FAC_GET_CFG_FAIL; + } + for(i = 0; i< st_len; i++){ + if(*(raw_s+i) < tmp) break; + } + HYN_INFO("%s,shortth = %d",i == st_len ? "short test pass":"short test failed",tmp); + if(i != st_len){ + return FAC_TEST_SHORT_FAIL; + } + } + + if(test_item & MULTI_SCAP_TEST){ + // self captest + ret = hyn_get_threshold(cfg_path,"RxSCapScanMin",test_th,ic->fw_sensor_rxnum); + ret |= hyn_get_threshold(cfg_path,"TxSCapScanMin",test_th+ic->fw_sensor_rxnum,ic->fw_sensor_txnum); + ret |= hyn_get_threshold(cfg_path,"RxSCapScanMax",test_th+st_len,ic->fw_sensor_rxnum); + ret |= hyn_get_threshold(cfg_path,"TxSCapScanMax",test_th+st_len+ic->fw_sensor_rxnum,ic->fw_sensor_txnum); + if(ret){ + HYN_ERROR("read threshold failed"); + return FAC_GET_CFG_FAIL; + } + else{ + // scap_fix = 128*(test_th[st_len+2] - test_th[2])/(abs(*(scap_p+2))+1); + for(i = 0; i< st_len; i++){ + tmp = *(scap_p+i);//*scap_fix/128; + if(tmp < test_th[i] || tmp > test_th[st_len+i]) break; + } + if(i == st_len){ + HYN_INFO("scap test pass"); + } + else{ + HYN_ERROR("scap test failed[%d] %d<%d>%d",i,test_th[i],tmp,test_th[st_len+i]); + return FAC_TEST_SCAP_FAIL; + } + } + } + return 0; +} + +#if (HYN_GKI_VER==0) +static int arry_to_string(s16 *from,u16 cnt,u8 *des,u16 maxlen) +{ + int str_cnt = 0; + int ret; + while(cnt--){ + ret = snprintf(&des[str_cnt],maxlen, "%d,",*from++); + str_cnt += ret; + if(str_cnt > maxlen-ret){ + str_cnt = maxlen; + HYN_ERROR("str full"); + break; + } + } + return str_cnt; +} +#endif + +int hyn_fac_test_log_save(char *log_name,struct hyn_ts_data *ts_data,s16 *test_data, int test_ret, u8 test_item) +{ + HYN_ENTER(); +#if (HYN_GKI_VER==0) + { + struct file *fp; + u8 w_buf[256],i; + int ret = -1; + if(strlen(log_name) == 0) + return ret; + + fp = filp_open(log_name, O_RDWR | O_CREAT, 0644); + if (IS_ERR(fp)) { + HYN_INFO("error occurred while opening file %s.\n", log_name); + return -EIO; + } + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0) + {mm_segment_t old_fs; + old_fs = get_fs(); + set_fs(KERNEL_DS); + #undef hyn_fs_write + #define hyn_fs_write vfs_write +#endif + ret = snprintf(w_buf,sizeof(w_buf), test_ret ==0 ? "factory test pass\n":"factory test ng\n"); + hyn_fs_write(fp, w_buf, min_t(size_t, ret, sizeof(w_buf)-1), &fp->f_pos); + if(test_ret == FAC_GET_DATA_FAIL){ + ret = snprintf(w_buf,sizeof(w_buf), "read fac_test data fail\n"); + hyn_fs_write(fp, w_buf, ret, &fp->f_pos); + } + else{ + + if(test_item & MULTI_OPEN_TEST){ + ret = snprintf(w_buf,sizeof(w_buf), "open high test data\n"); + hyn_fs_write(fp, w_buf, ret, &fp->f_pos); + for(i = 0; i< ts_data->hw_info.fw_sensor_txnum; i++){ + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + test_data += ts_data->hw_info.fw_sensor_rxnum; + } + + ret = snprintf(w_buf,sizeof(w_buf), "open low test data\n"); + hyn_fs_write(fp, w_buf, ret, &fp->f_pos); + for(i = 0; i< ts_data->hw_info.fw_sensor_txnum; i++){ + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + test_data += ts_data->hw_info.fw_sensor_rxnum; + } + } + + if(test_item & MULTI_SHORT_TEST){ + ret = snprintf(w_buf,sizeof(w_buf), "short test data\n"); + hyn_fs_write(fp, w_buf, ret, &fp->f_pos); + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + test_data += ts_data->hw_info.fw_sensor_rxnum; + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_txnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + test_data += ts_data->hw_info.fw_sensor_txnum; + } + + if(test_item & MULTI_SCAP_TEST){ + ret = snprintf(w_buf,sizeof(w_buf), "scap test data\n"); + hyn_fs_write(fp, w_buf, ret, &fp->f_pos); + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_rxnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + test_data += ts_data->hw_info.fw_sensor_rxnum; + ret = arry_to_string(test_data,ts_data->hw_info.fw_sensor_txnum,w_buf,sizeof(w_buf)-2); + w_buf[ret+1] = '\n'; + hyn_fs_write(fp, w_buf, ret+2, &fp->f_pos); + // test_data += ts_data->hw_info.fw_sensor_txnum; + } + } +#if LINUX_VERSION_CODE <= KERNEL_VERSION(4, 14, 0) + set_fs(old_fs);} +#endif + filp_close(fp, NULL); + } +#endif + return 0; +} diff --git a/drivers/input/touchscreen/hyn/readme.txt b/drivers/input/touchscreen/hyn/readme.txt new file mode 100644 index 000000000000..6bd19a3cc618 --- /dev/null +++ b/drivers/input/touchscreen/hyn/readme.txt @@ -0,0 +1,199 @@ +1、芯片对应关系 +----------匹配符-------------------------函数接口----------支持的芯片型号-------------- + {.compatible = "hyn,66xx", .data = &hyn_cst66xx_fuc,}, /*support 36xx、35xx、66xx、68xx */ + {.compatible = "hyn,36xxes", .data = &hyn_cst36xxes_fuc,}, /*support 154es 3654es 3640es*/ + {.compatible = "hyn,3240", .data = &hyn_cst3240_fuc,}, /*support 3240 */ + {.compatible = "hyn,92xx", .data = &hyn_cst92xx_fuc,}, /*support 9217、9220 */ + {.compatible = "hyn,3xx", .data = &hyn_cst3xx_fuc,}, /*support 340、348、328、128、140、148*/ + {.compatible = "hyn,7xx", .data = &hyn_cst7xx_fuc,}, /*support 726、826、836u*/ + {.compatible = "hyn,8xxt", .data = &hyn_cst8xxT_fuc,}, /*support 816t、816d、820、08C*/ + {.compatible = "hyn,226se", .data = &hyn_cst226se_fuc,}, /*support 226se 8922*/ + + +2、I2c接口最小dts参考配置,下面都是必配项: + hynitron@5A { + compatible = "hyn,66xx"; //根据芯片型号配置 + reg = <0x5A>; //根据芯片型号配置 + + interrupt-parent = <&tlmm>; //根据平台配置 + interrupts = <65 0x02>; //根据平台配置 + reset-gpio = <&tlmm 64 0x01>; //根据平台配置 + irq-gpio = <&tlmm 65 0x02>; //根据平台配置 + + //panel = <&dsi_1080p_video>; //CONFIG_DRM_PANEL 需要配置 + + max-touch-number = <5>; + display-coords = <0 0 800 1280>; + pos-swap = <0>; //xy坐标交换 + posx-reverse = <0>; //x坐标反向 + posy-reverse = <0>; //y坐标反向 + }; + +3、SPI接口最小dts参考配置,下面都是必配项: + spi@78b900{ + hynitron@0 { + compatible = "hyn,66xx"; //根据芯片型号配置 + reg = <0>; //根据芯片型号配置 + spi-max-frequency=<6000000>; //默认配6M + + interrupt-parent = <&tlmm>; //根据平台配置 + interrupts = <65 0x02>; //根据平台配置 + reset-gpio = <&tlmm 64 0x01>; //根据平台配置 + irq-gpio = <&tlmm 65 0x02>; //根据平台配置 + + max-touch-number = <5>; + display-coords = <0 0 800 1280>; + pos-swap = <0>; //xy坐标交换 + posx-reverse = <0>; //x坐标反向 + posy-reverse = <0>; //y坐标反向 + }; + }; + +4、全dts参考配置: + hynitron@5A { + compatible = "hyn,66xx"; + reg = <0x5A>; + vdd_ana-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + + interrupt-parent = <&tlmm>; + interrupts = <65 0x02>; + reset-gpio = <&tlmm 64 0x01>; + irq-gpio = <&tlmm 65 0x02>; + + pinctrl-names = "ts_active","ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + + max-touch-number = <5>; + display-coords = <0 0 800 1280>; + pos-swap = <1>; + posx-reverse = <0>; + posy-reverse = <0>; + + key-number = <0>; + keys = <139 102 158>; + key-y-coord = <2000>; + key-x-coords = <200 600 800>; + }; + +PINCTL配置 + 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_reset_active { + ts_reset_active: ts_reset_active { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + 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; + }; + }; + }; + + pmx_ts_reset_suspend { + ts_reset_suspend: ts_reset_suspend { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + +3、参考Makefile配置: + +obj-y += hynitron_touch.o +hynitron_touch-objs += hyn_core.o hyn_lib/hyn_i2c.o hyn_lib/hyn_spi.o hyn_lib/hyn_ts_ext.o hyn_lib/hyn_fs_node.o +hynitron_touch-objs += hyn_lib/hyn_tool.o +hynitron_touch-objs += hyn_lib/hyn_gesture.o +hynitron_touch-objs += hyn_lib/hyn_prox.o +hynitron_touch-objs += hyn_chips/hyn_cst66xx.o +hynitron_touch-objs += hyn_chips/hyn_cst3240.o +hynitron_touch-objs += hyn_chips/hyn_cst92xx.o +hynitron_touch-objs += hyn_chips/hyn_cst3xx.o +hynitron_touch-objs += hyn_chips/hyn_cst1xx.o +hynitron_touch-objs += hyn_chips/hyn_cst7xx.o +hynitron_touch-objs += hyn_chips/hyn_cst8xxT.o +hynitron_touch-objs += hyn_chips/hyn_cst7xx.o + + +4、sys节点操作 +1、升级 + 通过文件升级 + adb push xxx.bin /sdcard/app.bin + adb shell "echo fd>/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpfwver" + 通过dump升级(GKI version) + adb push xxx.bin /sdcard/app.bin + adb shell "cd /sys/hynitron_debug && echo fwstart>./hyndumpfw && dd if=/sdcard/app.bin of=./hyndumpfw && echo fwend>./hyndumpfw" + +2、write + eg:写 d1 01 02 03 04 + echo w d1 01 02 03 04 >/sys/hynitron_debug/hyntpdbg +3、read + eg 读 20 byte + echo r 20 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg +3、read reg (max reg长度4 byte max read 256 byte) + eg:写 d1 01 读 2 byte + echo w d1 01 r 2 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg + eg:写 d1 01 02 03 读 20 byte + echo w d1 01 02 03 r 20 >/sys/hynitron_debug/hyntpdbg && cat /sys/hynitron_debug/hyntpdbg + 如果reg 不变可以直接用 cat /sys/hynitron_debug/hyntpdbg 读(reg沿用上次的操作) +4、调试log debug + echo 7 >/proc/sys/kernel/printk + echo log,3>/sys/hynitron_debug/hyntpdbg + +5、读版TP_FW本号 + cat /sys/hynitron_debug/hyntpfwver + +6、tp0 自测(需要提前准备自测配置文件) + cat /sys/hynitron_debug/hynselftest + +7、充电模式进入和退出 + enter: + echo c1>/sys/hynitron_debug/hynswitchmode + exit: + echo c0>/sys/hynitron_debug/hynswitchmode +8、手套模式进入和退出 + enter: + echo g1>/sys/hynitron_debug/hynswitchmode + exit: + echo g0>/sys/hynitron_debug/hynswitchmode diff --git a/drivers/media/i2c/gc2093.c b/drivers/media/i2c/gc2093.c index ea2db280f865..e287048f18bc 100644 --- a/drivers/media/i2c/gc2093.c +++ b/drivers/media/i2c/gc2093.c @@ -1857,7 +1857,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&gc2093_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/gc3003.c b/drivers/media/i2c/gc3003.c index a9a55a0210eb..98fb88460512 100644 --- a/drivers/media/i2c/gc3003.c +++ b/drivers/media/i2c/gc3003.c @@ -2055,7 +2055,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&gc3003_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/maxim/remote/Kconfig b/drivers/media/i2c/maxim/remote/Kconfig index f826eec06613..220bf8aff589 100644 --- a/drivers/media/i2c/maxim/remote/Kconfig +++ b/drivers/media/i2c/maxim/remote/Kconfig @@ -74,6 +74,15 @@ config VIDEO_MAXIM_CAM_OV231X To compile this driver as a module, choose M here: the module will be called ov231x. +config VIDEO_MAXIM_CAM_OX03C10 + tristate "Maxim Remote Sensor ox03c10 support" + depends on VIDEO_MAXIM_SERDES + help + This driver supports the remote sensor ox03c10. + + To compile this driver as a module, choose M here: the + module will be called ox03c10. + config VIDEO_MAXIM_CAM_OX03J10 tristate "Maxim Remote Sensor ox03j10 support" depends on VIDEO_MAXIM_SERDES diff --git a/drivers/media/i2c/maxim/remote/Makefile b/drivers/media/i2c/maxim/remote/Makefile index 96144938baa9..82c85bc7e18c 100644 --- a/drivers/media/i2c/maxim/remote/Makefile +++ b/drivers/media/i2c/maxim/remote/Makefile @@ -8,6 +8,7 @@ maxim-dummy-objs := dummy.o maxim-sc320at-objs := sc320at.o maxim-ox01f10-objs := ox01f10.o maxim-ov231x-objs := ov231x.o +maxim-ox03c10-objs := ox03c10.o maxim-ox03j10-objs := ox03j10.o maxim-os04a10-objs := os04a10.o @@ -15,5 +16,6 @@ obj-$(CONFIG_VIDEO_MAXIM_CAM_DUMMY) += maxim-dummy.o obj-$(CONFIG_VIDEO_MAXIM_CAM_SC320AT) += maxim-sc320at.o obj-$(CONFIG_VIDEO_MAXIM_CAM_OX01F10) += maxim-ox01f10.o obj-$(CONFIG_VIDEO_MAXIM_CAM_OV231X) += maxim-ov231x.o +obj-$(CONFIG_VIDEO_MAXIM_CAM_OX03C10) += maxim-ox03c10.o obj-$(CONFIG_VIDEO_MAXIM_CAM_OX03J10) += maxim-ox03j10.o obj-$(CONFIG_VIDEO_MAXIM_CAM_OS04A10) += maxim-os04a10.o diff --git a/drivers/media/i2c/maxim/remote/ox03c10.c b/drivers/media/i2c/maxim/remote/ox03c10.c new file mode 100644 index 000000000000..999259b398e0 --- /dev/null +++ b/drivers/media/i2c/maxim/remote/ox03c10.c @@ -0,0 +1,6042 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim Remote Sensor OmniVision OX03C10 driver + * + * Copyright (C) 2025 Rockchip Electronics Co., Ltd. + * + * Author: Cai Wenzhong + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maxim_remote.h" + +#define DRIVER_VERSION KERNEL_VERSION(1, 0x00, 0x01) + +#ifndef V4L2_CID_DIGITAL_GAIN +#define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN +#endif + +#define OX03C10_NAME "ox03c10" + +#define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode" +#define OF_CAMERA_HDR_OPERATING_MODE "hdr-operating-mode" + +#define OX03C10_XVCLK_FREQ 24000000 + +#define OX03C10_LINK_FREQ_300MHZ 300000000 +#define OX03C10_LINK_FREQ_480MHZ 480000000 + +#define OX03C10_CHIP_ID 0x005803 +#define OX03C10_REG_CHIP_ID 0x300A + +#define OX03C10_REG_CTRL_MODE 0x0100 +#define OX03C10_MODE_SW_STANDBY 0x0 +#define OX03C10_MODE_STREAMING BIT(0) + +#define OX03C10_VTS_MAX 0x7FFF + +#define OX03C10_GAIN_MIN 0x10 +#define OX03C10_GAIN_MAX 0xF7F +#define OX03C10_GAIN_STEP 0x01 +#define OX03C10_GAIN_DEFAULT 0x30 + +// exposure ctrl reg for DCG +#define OX03C10_EXPOSURE_HCG_MIN 4 +#define OX03C10_EXPOSURE_HCG_STEP 1 +#define OX03C10_REG_EXPOSURE_DCG_H 0x3501 // bit[7:0] for exposure[15:8] +#define OX03C10_REG_EXPOSURE_DCG_L 0x3502 // bit[7:0] for exposure[7:0] + +// gain ctrl reg for HCG +#define OX03C10_REG_AGAIN_HCG_H 0x3508 // bit[3:0] for RealGain[7:4] +#define OX03C10_REG_AGAIN_HCG_L 0x3509 // bit[7:4] for RealGain[3:0] +#define OX03C10_REG_DGAIN_HCG_H 0x350A // bit[3:0] for DigitalGain[13:10] +#define OX03C10_REG_DGAIN_HCG_M 0x350B // bit[7:0] for DigitalGain[9:2] +#define OX03C10_REG_DGAIN_HCG_L 0x350C // bit[7:6] for DigitalGain[1:0] + +// gain ctrl reg for LCG +#define OX03C10_REG_AGAIN_LCG_H 0x3588 // bit[3:0] for RealGain[7:4] +#define OX03C10_REG_AGAIN_LCG_L 0x3589 // bit[7:4] for RealGain[3:0] +#define OX03C10_REG_DGAIN_LCG_H 0x358A // bit[3:0] for DigitalGain[13:10] +#define OX03C10_REG_DGAIN_LCG_M 0x358B // bit[7:0] for DigitalGain[9:2] +#define OX03C10_REG_DGAIN_LCG_L 0x358C // bit[7:6] for DigitalGain[1:0] + +// exposure and gain ctrl reg for SPD +#define OX03C10_EXPOSURE_SPD_MIN 4 +#define OX03C10_EXPOSURE_SPD_STEP 1 +#define OX03C10_REG_EXPOSURE_SPD_H 0x3541 // bit[7:0] for exposure[15:8] +#define OX03C10_REG_EXPOSURE_SPD_L 0x3542 // bit[7:0] for exposure[7:0] +#define OX03C10_REG_AGAIN_SPD_H 0x3548 // bit[3:0] for RealGain[7:4] +#define OX03C10_REG_AGAIN_SPD_L 0x3549 // bit[7:4] for RealGain[3:0] +#define OX03C10_REG_DGAIN_SPD_H 0x354A // bit[3:0] for DigitalGain[13:10] +#define OX03C10_REG_DGAIN_SPD_M 0x354B // bit[7:0] for DigitalGain[9:2] +#define OX03C10_REG_DGAIN_SPD_L 0x354C // bit[7:6] for DigitalGain[1:0] + +// exposure and gain ctrl reg for VS +#define OX03C10_EXPOSURE_VS_MIN 4 +#define OX03C10_EXPOSURE_VS_STEP 1 +#define OX03C10_REG_EXPOSURE_VS_H 0x35C1 // bit[7:0] for exposure[15:8] +#define OX03C10_REG_EXPOSURE_VS_L 0x35C2 // bit[7:0] for exposure[7:0] +#define OX03C10_REG_AGAIN_VS_H 0x35C8 // bit[3:0] for RealGain[7:4] +#define OX03C10_REG_AGAIN_VS_L 0x35C9 // bit[7:4] for RealGain[3:0] +#define OX03C10_REG_DGAIN_VS_H 0x35CA // bit[3:0] for DigitalGain[13:10] +#define OX03C10_REG_DGAIN_VS_M 0x35CB // bit[7:0] for DigitalGain[9:2] +#define OX03C10_REG_DGAIN_VS_L 0x35CC // bit[7:6] for DigitalGain[1:0] + +#define OX03C10_GROUP_UPDATE_ADDRESS 0x3208 +#define OX03C10_GROUP_UPDATE_START_DATA 0x00 +#define OX03C10_GROUP_UPDATE_END_DATA 0x10 +#define OX03C10_GROUP_UPDATE_LAUNCH 0xA0 + +#define OX03C10_GROUP1_UPDATE_START_DATA 0x01 +#define OX03C10_GROUP1_UPDATE_END_DATA 0x11 +#define OX03C10_GROUP1_UPDATE_LAUNCH 0xA1 + +#define OX03C10_REG_TEST_PATTERN 0x5040 +#define OX03C10_TEST_PATTERN_ENABLE 0x80 +#define OX03C10_TEST_PATTERN_DISABLE 0x0 + +#define OX03C10_REG_VTS 0x380E + +#define OX03C10_REG_HCG_B_GAIN 0x5280 +#define OX03C10_REG_HCG_GB_GAIN 0x5282 +#define OX03C10_REG_HCG_GR_GAIN 0x5284 +#define OX03C10_REG_HCG_R_GAIN 0x5286 + +#define OX03C10_REG_LCG_B_GAIN 0x5480 +#define OX03C10_REG_LCG_GB_GAIN 0x5482 +#define OX03C10_REG_LCG_GR_GAIN 0x5484 +#define OX03C10_REG_LCG_R_GAIN 0x5486 + +#define OX03C10_REG_SPD_B_GAIN 0x5680 +#define OX03C10_REG_SPD_GB_GAIN 0x5682 +#define OX03C10_REG_SPD_GR_GAIN 0x5684 +#define OX03C10_REG_SPD_R_GAIN 0x5686 + +#define OX03C10_REG_VS_B_GAIN 0x5880 +#define OX03C10_REG_VS_GB_GAIN 0x5882 +#define OX03C10_REG_VS_GR_GAIN 0x5884 +#define OX03C10_REG_VS_R_GAIN 0x5886 + +#define OX03C10_REG_HCG_BLC 0x4026 +#define OX03C10_REG_LCG_BLC 0x4028 +#define OX03C10_REG_SPD_BLC 0x402A +#define OX03C10_REG_VS_BLC 0x402C + +#define OX03C10_VFLIP_REG 0x3820 +#define MIRROR_BIT_MASK BIT(5) +#define FLIP_BIT_MASK BIT(2) + +/* I2C default address */ +#define OX03C10_I2C_ADDR_DEF 0x36 + +/* register address: 16bit */ +#define OX03C10_REG_ADDR_16BITS 2 + +/* register value: 8bit or 16bit or 24bit */ +#define OX03C10_REG_VALUE_08BIT 1 +#define OX03C10_REG_VALUE_16BIT 2 +#define OX03C10_REG_VALUE_24BIT 3 + +#define I2C_REG_NULL 0xFFFF +#define I2C_REG_DELAY 0xFFEE + +struct i2c_regval { + u16 reg_addr; + u8 reg_val; +}; + +/* + * ox03c10 hdr operating mode + * + * Note: Please confirm if the SoC supports RAW16 + * + * Each Pixel has two photo diodes with independent + * exposure gain controls to extend the dynamic range. + * + * LPD: Large Photo Diode + * LPD for HCG, LCG and VS + * SPD: Small Photo Diode + * + * DCG: Dual Conversion Gain + * HCG: High Conversion Gain + * LCG: Low Conversion Gain + * VS: Very Short Exposure + * + * PWL: PieceWise Linear + * HDR3: PWL12, PWL14, PWL16 + * HDR4: PWL12, PWL14, PWL16, PWL20 + * + * LFM: LED Flicker Mitigation + * + * HDR3: DCG (HCG + LCG) + VS or DCG (HCG + LCG) + SPD + * uncompressed 20bit + * HDR4: DCG (HCG + LCG) + SPD + VS + * uncompressed 24bit + */ +enum ox03c10_hdr_operating_mode { + OX03C10_HDR3_DCG_VS_12BIT = 0, + OX03C10_HDR3_DCG_SPD_12BIT = 1, + OX03C10_HDR3_DCG_VS_LFM_16BIT = 2, + OX03C10_HDR_OPERATING_MODE_MAX, +}; + +struct ox03c10_mode { + u32 bus_fmt; + u32 width; + u32 height; + struct v4l2_fract max_fps; + u32 hts_def; + u32 vts_def; + u32 exp_def; + u32 exp_mode; + + u32 link_freq_idx; + u32 bpp; + u32 hdr_mode; + struct rkmodule_hdr_compr *hdr_compr; + u32 hdr_operating_mode; + u32 vc[PAD_MAX]; + const struct i2c_regval *reg_list; + const struct i2c_regval *linear_reg_list; +}; + +struct ox03c10 { + struct i2c_client *client; + struct regulator *poc_regulator; + + struct mutex mutex; + + struct v4l2_subdev subdev; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *anal_gain; + struct v4l2_ctrl *digi_gain; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; + struct v4l2_ctrl *test_pattern; + + struct v4l2_fwnode_endpoint bus_cfg; + + bool streaming; + bool power_on; + + const struct ox03c10_mode *supported_modes; + const struct ox03c10_mode *cur_mode; + u32 cfg_modes_num; + + u32 module_index; + const char *module_facing; + const char *module_name; + const char *len_name; + + bool has_init_exp; + bool has_init_wbgain; + struct preisp_hdrae_exp_s init_hdrae_exp; + struct rkmodule_wb_gain_group init_wbgain; + struct rkmodule_dcg_ratio dcg_ratio; + struct rkmodule_dcg_ratio spd_ratio; + + u8 cam_i2c_addr_def; + u8 cam_i2c_addr_map; + + struct maxim_remote_ser *remote_ser; +}; + +/* + * hdr_operating_mode: OX03C10_HDR3_DCG_SPD_12BIT + */ +static const struct i2c_regval ox03c10_1920x1080_30fps_HDR3_DCG_SPD_PWL12_mipi600[] = { + {0x0103, 0x01}, + {0x0107, 0x01}, + {I2C_REG_DELAY, 6}, + {0x4d5a, 0x1c}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x3208, 0x04}, + {0x4620, 0x04}, + {0x3208, 0x14}, + {0x3208, 0x05}, + {0x4620, 0x04}, + {0x3208, 0x15}, + {0x3208, 0x02}, + {0x3507, 0x00}, + {0x3208, 0x12}, + {0x3208, 0xa2}, + {0x0301, 0xc8}, + {0x0303, 0x01}, + {0x0304, 0x01}, + {0x0305, 0x2c}, + {0x0306, 0x04}, + {0x0307, 0x03}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x00}, + {0x0323, 0x05}, + {0x0324, 0x01}, + {0x0325, 0x2c}, + {0x032e, 0x00}, + {0x032a, 0x04}, + {0x0326, 0x09}, + {0x0327, 0x04}, + {0x0331, 0x04}, + {0x0400, 0xe0}, + {0x0401, 0x80}, + {0x0403, 0xde}, + {0x0404, 0x34}, + {0x0405, 0x3b}, + {0x0406, 0xd4}, + {0x0407, 0x08}, + {0x0408, 0xe0}, + {0x0409, 0x62}, + {0x040a, 0xde}, + {0x040b, 0x34}, + {0x040c, 0x8f}, + {0x040d, 0x9b}, + {0x040e, 0x08}, + {0x2803, 0xfe}, + {0x280b, 0x00}, + {0x280c, 0x79}, + {0x3001, 0x03}, + {0x3002, 0xf8}, + {0x3005, 0x80}, + {0x3007, 0x01}, + {0x3008, 0x80}, + {0x3012, 0x41}, + {0x3020, 0x05}, + {0x3700, 0x28}, + {0x3701, 0x15}, + {0x3702, 0x19}, + {0x3703, 0x23}, + {0x3704, 0x0a}, + {0x3705, 0x00}, + {0x3706, 0x3e}, + {0x3707, 0x0d}, + {0x3708, 0x50}, + {0x3709, 0x5a}, + {0x370a, 0x00}, + {0x370b, 0x96}, + {0x3711, 0x11}, + {0x3712, 0x13}, + {0x3717, 0x02}, + {0x3718, 0x73}, + {0x372c, 0x40}, + {0x3733, 0x01}, + {0x3738, 0x36}, + {0x3739, 0x36}, + {0x373a, 0x25}, + {0x373b, 0x25}, + {0x373f, 0x21}, + {0x3740, 0x21}, + {0x3741, 0x21}, + {0x3742, 0x21}, + {0x3747, 0x28}, + {0x3748, 0x28}, + {0x3749, 0x19}, + {0x3755, 0x1a}, + {0x3756, 0x0a}, + {0x3757, 0x1c}, + {0x3765, 0x19}, + {0x3766, 0x05}, + {0x3767, 0x05}, + {0x3768, 0x13}, + {0x376c, 0x07}, + {0x3778, 0x20}, + {0x377c, 0xc8}, + {0x3781, 0x02}, + {0x3783, 0x02}, + {0x379c, 0x58}, + {0x379e, 0x00}, + {0x379f, 0x00}, + {0x37a0, 0x00}, + {0x37bc, 0x22}, + {0x37c0, 0x01}, + {0x37c4, 0x3e}, + {0x37c5, 0x3e}, + {0x37c6, 0x2a}, + {0x37c7, 0x28}, + {0x37c8, 0x02}, + {0x37c9, 0x12}, + {0x37cb, 0x29}, + {0x37cd, 0x29}, + {0x37d2, 0x00}, + {0x37d3, 0x73}, + {0x37d6, 0x00}, + {0x37d7, 0x6b}, + {0x37dc, 0x00}, + {0x37df, 0x54}, + {0x37e2, 0x00}, + {0x37e3, 0x00}, + {0x37f8, 0x00}, + {0x37f9, 0x01}, + {0x37fa, 0x00}, + {0x37fb, 0x19}, + {0x3c03, 0x01}, + {0x3c04, 0x01}, + {0x3c06, 0x21}, + {0x3c08, 0x01}, + {0x3c09, 0x01}, + {0x3c0a, 0x01}, + {0x3c0b, 0x21}, + {0x3c13, 0x21}, + {0x3c14, 0x82}, + {0x3c16, 0x13}, + {0x3c21, 0x00}, + {0x3c22, 0xf3}, + {0x3c37, 0x12}, + {0x3c38, 0x31}, + {0x3c3c, 0x00}, + {0x3c3d, 0x03}, + {0x3c44, 0x16}, + {0x3c5c, 0x8a}, + {0x3c5f, 0x03}, + {0x3c61, 0x80}, + {0x3c6f, 0x2b}, + {0x3c70, 0x5f}, + {0x3c71, 0x2c}, + {0x3c72, 0x2c}, + {0x3c73, 0x2c}, + {0x3c76, 0x12}, + {0x3182, 0x12}, + {0x320e, 0x00}, + {0x320f, 0x00}, + {0x3211, 0x61}, + {0x3215, 0xcd}, + {0x3219, 0x08}, + {0x3506, 0x20}, + {0x350a, 0x01}, + {0x350b, 0x00}, + {0x350c, 0x00}, + {0x3586, 0x30}, + {0x358a, 0x01}, + {0x358b, 0x00}, + {0x358c, 0x00}, + {0x3541, 0x00}, + {0x3542, 0x04}, + {0x3546, 0x10}, + {0x3548, 0x04}, + {0x3549, 0x40}, + {0x354a, 0x01}, + {0x354b, 0x00}, + {0x354c, 0x00}, + {0x35c1, 0x00}, + {0x35c2, 0x02}, + {0x35c6, 0x90}, + {0x3600, 0x8f}, + {0x3605, 0x16}, + {0x3609, 0xf0}, + {0x360a, 0x01}, + {0x360e, 0x1d}, + {0x360f, 0x10}, + {0x3610, 0x70}, + {0x3611, 0x3a}, + {0x3612, 0x28}, + {0x361a, 0x29}, + {0x361b, 0x6c}, + {0x361c, 0x0b}, + {0x361d, 0x00}, + {0x361e, 0xfc}, + {0x362a, 0x00}, + {0x364d, 0x0f}, + {0x364e, 0x18}, + {0x364f, 0x12}, + {0x3653, 0x1c}, + {0x3654, 0x00}, + {0x3655, 0x1f}, + {0x3656, 0x1f}, + {0x3657, 0x0c}, + {0x3658, 0x0a}, + {0x3659, 0x14}, + {0x365a, 0x18}, + {0x365b, 0x14}, + {0x365c, 0x10}, + {0x365e, 0x12}, + {0x3674, 0x08}, + {0x3677, 0x3a}, + {0x3678, 0x3a}, + {0x3679, 0x19}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3806, 0x05}, + {0x3807, 0x0b}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x04}, + {0x380b, 0x38}, + {0x380c, 0x08}, + {0x380d, 0x8e}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x68}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x381c, 0x18}, + {0x381e, 0x01}, + {0x381f, 0x01}, + {0x3820, 0x00}, + {0x3821, 0x19}, + {0x3832, 0x00}, + {0x3834, 0x00}, + {0x384c, 0x04}, + {0x384d, 0x1a}, + {0x3850, 0x00}, + {0x3851, 0x42}, + {0x3852, 0x00}, + {0x3853, 0x40}, + {0x3858, 0x04}, + {0x388c, 0x04}, + {0x388d, 0x56}, + {0x3b40, 0x05}, + {0x3b41, 0x40}, + {0x3b42, 0x00}, + {0x3b43, 0x90}, + {0x3b44, 0x02}, + {0x3b45, 0x00}, + {0x3b46, 0x02}, + {0x3b47, 0x00}, + {0x3b48, 0x19}, + {0x3b49, 0x12}, + {0x3b4a, 0x16}, + {0x3b4b, 0x2e}, + {0x3b4c, 0x03}, + {0x3b4d, 0x00}, + {0x3b86, 0x00}, + {0x3b87, 0x34}, + {0x3b88, 0x00}, + {0x3b89, 0x08}, + {0x3b8a, 0x05}, + {0x3b8b, 0x00}, + {0x3b8c, 0x07}, + {0x3b8d, 0x80}, + {0x3b8e, 0x00}, + {0x3b8f, 0x00}, + {0x3b92, 0x05}, + {0x3b93, 0x00}, + {0x3b94, 0x07}, + {0x3b95, 0x80}, + {0x3b9e, 0x09}, + {0x3d85, 0x05}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d99, 0x00}, + {0x3d9a, 0x9f}, + {0x3d9b, 0x00}, + {0x3d9c, 0xa0}, + {0x3da4, 0x00}, + {0x3da7, 0x50}, + {0x420e, 0x6b}, + {0x420f, 0x6e}, + {0x4210, 0x06}, + {0x4211, 0xc1}, + {0x421e, 0x02}, + {0x421f, 0x45}, + {0x4220, 0xe1}, + {0x4221, 0x01}, + {0x4301, 0xff}, + {0x4307, 0x03}, + {0x4308, 0x13}, + {0x430a, 0x13}, + {0x430d, 0x93}, + {0x430f, 0x57}, + {0x4310, 0x95}, + {0x4311, 0x16}, + {0x4316, 0x00}, + {0x4317, 0x08}, + {0x4319, 0x03}, + {0x431a, 0x00}, + {0x431b, 0x00}, + {0x431d, 0x2a}, + {0x431e, 0x11}, + {0x431f, 0x20}, + {0x4320, 0x19}, + {0x4323, 0x80}, + {0x4324, 0x00}, + {0x4503, 0x4e}, + {0x4505, 0x00}, + {0x4509, 0x00}, + {0x450a, 0x00}, + {0x4580, 0xf8}, + {0x4583, 0x07}, + {0x4584, 0x6a}, + {0x4585, 0x08}, + {0x4586, 0x05}, + {0x4587, 0x04}, + {0x4588, 0x73}, + {0x4589, 0x05}, + {0x458a, 0x1f}, + {0x458b, 0x02}, + {0x458c, 0xdc}, + {0x458d, 0x03}, + {0x458e, 0x02}, + {0x4597, 0x07}, + {0x4598, 0x40}, + {0x4599, 0x0e}, + {0x459a, 0x0e}, + {0x459b, 0xf5}, + {0x459c, 0xf1}, + {0x4602, 0x00}, + {0x4603, 0x13}, + {0x4604, 0x00}, + {0x4609, 0x60}, + {0x460a, 0x30}, + {0x4610, 0x00}, + {0x4611, 0x40}, + {0x4612, 0x01}, + {0x4613, 0x00}, + {0x4614, 0x00}, + {0x4615, 0x40}, + {0x4616, 0x01}, + {0x4617, 0x00}, + {0x4800, 0x04}, + {0x480a, 0x22}, + {0x4813, 0xe4}, + {0x4814, 0x2a}, + {0x4837, 0x1a}, + {0x484b, 0x47}, + {0x484f, 0x00}, + {0x4887, 0x51}, + {0x4d00, 0x4a}, + {0x4d01, 0x18}, + {0x4d05, 0xff}, + {0x4d06, 0x88}, + {0x4d08, 0x63}, + {0x4d09, 0xdf}, + {0x4d15, 0x7d}, + {0x4d1a, 0x20}, + {0x4d30, 0x0a}, + {0x4d31, 0x00}, + {0x4d34, 0x7d}, + {0x4d3c, 0x7d}, + {0x4f00, 0x3f}, + {0x4f01, 0xff}, + {0x4f02, 0xff}, + {0x4f03, 0x2c}, + {0x4f04, 0xe0}, + {0x6a00, 0x00}, + {0x6a01, 0x20}, + {0x6a02, 0x00}, + {0x6a03, 0x20}, + {0x6a04, 0x02}, + {0x6a05, 0x80}, + {0x6a06, 0x01}, + {0x6a07, 0xe0}, + {0x6a08, 0xcf}, + {0x6a09, 0x01}, + {0x6a0a, 0x40}, + {0x6a20, 0x00}, + {0x6a21, 0x02}, + {0x6a22, 0x00}, + {0x6a23, 0x00}, + {0x6a24, 0x00}, + {0x6a25, 0x00}, + {0x6a26, 0x00}, + {0x6a27, 0x00}, + {0x6a28, 0x00}, + {0x5000, 0x8f}, + {0x5001, 0x75}, + {0x5002, 0x7f}, + {0x5003, 0x7a}, + {0x5004, 0x3e}, + {0x5005, 0x1e}, + {0x5006, 0x1e}, + {0x5007, 0x1e}, + {0x5008, 0x00}, + {0x500c, 0x00}, + {0x502c, 0x00}, + {0x502e, 0x00}, + {0x502f, 0x00}, + {0x504b, 0x00}, + {0x5053, 0x00}, + {0x505b, 0x00}, + {0x5063, 0x00}, + {0x5070, 0x00}, + {0x5074, 0x04}, + {0x507a, 0x04}, + {0x507b, 0x09}, + {0x5500, 0x02}, + {0x5700, 0x02}, + {0x5900, 0x02}, + {0x6007, 0x04}, + {0x6008, 0x05}, + {0x6009, 0x02}, + {0x600b, 0x08}, + {0x600c, 0x07}, + {0x600d, 0x88}, + {0x6016, 0x00}, + {0x6027, 0x04}, + {0x6028, 0x05}, + {0x6029, 0x02}, + {0x602b, 0x08}, + {0x602c, 0x07}, + {0x602d, 0x88}, + {0x6047, 0x04}, + {0x6048, 0x05}, + {0x6049, 0x02}, + {0x604b, 0x08}, + {0x604c, 0x07}, + {0x604d, 0x88}, + {0x6067, 0x04}, + {0x6068, 0x05}, + {0x6069, 0x02}, + {0x606b, 0x08}, + {0x606c, 0x07}, + {0x606d, 0x88}, + {0x6087, 0x04}, + {0x6088, 0x05}, + {0x6089, 0x02}, + {0x608b, 0x08}, + {0x608c, 0x07}, + {0x608d, 0x88}, + {0x5e00, 0x00}, + {0x5e01, 0x08}, + {0x5e02, 0x09}, + {0x5e03, 0x0a}, + {0x5e04, 0x0b}, + {0x5e05, 0x0c}, + {0x5e06, 0x0c}, + {0x5e07, 0x0c}, + {0x5e08, 0x0c}, + {0x5e09, 0x0c}, + {0x5e0a, 0x0d}, + {0x5e0b, 0x0d}, + {0x5e0c, 0x0d}, + {0x5e0d, 0x0d}, + {0x5e0e, 0x0d}, + {0x5e0f, 0x0d}, + {0x5e10, 0x0d}, + {0x5e11, 0x0d}, + {0x5e12, 0x0e}, + {0x5e13, 0x0e}, + {0x5e14, 0x0e}, + {0x5e15, 0x0e}, + {0x5e16, 0x0e}, + {0x5e17, 0x0e}, + {0x5e18, 0x0e}, + {0x5e19, 0x10}, + {0x5e1a, 0x11}, + {0x5e1b, 0x11}, + {0x5e1c, 0x12}, + {0x5e1d, 0x12}, + {0x5e1e, 0x14}, + {0x5e1f, 0x15}, + {0x5e20, 0x17}, + {0x5e21, 0x17}, + {0x5e22, 0x00}, + {0x5e23, 0x01}, + {0x5e26, 0x00}, + {0x5e27, 0x3f}, + {0x5e29, 0x00}, + {0x5e2a, 0x40}, + {0x5e2c, 0x00}, + {0x5e2d, 0x40}, + {0x5e2f, 0x00}, + {0x5e30, 0x40}, + {0x5e32, 0x00}, + {0x5e33, 0x40}, + {0x5e34, 0x00}, + {0x5e35, 0x00}, + {0x5e36, 0x40}, + {0x5e37, 0x00}, + {0x5e38, 0x00}, + {0x5e39, 0x40}, + {0x5e3a, 0x00}, + {0x5e3b, 0x00}, + {0x5e3c, 0x40}, + {0x5e3d, 0x00}, + {0x5e3e, 0x00}, + {0x5e3f, 0x40}, + {0x5e40, 0x00}, + {0x5e41, 0x00}, + {0x5e42, 0x60}, + {0x5e43, 0x00}, + {0x5e44, 0x00}, + {0x5e45, 0x60}, + {0x5e46, 0x00}, + {0x5e47, 0x00}, + {0x5e48, 0x60}, + {0x5e49, 0x00}, + {0x5e4a, 0x00}, + {0x5e4b, 0x60}, + {0x5e4c, 0x00}, + {0x5e4d, 0x00}, + {0x5e4e, 0x60}, + {0x5e50, 0x00}, + {0x5e51, 0x60}, + {0x5e53, 0x00}, + {0x5e54, 0x60}, + {0x5e56, 0x00}, + {0x5e57, 0x80}, + {0x5e59, 0x00}, + {0x5e5a, 0x80}, + {0x5e5c, 0x00}, + {0x5e5d, 0x80}, + {0x5e5f, 0x00}, + {0x5e60, 0x80}, + {0x5e62, 0x00}, + {0x5e63, 0x80}, + {0x5e65, 0x00}, + {0x5e66, 0x80}, + {0x5e68, 0x00}, + {0x5e69, 0x80}, + {0x5e6b, 0x01}, + {0x5e6c, 0x20}, + {0x5e6e, 0x01}, + {0x5e6f, 0xd0}, + {0x5e71, 0x01}, + {0x5e72, 0x30}, + {0x5e74, 0x01}, + {0x5e75, 0x80}, + {0x5e77, 0x01}, + {0x5e78, 0x00}, + {0x5e7a, 0x00}, + {0x5e7b, 0x00}, + {0x5e7d, 0x00}, + {0x5e7e, 0x00}, + {0x5e80, 0x00}, + {0x5e81, 0x00}, + {0x5e83, 0x00}, + {0x5e84, 0x00}, + {0x5f00, 0x02}, + {0x5f01, 0x08}, + {0x5f02, 0x09}, + {0x5f03, 0x0a}, + {0x5f04, 0x0b}, + {0x5f05, 0x0c}, + {0x5f06, 0x0c}, + {0x5f07, 0x0c}, + {0x5f08, 0x0c}, + {0x5f09, 0x0c}, + {0x5f0a, 0x0d}, + {0x5f0b, 0x0d}, + {0x5f0c, 0x0d}, + {0x5f0d, 0x0d}, + {0x5f0e, 0x0d}, + {0x5f0f, 0x0e}, + {0x5f10, 0x0e}, + {0x5f11, 0x0e}, + {0x5f12, 0x0e}, + {0x5f13, 0x0f}, + {0x5f14, 0x0f}, + {0x5f15, 0x10}, + {0x5f16, 0x11}, + {0x5f17, 0x11}, + {0x5f18, 0x12}, + {0x5f19, 0x12}, + {0x5f1a, 0x13}, + {0x5f1b, 0x13}, + {0x5f1c, 0x14}, + {0x5f1d, 0x14}, + {0x5f1e, 0x16}, + {0x5f1f, 0x16}, + {0x5f20, 0x16}, + {0x5f21, 0x08}, + {0x5f22, 0x00}, + {0x5f23, 0x01}, + {0x5f26, 0x02}, + {0x5f27, 0x00}, + {0x5f29, 0x02}, + {0x5f2a, 0x00}, + {0x5f2c, 0x02}, + {0x5f2d, 0x00}, + {0x5f2f, 0x02}, + {0x5f30, 0x00}, + {0x5f32, 0x02}, + {0x5f33, 0x00}, + {0x5f34, 0x00}, + {0x5f35, 0x02}, + {0x5f36, 0x00}, + {0x5f37, 0x00}, + {0x5f38, 0x02}, + {0x5f39, 0x00}, + {0x5f3a, 0x00}, + {0x5f3b, 0x02}, + {0x5f3c, 0x00}, + {0x5f3d, 0x00}, + {0x5f3e, 0x02}, + {0x5f3f, 0x00}, + {0x5f40, 0x00}, + {0x5f41, 0x02}, + {0x5f42, 0x00}, + {0x5f43, 0x00}, + {0x5f44, 0x02}, + {0x5f45, 0x00}, + {0x5f46, 0x00}, + {0x5f47, 0x04}, + {0x5f48, 0x00}, + {0x5f49, 0x00}, + {0x5f4a, 0x04}, + {0x5f4b, 0x00}, + {0x5f4c, 0x00}, + {0x5f4d, 0x04}, + {0x5f4e, 0x00}, + {0x5f50, 0x04}, + {0x5f51, 0x00}, + {0x5f53, 0x04}, + {0x5f54, 0x00}, + {0x5f56, 0x04}, + {0x5f57, 0x00}, + {0x5f59, 0x04}, + {0x5f5a, 0x00}, + {0x5f5c, 0x04}, + {0x5f5d, 0x00}, + {0x5f5f, 0x08}, + {0x5f60, 0x00}, + {0x5f62, 0x08}, + {0x5f63, 0x00}, + {0x5f65, 0x08}, + {0x5f66, 0x00}, + {0x5f68, 0x08}, + {0x5f69, 0x00}, + {0x5f6b, 0x08}, + {0x5f6c, 0x00}, + {0x5f6e, 0x10}, + {0x5f6f, 0x00}, + {0x5f71, 0x10}, + {0x5f72, 0x00}, + {0x5f74, 0x10}, + {0x5f75, 0x00}, + {0x5f77, 0x10}, + {0x5f78, 0x00}, + {0x5f7a, 0x20}, + {0x5f7b, 0x00}, + {0x5f7d, 0x20}, + {0x5f7e, 0x00}, + {0x5f80, 0x20}, + {0x5f81, 0x00}, + {0x5f83, 0x00}, + {0x5f84, 0xff}, + {0x5240, 0x0f}, + {0x5243, 0x00}, + {0x5244, 0x00}, + {0x5245, 0x00}, + {0x5246, 0x00}, + {0x5247, 0x00}, + {0x5248, 0x00}, + {0x5249, 0x00}, + {0x5440, 0x0f}, + {0x5443, 0x00}, + {0x5445, 0x00}, + {0x5447, 0x00}, + {0x5448, 0x00}, + {0x5449, 0x00}, + {0x5640, 0x0f}, + {0x5642, 0x00}, + {0x5643, 0x00}, + {0x5644, 0x00}, + {0x5645, 0x00}, + {0x5646, 0x00}, + {0x5647, 0x00}, + {0x5649, 0x00}, + {0x5840, 0x0f}, + {0x5842, 0x00}, + {0x5843, 0x00}, + {0x5845, 0x00}, + {0x5846, 0x00}, + {0x5847, 0x00}, + {0x5848, 0x00}, + {0x5849, 0x00}, + {0x4001, 0x2b}, + {0x4008, 0x02}, + {0x4009, 0x03}, + {0x4018, 0x12}, + {0x4022, 0x40}, + {0x4023, 0x20}, + {0x4026, 0x00}, + {0x4027, 0x40}, + {0x4028, 0x00}, + {0x4029, 0x40}, + {0x402a, 0x00}, + {0x402b, 0x40}, + {0x402c, 0x00}, + {0x402d, 0x40}, + {0x405e, 0x00}, + {0x405f, 0x00}, + {0x4060, 0x00}, + {0x4061, 0x00}, + {0x4062, 0x00}, + {0x4063, 0x00}, + {0x4064, 0x00}, + {0x4065, 0x00}, + {0x4066, 0x00}, + {0x4067, 0x00}, + {0x4068, 0x00}, + {0x4069, 0x00}, + {0x406a, 0x00}, + {0x406b, 0x00}, + {0x406c, 0x00}, + {0x406d, 0x00}, + {0x406e, 0x00}, + {0x406f, 0x00}, + {0x4070, 0x00}, + {0x4071, 0x00}, + {0x4072, 0x00}, + {0x4073, 0x00}, + {0x4074, 0x00}, + {0x4075, 0x00}, + {0x4076, 0x00}, + {0x4077, 0x00}, + {0x4078, 0x00}, + {0x4079, 0x00}, + {0x407a, 0x00}, + {0x407b, 0x00}, + {0x407c, 0x00}, + {0x407d, 0x00}, + {0x407e, 0xcc}, + {0x407f, 0x18}, + {0x4080, 0xff}, + {0x4081, 0xff}, + {0x4082, 0x01}, + {0x4083, 0x53}, + {0x4084, 0x01}, + {0x4085, 0x2b}, + {0x4086, 0x00}, + {0x4087, 0xb3}, + {0x4640, 0x40}, + {0x4641, 0x11}, + {0x4642, 0x0e}, + {0x4643, 0xee}, + {0x4646, 0x0f}, + {0x4648, 0x00}, + {0x4649, 0x03}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x5b80, 0x01}, + {0x5c00, 0x08}, + {0x5c80, 0x00}, + {0x5bbe, 0x12}, + {0x5c3e, 0x12}, + {0x5cbe, 0x12}, + {0x5b8a, 0x80}, + {0x5b8b, 0x80}, + {0x5b8c, 0x80}, + {0x5b8d, 0x80}, + {0x5b8e, 0x80}, + {0x5b8f, 0x40}, + {0x5b90, 0x80}, + {0x5b91, 0x80}, + {0x5b92, 0x80}, + {0x5b93, 0x60}, + {0x5b94, 0x00}, + {0x5b95, 0x00}, + {0x5b96, 0x40}, + {0x5b97, 0x80}, + {0x5b98, 0x10}, + {0x5b99, 0x00}, + {0x5b9a, 0x00}, + {0x5b9b, 0x00}, + {0x5b9c, 0x00}, + {0x5b9d, 0x00}, + {0x5b9e, 0x00}, + {0x5b9f, 0x00}, + {0x5ba0, 0x00}, + {0x5ba1, 0x00}, + {0x5ba2, 0x00}, + {0x5ba3, 0x00}, + {0x5ba4, 0x00}, + {0x5ba5, 0x00}, + {0x5ba6, 0x00}, + {0x5ba7, 0x00}, + {0x5ba8, 0x00}, + {0x5ba9, 0xc0}, + {0x5baa, 0x01}, + {0x5bab, 0x40}, + {0x5bac, 0x02}, + {0x5bad, 0x40}, + {0x5bae, 0x00}, + {0x5baf, 0x50}, + {0x5bb0, 0x00}, + {0x5bb1, 0x60}, + {0x5bb2, 0x00}, + {0x5bb3, 0xc0}, + {0x5c0a, 0x80}, + {0x5c0b, 0x80}, + {0x5c0c, 0x80}, + {0x5c0d, 0x80}, + {0x5c0e, 0x60}, + {0x5c0f, 0x80}, + {0x5c10, 0x80}, + {0x5c11, 0x80}, + {0x5c12, 0x60}, + {0x5c13, 0x20}, + {0x5c14, 0x80}, + {0x5c15, 0x80}, + {0x5c16, 0x80}, + {0x5c17, 0x20}, + {0x5c18, 0x00}, + {0x5c19, 0x80}, + {0x5c1a, 0x40}, + {0x5c1b, 0x20}, + {0x5c1c, 0x00}, + {0x5c1d, 0x00}, + {0x5c1e, 0x80}, + {0x5c1f, 0x00}, + {0x5c20, 0x00}, + {0x5c21, 0x00}, + {0x5c22, 0x00}, + {0x5c23, 0x00}, + {0x5c24, 0x00}, + {0x5c25, 0x00}, + {0x5c26, 0x00}, + {0x5c27, 0x00}, + {0x5c28, 0x02}, + {0x5c29, 0x00}, + {0x5c2a, 0x02}, + {0x5c2b, 0x76}, + {0x5c2c, 0x03}, + {0x5c2d, 0x08}, + {0x5c2e, 0x00}, + {0x5c2f, 0x80}, + {0x5c30, 0x01}, + {0x5c31, 0x00}, + {0x5c32, 0x02}, + {0x5c33, 0x00}, + {0x5c8a, 0x80}, + {0x5c8b, 0x80}, + {0x5c8c, 0x80}, + {0x5c8d, 0x80}, + {0x5c8e, 0x80}, + {0x5c8f, 0x80}, + {0x5c90, 0x80}, + {0x5c91, 0x80}, + {0x5c92, 0x80}, + {0x5c93, 0x60}, + {0x5c94, 0x80}, + {0x5c95, 0x80}, + {0x5c96, 0x80}, + {0x5c97, 0x60}, + {0x5c98, 0x40}, + {0x5c99, 0x80}, + {0x5c9a, 0x80}, + {0x5c9b, 0x80}, + {0x5c9c, 0x40}, + {0x5c9d, 0x20}, + {0x5c9e, 0x80}, + {0x5c9f, 0x80}, + {0x5ca0, 0x80}, + {0x5ca1, 0x20}, + {0x5ca2, 0x00}, + {0x5ca3, 0x80}, + {0x5ca4, 0x80}, + {0x5ca5, 0x80}, + {0x5ca6, 0x00}, + {0x5ca7, 0x00}, + {0x5ca8, 0x01}, + {0x5ca9, 0x00}, + {0x5caa, 0x02}, + {0x5cab, 0x00}, + {0x5cac, 0x03}, + {0x5cad, 0x08}, + {0x5cae, 0x01}, + {0x5caf, 0x00}, + {0x5cb0, 0x02}, + {0x5cb1, 0x00}, + {0x5cb2, 0x03}, + {0x5cb3, 0x08}, + {0x5be7, 0x80}, + {0x5bc9, 0x80}, + {0x5bca, 0x80}, + {0x5bcb, 0x80}, + {0x5bcc, 0x80}, + {0x5bcd, 0x80}, + {0x5bce, 0x80}, + {0x5bcf, 0x80}, + {0x5bd0, 0x80}, + {0x5bd1, 0x80}, + {0x5bd2, 0x20}, + {0x5bd3, 0x80}, + {0x5bd4, 0x40}, + {0x5bd5, 0x20}, + {0x5bd6, 0x00}, + {0x5bd7, 0x00}, + {0x5bd8, 0x00}, + {0x5bd9, 0x00}, + {0x5bda, 0x00}, + {0x5bdb, 0x00}, + {0x5bdc, 0x00}, + {0x5bdd, 0x00}, + {0x5bde, 0x00}, + {0x5bdf, 0x00}, + {0x5be0, 0x00}, + {0x5be1, 0x00}, + {0x5be2, 0x00}, + {0x5be3, 0x00}, + {0x5be4, 0x00}, + {0x5be5, 0x00}, + {0x5be6, 0x00}, + {0x5c49, 0x80}, + {0x5c4a, 0x80}, + {0x5c4b, 0x80}, + {0x5c4c, 0x80}, + {0x5c4d, 0x40}, + {0x5c4e, 0x80}, + {0x5c4f, 0x80}, + {0x5c50, 0x80}, + {0x5c51, 0x60}, + {0x5c52, 0x20}, + {0x5c53, 0x80}, + {0x5c54, 0x80}, + {0x5c55, 0x80}, + {0x5c56, 0x20}, + {0x5c57, 0x00}, + {0x5c58, 0x80}, + {0x5c59, 0x40}, + {0x5c5a, 0x20}, + {0x5c5b, 0x00}, + {0x5c5c, 0x00}, + {0x5c5d, 0x80}, + {0x5c5e, 0x00}, + {0x5c5f, 0x00}, + {0x5c60, 0x00}, + {0x5c61, 0x00}, + {0x5c62, 0x00}, + {0x5c63, 0x00}, + {0x5c64, 0x00}, + {0x5c65, 0x00}, + {0x5c66, 0x00}, + {0x5cc9, 0x80}, + {0x5cca, 0x80}, + {0x5ccb, 0x80}, + {0x5ccc, 0x80}, + {0x5ccd, 0x80}, + {0x5cce, 0x80}, + {0x5ccf, 0x80}, + {0x5cd0, 0x80}, + {0x5cd1, 0x80}, + {0x5cd2, 0x60}, + {0x5cd3, 0x80}, + {0x5cd4, 0x80}, + {0x5cd5, 0x80}, + {0x5cd6, 0x60}, + {0x5cd7, 0x40}, + {0x5cd8, 0x80}, + {0x5cd9, 0x80}, + {0x5cda, 0x80}, + {0x5cdb, 0x40}, + {0x5cdc, 0x20}, + {0x5cdd, 0x80}, + {0x5cde, 0x80}, + {0x5cdf, 0x80}, + {0x5ce0, 0x20}, + {0x5ce1, 0x00}, + {0x5ce2, 0x80}, + {0x5ce3, 0x80}, + {0x5ce4, 0x80}, + {0x5ce5, 0x00}, + {0x5ce6, 0x00}, + {0x5b84, 0x02}, + {0x5b85, 0xcc}, + {0x5bb4, 0x05}, + {0x5bb5, 0xc6}, + {0x5c04, 0x02}, + {0x5c05, 0xcc}, + {0x5c34, 0x05}, + {0x5c35, 0x33}, + {0x5c84, 0x02}, + {0x5c85, 0xcc}, + {0x5cb4, 0x05}, + {0x5cb5, 0x33}, + {0x5bbf, 0x00}, + {0x5bc0, 0x04}, + {0x5bc1, 0x06}, + {0x5bc2, 0xff}, + {0x5bc3, 0x00}, + {0x5bc4, 0x04}, + {0x5bc5, 0x02}, + {0x5bc6, 0xb8}, + {0x5c3f, 0x00}, + {0x5c40, 0x04}, + {0x5c41, 0x07}, + {0x5c42, 0xff}, + {0x5c43, 0x00}, + {0x5c44, 0x04}, + {0x5c45, 0x03}, + {0x5c46, 0xb8}, + {0x5cbf, 0x00}, + {0x5cc0, 0x20}, + {0x5cc1, 0x07}, + {0x5cc2, 0xff}, + {0x5cc3, 0x00}, + {0x5cc4, 0x20}, + {0x5cc5, 0x03}, + {0x5cc6, 0x00}, + {0x5b86, 0x05}, + {0x5c06, 0x05}, + {0x5c86, 0x05}, + {0x5bb8, 0x01}, + {0x5bb9, 0x01}, + {0x5c38, 0x01}, + {0x5c39, 0x01}, + {0x5cb8, 0x01}, + {0x5cb9, 0x01}, + {0x5bc7, 0x00}, + {0x5bc8, 0x80}, + {0x5c47, 0x00}, + {0x5c48, 0x80}, + {0x5cc7, 0x00}, + {0x5cc8, 0x80}, + {0x5bba, 0x01}, + {0x5bbb, 0x00}, + {0x5c3a, 0x01}, + {0x5c3b, 0x00}, + {0x5cba, 0x01}, + {0x5cbb, 0x00}, + {0x5d74, 0x01}, + {0x5d75, 0x00}, + {0x5d1f, 0x81}, + {0x5d11, 0x00}, + {0x5d12, 0x10}, + {0x5d13, 0x10}, + {0x5d15, 0x05}, + {0x5d16, 0x05}, + {0x5d17, 0x05}, + {0x5d08, 0x03}, + {0x5d09, 0x6b}, + {0x5d0a, 0x03}, + {0x5d0b, 0x6b}, + {0x5d18, 0x03}, + {0x5d19, 0x6b}, + {0x52c6, 0x00}, + {0x52c7, 0x12}, + {0x52c8, 0x04}, + {0x52c9, 0x02}, + {0x52ca, 0x01}, + {0x52cb, 0x01}, + {0x52cc, 0x04}, + {0x52cd, 0x02}, + {0x52ce, 0x01}, + {0x52cf, 0x01}, + {0x52d0, 0x03}, + {0x52d1, 0x08}, + {0x52d2, 0x0c}, + {0x54c6, 0x00}, + {0x54c7, 0x12}, + {0x54c8, 0x04}, + {0x54c9, 0x02}, + {0x54ca, 0x01}, + {0x54cb, 0x01}, + {0x54cc, 0x04}, + {0x54cd, 0x02}, + {0x54ce, 0x01}, + {0x54cf, 0x01}, + {0x54d0, 0x03}, + {0x54d1, 0x08}, + {0x54d2, 0x0c}, + {0x56c6, 0x00}, + {0x56c7, 0x12}, + {0x56c8, 0x04}, + {0x56c9, 0x02}, + {0x56ca, 0x01}, + {0x56cb, 0x01}, + {0x56cc, 0x04}, + {0x56cd, 0x02}, + {0x56ce, 0x01}, + {0x56cf, 0x01}, + {0x56d0, 0x03}, + {0x56d1, 0x08}, + {0x56d2, 0x0c}, + {0x58c6, 0x00}, + {0x58c7, 0x12}, + {0x58c8, 0x04}, + {0x58c9, 0x02}, + {0x58ca, 0x01}, + {0x58cb, 0x01}, + {0x58cc, 0x04}, + {0x58cd, 0x02}, + {0x58ce, 0x01}, + {0x58cf, 0x01}, + {0x58d0, 0x03}, + {0x58d1, 0x08}, + {0x58d2, 0x0c}, + {0x5004, 0x1e}, + {0x610a, 0x07}, + {0x610b, 0x80}, + {0x610c, 0x05}, + {0x610d, 0x00}, + {0x6102, 0x3f}, + {0x5d62, 0x07}, + {0x5d40, 0x02}, + {0x5d41, 0x01}, + {0x5d63, 0x08}, + {0x5d64, 0x01}, + {0x5d65, 0xff}, + {0x5d56, 0x00}, + {0x5d57, 0x20}, + {0x5d58, 0x00}, + {0x5d59, 0x20}, + {0x5d5a, 0x00}, + {0x5d5b, 0x0c}, + {0x5d5c, 0x02}, + {0x5d5d, 0x40}, + {0x5d5e, 0x02}, + {0x5d5f, 0x40}, + {0x5d60, 0x03}, + {0x5d61, 0x40}, + {0x5d4a, 0x02}, + {0x5d4b, 0x40}, + {0x5d4c, 0x02}, + {0x5d4d, 0x40}, + {0x5d4e, 0x02}, + {0x5d4f, 0x40}, + {0x5d50, 0x18}, + {0x5d51, 0x80}, + {0x5d52, 0x18}, + {0x5d53, 0x80}, + {0x5d54, 0x18}, + {0x5d55, 0x80}, + {0x5d46, 0x20}, + {0x5d47, 0x00}, + {0x5d48, 0x22}, + {0x5d49, 0x00}, + {0x5d42, 0x20}, + {0x5d43, 0x00}, + {0x5d44, 0x22}, + {0x5d45, 0x00}, + {0x5b40, 0x01}, + {0x5b41, 0x14}, + {0x5b42, 0x0f}, + {0x5b43, 0xf1}, + {0x5b44, 0x0f}, + {0x5b45, 0xfc}, + {0x5b46, 0x0f}, + {0x5b47, 0xf0}, + {0x5b48, 0x01}, + {0x5b49, 0x02}, + {0x5b4a, 0x00}, + {0x5b4b, 0x0e}, + {0x5b4c, 0x0f}, + {0x5b4d, 0xf1}, + {0x5b4e, 0x0f}, + {0x5b4f, 0xe4}, + {0x5b50, 0x01}, + {0x5b51, 0x2b}, + {0x5b52, 0x01}, + {0x5b53, 0x0f}, + {0x5b54, 0x0f}, + {0x5b55, 0xf1}, + {0x5b56, 0x00}, + {0x5b57, 0x00}, + {0x5b58, 0x0f}, + {0x5b59, 0xeb}, + {0x5b5a, 0x01}, + {0x5b5b, 0x04}, + {0x5b5c, 0x00}, + {0x5b5d, 0x11}, + {0x5b5e, 0x0f}, + {0x5b5f, 0xc8}, + {0x5b60, 0x0f}, + {0x5b61, 0xbd}, + {0x5b62, 0x01}, + {0x5b63, 0x7b}, + {0x5b64, 0x01}, + {0x5b65, 0x11}, + {0x5b66, 0x0f}, + {0x5b67, 0xf4}, + {0x5b68, 0x0f}, + {0x5b69, 0xfb}, + {0x5b6a, 0x0f}, + {0x5b6b, 0xf2}, + {0x5b6c, 0x01}, + {0x5b6d, 0x04}, + {0x5b6e, 0x00}, + {0x5b6f, 0x0a}, + {0x5b70, 0x0f}, + {0x5b71, 0xea}, + {0x5b72, 0x0f}, + {0x5b73, 0xc7}, + {0x5b74, 0x01}, + {0x5b75, 0x4e}, + {0x5b78, 0x00}, + {0x5b79, 0x4c}, + {0x5b7a, 0x00}, + {0x5b7b, 0xb9}, + {0x5b7c, 0x01}, + {0x5b7d, 0x38}, + {0x5b7e, 0x01}, + {0x5280, 0x05}, + {0x5281, 0xf2}, + {0x5282, 0x04}, + {0x5283, 0x00}, + {0x5284, 0x04}, + {0x5285, 0x00}, + {0x5286, 0x07}, + {0x5287, 0x3f}, + {0x4221, 0x13}, + {0x3501, 0x01}, + {0x3502, 0xc8}, + {0x3541, 0x01}, + {0x3542, 0xc8}, + {0x35c1, 0x00}, + {0x35c2, 0x00}, + {0x35c8, 0x01}, + {0x420e, 0x66}, + {0x420f, 0x5d}, + {0x4210, 0xa8}, + {0x4211, 0x55}, + {0x507a, 0x5f}, + {0x507b, 0x46}, + {0x4f00, 0x00}, + {0x4f01, 0x01}, + {0x4f02, 0x80}, + {0x4f03, 0x2c}, + {0x4f04, 0xf8}, + + {I2C_REG_NULL, 0x00}, +}; + +/* + * hdr_operating_mode: OX03C10_HDR3_DCG_VS_12BIT + */ +static const struct i2c_regval ox03c10_1920x1080_30fps_HDR3_DCG_VS_PWL12_mipi600[] = { + {0x0103, 0x01}, + {0x0107, 0x01}, + {I2C_REG_DELAY, 6}, + {0x4d5a, 0x1c}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x3208, 0x04}, + {0x4620, 0x04}, + {0x3208, 0x14}, + {0x3208, 0x05}, + {0x4620, 0x04}, + {0x3208, 0x15}, + {0x3208, 0x02}, + {0x3507, 0x00}, + {0x3208, 0x12}, + {0x3208, 0xa2}, + {0x0301, 0xc8}, + {0x0303, 0x01}, + {0x0304, 0x01}, + {0x0305, 0x2c}, + {0x0306, 0x04}, + {0x0307, 0x03}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x00}, + {0x0323, 0x05}, + {0x0324, 0x01}, + {0x0325, 0x2c}, + {0x032e, 0x00}, + {0x032a, 0x04}, + {0x0326, 0x09}, + {0x0327, 0x04}, + {0x0331, 0x04}, + {0x0400, 0xe0}, + {0x0401, 0x80}, + {0x0403, 0xde}, + {0x0404, 0x34}, + {0x0405, 0x3b}, + {0x0406, 0xd4}, + {0x0407, 0x08}, + {0x0408, 0xe0}, + {0x0409, 0x62}, + {0x040a, 0xde}, + {0x040b, 0x34}, + {0x040c, 0x8f}, + {0x040d, 0x9b}, + {0x040e, 0x08}, + {0x2803, 0xfe}, + {0x280b, 0x00}, + {0x280c, 0x79}, + {0x3001, 0x03}, + {0x3002, 0xf8}, + {0x3005, 0x80}, + {0x3007, 0x01}, + {0x3008, 0x80}, + {0x3012, 0x41}, + {0x3020, 0x05}, + {0x3700, 0x28}, + {0x3701, 0x15}, + {0x3702, 0x19}, + {0x3703, 0x23}, + {0x3704, 0x0a}, + {0x3705, 0x00}, + {0x3706, 0x3e}, + {0x3707, 0x0d}, + {0x3708, 0x50}, + {0x3709, 0x5a}, + {0x370a, 0x00}, + {0x370b, 0x96}, + {0x3711, 0x11}, + {0x3712, 0x13}, + {0x3717, 0x02}, + {0x3718, 0x73}, + {0x372c, 0x40}, + {0x3733, 0x01}, + {0x3738, 0x36}, + {0x3739, 0x36}, + {0x373a, 0x25}, + {0x373b, 0x25}, + {0x373f, 0x21}, + {0x3740, 0x21}, + {0x3741, 0x21}, + {0x3742, 0x21}, + {0x3747, 0x28}, + {0x3748, 0x28}, + {0x3749, 0x19}, + {0x3755, 0x1a}, + {0x3756, 0x0a}, + {0x3757, 0x1c}, + {0x3765, 0x19}, + {0x3766, 0x05}, + {0x3767, 0x05}, + {0x3768, 0x13}, + {0x376c, 0x07}, + {0x3778, 0x20}, + {0x377c, 0xc8}, + {0x3781, 0x02}, + {0x3783, 0x02}, + {0x379c, 0x58}, + {0x379e, 0x00}, + {0x379f, 0x00}, + {0x37a0, 0x00}, + {0x37bc, 0x22}, + {0x37c0, 0x01}, + {0x37c4, 0x3e}, + {0x37c5, 0x3e}, + {0x37c6, 0x2a}, + {0x37c7, 0x28}, + {0x37c8, 0x02}, + {0x37c9, 0x12}, + {0x37cb, 0x29}, + {0x37cd, 0x29}, + {0x37d2, 0x00}, + {0x37d3, 0x73}, + {0x37d6, 0x00}, + {0x37d7, 0x6b}, + {0x37dc, 0x00}, + {0x37df, 0x54}, + {0x37e2, 0x00}, + {0x37e3, 0x00}, + {0x37f8, 0x00}, + {0x37f9, 0x01}, + {0x37fa, 0x00}, + {0x37fb, 0x19}, + {0x3c03, 0x01}, + {0x3c04, 0x01}, + {0x3c06, 0x21}, + {0x3c08, 0x01}, + {0x3c09, 0x01}, + {0x3c0a, 0x01}, + {0x3c0b, 0x21}, + {0x3c13, 0x21}, + {0x3c14, 0x82}, + {0x3c16, 0x13}, + {0x3c21, 0x00}, + {0x3c22, 0xf3}, + {0x3c37, 0x12}, + {0x3c38, 0x31}, + {0x3c3c, 0x00}, + {0x3c3d, 0x03}, + {0x3c44, 0x16}, + {0x3c5c, 0x8a}, + {0x3c5f, 0x03}, + {0x3c61, 0x80}, + {0x3c6f, 0x2b}, + {0x3c70, 0x5f}, + {0x3c71, 0x2c}, + {0x3c72, 0x2c}, + {0x3c73, 0x2c}, + {0x3c76, 0x12}, + {0x3182, 0x12}, + {0x320e, 0x00}, + {0x320f, 0x00}, + {0x3211, 0x61}, + {0x3215, 0xcd}, + {0x3219, 0x08}, + {0x3506, 0x20}, + {0x350a, 0x01}, + {0x350b, 0x00}, + {0x350c, 0x00}, + {0x3586, 0x30}, + {0x358a, 0x01}, + {0x358b, 0x00}, + {0x358c, 0x00}, + {0x3541, 0x00}, + {0x3542, 0x04}, + {0x3546, 0x10}, + {0x3548, 0x04}, + {0x3549, 0x40}, + {0x354a, 0x01}, + {0x354b, 0x00}, + {0x354c, 0x00}, + {0x35c1, 0x00}, + {0x35c2, 0x02}, + {0x35c6, 0x90}, + {0x3600, 0x8f}, + {0x3605, 0x16}, + {0x3609, 0xf0}, + {0x360a, 0x01}, + {0x360e, 0x1d}, + {0x360f, 0x10}, + {0x3610, 0x70}, + {0x3611, 0x3a}, + {0x3612, 0x28}, + {0x361a, 0x29}, + {0x361b, 0x6c}, + {0x361c, 0x0b}, + {0x361d, 0x00}, + {0x361e, 0xfc}, + {0x362a, 0x00}, + {0x364d, 0x0f}, + {0x364e, 0x18}, + {0x364f, 0x12}, + {0x3653, 0x1c}, + {0x3654, 0x00}, + {0x3655, 0x1f}, + {0x3656, 0x1f}, + {0x3657, 0x0c}, + {0x3658, 0x0a}, + {0x3659, 0x14}, + {0x365a, 0x18}, + {0x365b, 0x14}, + {0x365c, 0x10}, + {0x365e, 0x12}, + {0x3674, 0x08}, + {0x3677, 0x3a}, + {0x3678, 0x3a}, + {0x3679, 0x19}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3806, 0x05}, + {0x3807, 0x0b}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x04}, + {0x380b, 0x38}, + {0x380c, 0x08}, + {0x380d, 0x8e}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x68}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x381c, 0x18}, + {0x381e, 0x01}, + {0x381f, 0x01}, + {0x3820, 0x00}, + {0x3821, 0x19}, + {0x3832, 0x00}, + {0x3834, 0x00}, + {0x384c, 0x04}, + {0x384d, 0x1a}, + {0x3850, 0x00}, + {0x3851, 0x42}, + {0x3852, 0x00}, + {0x3853, 0x40}, + {0x3858, 0x04}, + {0x388c, 0x04}, + {0x388d, 0x56}, + {0x3b40, 0x05}, + {0x3b41, 0x40}, + {0x3b42, 0x00}, + {0x3b43, 0x90}, + {0x3b44, 0x02}, + {0x3b45, 0x00}, + {0x3b46, 0x02}, + {0x3b47, 0x00}, + {0x3b48, 0x19}, + {0x3b49, 0x12}, + {0x3b4a, 0x16}, + {0x3b4b, 0x2e}, + {0x3b4c, 0x03}, + {0x3b4d, 0x00}, + {0x3b86, 0x00}, + {0x3b87, 0x34}, + {0x3b88, 0x00}, + {0x3b89, 0x08}, + {0x3b8a, 0x05}, + {0x3b8b, 0x00}, + {0x3b8c, 0x07}, + {0x3b8d, 0x80}, + {0x3b8e, 0x00}, + {0x3b8f, 0x00}, + {0x3b92, 0x05}, + {0x3b93, 0x00}, + {0x3b94, 0x07}, + {0x3b95, 0x80}, + {0x3b9e, 0x09}, + {0x3d85, 0x05}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d99, 0x00}, + {0x3d9a, 0x9f}, + {0x3d9b, 0x00}, + {0x3d9c, 0xa0}, + {0x3da4, 0x00}, + {0x3da7, 0x50}, + {0x420e, 0x6b}, + {0x420f, 0x6e}, + {0x4210, 0x06}, + {0x4211, 0xc1}, + {0x421e, 0x02}, + {0x421f, 0x45}, + {0x4220, 0xe1}, + {0x4221, 0x01}, + {0x4301, 0x0f}, + {0x4307, 0x03}, + {0x4308, 0x13}, + {0x430a, 0x13}, + {0x430d, 0x93}, + {0x430f, 0x57}, + {0x4310, 0x95}, + {0x4311, 0x16}, + {0x4316, 0x00}, + {0x4317, 0x08}, + {0x4319, 0x01}, + {0x431a, 0x00}, + {0x431b, 0x00}, + {0x431d, 0x2a}, + {0x431e, 0x11}, + {0x431f, 0x20}, + {0x4320, 0x19}, + {0x4323, 0x80}, + {0x4324, 0x00}, + {0x4503, 0x4e}, + {0x4505, 0x00}, + {0x4509, 0x00}, + {0x450a, 0x00}, + {0x4580, 0xf8}, + {0x4583, 0x07}, + {0x4584, 0x6a}, + {0x4585, 0x08}, + {0x4586, 0x05}, + {0x4587, 0x04}, + {0x4588, 0x73}, + {0x4589, 0x05}, + {0x458a, 0x1f}, + {0x458b, 0x02}, + {0x458c, 0xdc}, + {0x458d, 0x03}, + {0x458e, 0x02}, + {0x4597, 0x07}, + {0x4598, 0x40}, + {0x4599, 0x0e}, + {0x459a, 0x0e}, + {0x459b, 0xf5}, + {0x459c, 0xf1}, + {0x4602, 0x00}, + {0x4603, 0x13}, + {0x4604, 0x00}, + {0x4609, 0x60}, + {0x460a, 0x30}, + {0x4610, 0x00}, + {0x4611, 0x40}, + {0x4612, 0x01}, + {0x4613, 0x00}, + {0x4614, 0x00}, + {0x4615, 0x40}, + {0x4616, 0x01}, + {0x4617, 0x00}, + {0x4800, 0x04}, + {0x480a, 0x22}, + {0x4813, 0xe4}, + {0x4814, 0x2a}, + {0x4837, 0x1a}, + {0x484b, 0x47}, + {0x484f, 0x00}, + {0x4887, 0x51}, + {0x4d00, 0x4a}, + {0x4d01, 0x18}, + {0x4d05, 0xff}, + {0x4d06, 0x88}, + {0x4d08, 0x63}, + {0x4d09, 0xdf}, + {0x4d15, 0x7d}, + {0x4d1a, 0x20}, + {0x4d30, 0x0a}, + {0x4d31, 0x00}, + {0x4d34, 0x7d}, + {0x4d3c, 0x7d}, + {0x4f00, 0x3f}, + {0x4f01, 0xff}, + {0x4f02, 0xff}, + {0x4f03, 0x2c}, + {0x4f04, 0xe0}, + {0x6a00, 0x00}, + {0x6a01, 0x20}, + {0x6a02, 0x00}, + {0x6a03, 0x20}, + {0x6a04, 0x02}, + {0x6a05, 0x80}, + {0x6a06, 0x01}, + {0x6a07, 0xe0}, + {0x6a08, 0xcf}, + {0x6a09, 0x01}, + {0x6a0a, 0x40}, + {0x6a20, 0x00}, + {0x6a21, 0x02}, + {0x6a22, 0x00}, + {0x6a23, 0x00}, + {0x6a24, 0x00}, + {0x6a25, 0x00}, + {0x6a26, 0x00}, + {0x6a27, 0x00}, + {0x6a28, 0x00}, + {0x5000, 0x8f}, + {0x5001, 0x65}, + {0x5002, 0x7f}, + {0x5003, 0x7a}, + {0x5004, 0x3e}, + {0x5005, 0x1e}, + {0x5006, 0x1e}, + {0x5007, 0x1e}, + {0x5008, 0x00}, + {0x500c, 0x00}, + {0x502c, 0x00}, + {0x502e, 0x00}, + {0x502f, 0x00}, + {0x504b, 0x00}, + {0x5053, 0x00}, + {0x505b, 0x00}, + {0x5063, 0x00}, + {0x5070, 0x00}, + {0x5074, 0x04}, + {0x507a, 0x04}, + {0x507b, 0x09}, + {0x5500, 0x02}, + {0x5700, 0x02}, + {0x5900, 0x02}, + {0x6007, 0x04}, + {0x6008, 0x05}, + {0x6009, 0x02}, + {0x600b, 0x08}, + {0x600c, 0x07}, + {0x600d, 0x88}, + {0x6016, 0x00}, + {0x6027, 0x04}, + {0x6028, 0x05}, + {0x6029, 0x02}, + {0x602b, 0x08}, + {0x602c, 0x07}, + {0x602d, 0x88}, + {0x6047, 0x04}, + {0x6048, 0x05}, + {0x6049, 0x02}, + {0x604b, 0x08}, + {0x604c, 0x07}, + {0x604d, 0x88}, + {0x6067, 0x04}, + {0x6068, 0x05}, + {0x6069, 0x02}, + {0x606b, 0x08}, + {0x606c, 0x07}, + {0x606d, 0x88}, + {0x6087, 0x04}, + {0x6088, 0x05}, + {0x6089, 0x02}, + {0x608b, 0x08}, + {0x608c, 0x07}, + {0x608d, 0x88}, + {0x5e00, 0x00}, + {0x5e01, 0x08}, + {0x5e02, 0x09}, + {0x5e03, 0x0a}, + {0x5e04, 0x0b}, + {0x5e05, 0x0c}, + {0x5e06, 0x0c}, + {0x5e07, 0x0c}, + {0x5e08, 0x0c}, + {0x5e09, 0x0c}, + {0x5e0a, 0x0d}, + {0x5e0b, 0x0d}, + {0x5e0c, 0x0d}, + {0x5e0d, 0x0d}, + {0x5e0e, 0x0d}, + {0x5e0f, 0x0d}, + {0x5e10, 0x0d}, + {0x5e11, 0x0d}, + {0x5e12, 0x0e}, + {0x5e13, 0x0e}, + {0x5e14, 0x0e}, + {0x5e15, 0x0e}, + {0x5e16, 0x0e}, + {0x5e17, 0x0e}, + {0x5e18, 0x0e}, + {0x5e19, 0x10}, + {0x5e1a, 0x11}, + {0x5e1b, 0x11}, + {0x5e1c, 0x12}, + {0x5e1d, 0x12}, + {0x5e1e, 0x14}, + {0x5e1f, 0x15}, + {0x5e20, 0x17}, + {0x5e21, 0x17}, + {0x5e22, 0x00}, + {0x5e23, 0x01}, + {0x5e26, 0x00}, + {0x5e27, 0x3f}, + {0x5e29, 0x00}, + {0x5e2a, 0x40}, + {0x5e2c, 0x00}, + {0x5e2d, 0x40}, + {0x5e2f, 0x00}, + {0x5e30, 0x40}, + {0x5e32, 0x00}, + {0x5e33, 0x40}, + {0x5e34, 0x00}, + {0x5e35, 0x00}, + {0x5e36, 0x40}, + {0x5e37, 0x00}, + {0x5e38, 0x00}, + {0x5e39, 0x40}, + {0x5e3a, 0x00}, + {0x5e3b, 0x00}, + {0x5e3c, 0x40}, + {0x5e3d, 0x00}, + {0x5e3e, 0x00}, + {0x5e3f, 0x40}, + {0x5e40, 0x00}, + {0x5e41, 0x00}, + {0x5e42, 0x60}, + {0x5e43, 0x00}, + {0x5e44, 0x00}, + {0x5e45, 0x60}, + {0x5e46, 0x00}, + {0x5e47, 0x00}, + {0x5e48, 0x60}, + {0x5e49, 0x00}, + {0x5e4a, 0x00}, + {0x5e4b, 0x60}, + {0x5e4c, 0x00}, + {0x5e4d, 0x00}, + {0x5e4e, 0x60}, + {0x5e50, 0x00}, + {0x5e51, 0x60}, + {0x5e53, 0x00}, + {0x5e54, 0x60}, + {0x5e56, 0x00}, + {0x5e57, 0x80}, + {0x5e59, 0x00}, + {0x5e5a, 0x80}, + {0x5e5c, 0x00}, + {0x5e5d, 0x80}, + {0x5e5f, 0x00}, + {0x5e60, 0x80}, + {0x5e62, 0x00}, + {0x5e63, 0x80}, + {0x5e65, 0x00}, + {0x5e66, 0x80}, + {0x5e68, 0x00}, + {0x5e69, 0x80}, + {0x5e6b, 0x01}, + {0x5e6c, 0x20}, + {0x5e6e, 0x01}, + {0x5e6f, 0xd0}, + {0x5e71, 0x01}, + {0x5e72, 0x30}, + {0x5e74, 0x01}, + {0x5e75, 0x80}, + {0x5e77, 0x01}, + {0x5e78, 0x00}, + {0x5e7a, 0x00}, + {0x5e7b, 0x00}, + {0x5e7d, 0x00}, + {0x5e7e, 0x00}, + {0x5e80, 0x00}, + {0x5e81, 0x00}, + {0x5e83, 0x00}, + {0x5e84, 0x00}, + {0x5f00, 0x02}, + {0x5f01, 0x08}, + {0x5f02, 0x09}, + {0x5f03, 0x0a}, + {0x5f04, 0x0b}, + {0x5f05, 0x0c}, + {0x5f06, 0x0c}, + {0x5f07, 0x0c}, + {0x5f08, 0x0c}, + {0x5f09, 0x0c}, + {0x5f0a, 0x0d}, + {0x5f0b, 0x0d}, + {0x5f0c, 0x0d}, + {0x5f0d, 0x0d}, + {0x5f0e, 0x0d}, + {0x5f0f, 0x0e}, + {0x5f10, 0x0e}, + {0x5f11, 0x0e}, + {0x5f12, 0x0e}, + {0x5f13, 0x0f}, + {0x5f14, 0x0f}, + {0x5f15, 0x10}, + {0x5f16, 0x11}, + {0x5f17, 0x11}, + {0x5f18, 0x12}, + {0x5f19, 0x12}, + {0x5f1a, 0x13}, + {0x5f1b, 0x13}, + {0x5f1c, 0x14}, + {0x5f1d, 0x14}, + {0x5f1e, 0x16}, + {0x5f1f, 0x16}, + {0x5f20, 0x16}, + {0x5f21, 0x08}, + {0x5f22, 0x00}, + {0x5f23, 0x01}, + {0x5f26, 0x02}, + {0x5f27, 0x00}, + {0x5f29, 0x02}, + {0x5f2a, 0x00}, + {0x5f2c, 0x02}, + {0x5f2d, 0x00}, + {0x5f2f, 0x02}, + {0x5f30, 0x00}, + {0x5f32, 0x02}, + {0x5f33, 0x00}, + {0x5f34, 0x00}, + {0x5f35, 0x02}, + {0x5f36, 0x00}, + {0x5f37, 0x00}, + {0x5f38, 0x02}, + {0x5f39, 0x00}, + {0x5f3a, 0x00}, + {0x5f3b, 0x02}, + {0x5f3c, 0x00}, + {0x5f3d, 0x00}, + {0x5f3e, 0x02}, + {0x5f3f, 0x00}, + {0x5f40, 0x00}, + {0x5f41, 0x02}, + {0x5f42, 0x00}, + {0x5f43, 0x00}, + {0x5f44, 0x02}, + {0x5f45, 0x00}, + {0x5f46, 0x00}, + {0x5f47, 0x04}, + {0x5f48, 0x00}, + {0x5f49, 0x00}, + {0x5f4a, 0x04}, + {0x5f4b, 0x00}, + {0x5f4c, 0x00}, + {0x5f4d, 0x04}, + {0x5f4e, 0x00}, + {0x5f50, 0x04}, + {0x5f51, 0x00}, + {0x5f53, 0x04}, + {0x5f54, 0x00}, + {0x5f56, 0x04}, + {0x5f57, 0x00}, + {0x5f59, 0x04}, + {0x5f5a, 0x00}, + {0x5f5c, 0x04}, + {0x5f5d, 0x00}, + {0x5f5f, 0x08}, + {0x5f60, 0x00}, + {0x5f62, 0x08}, + {0x5f63, 0x00}, + {0x5f65, 0x08}, + {0x5f66, 0x00}, + {0x5f68, 0x08}, + {0x5f69, 0x00}, + {0x5f6b, 0x08}, + {0x5f6c, 0x00}, + {0x5f6e, 0x10}, + {0x5f6f, 0x00}, + {0x5f71, 0x10}, + {0x5f72, 0x00}, + {0x5f74, 0x10}, + {0x5f75, 0x00}, + {0x5f77, 0x10}, + {0x5f78, 0x00}, + {0x5f7a, 0x20}, + {0x5f7b, 0x00}, + {0x5f7d, 0x20}, + {0x5f7e, 0x00}, + {0x5f80, 0x20}, + {0x5f81, 0x00}, + {0x5f83, 0x00}, + {0x5f84, 0xff}, + {0x5240, 0x0f}, + {0x5243, 0x00}, + {0x5244, 0x00}, + {0x5245, 0x00}, + {0x5246, 0x00}, + {0x5247, 0x00}, + {0x5248, 0x00}, + {0x5249, 0x00}, + {0x5440, 0x0f}, + {0x5443, 0x00}, + {0x5445, 0x00}, + {0x5447, 0x00}, + {0x5448, 0x00}, + {0x5449, 0x00}, + {0x5640, 0x0f}, + {0x5642, 0x00}, + {0x5643, 0x00}, + {0x5644, 0x00}, + {0x5645, 0x00}, + {0x5646, 0x00}, + {0x5647, 0x00}, + {0x5649, 0x00}, + {0x5840, 0x0f}, + {0x5842, 0x00}, + {0x5843, 0x00}, + {0x5845, 0x00}, + {0x5846, 0x00}, + {0x5847, 0x00}, + {0x5848, 0x00}, + {0x5849, 0x00}, + {0x4001, 0x2b}, + {0x4008, 0x02}, + {0x4009, 0x03}, + {0x4018, 0x12}, + {0x4022, 0x40}, + {0x4023, 0x20}, + {0x4026, 0x00}, + {0x4027, 0x40}, + {0x4028, 0x00}, + {0x4029, 0x40}, + {0x402a, 0x00}, + {0x402b, 0x40}, + {0x402c, 0x00}, + {0x402d, 0x40}, + {0x405e, 0x00}, + {0x405f, 0x00}, + {0x4060, 0x00}, + {0x4061, 0x00}, + {0x4062, 0x00}, + {0x4063, 0x00}, + {0x4064, 0x00}, + {0x4065, 0x00}, + {0x4066, 0x00}, + {0x4067, 0x00}, + {0x4068, 0x00}, + {0x4069, 0x00}, + {0x406a, 0x00}, + {0x406b, 0x00}, + {0x406c, 0x00}, + {0x406d, 0x00}, + {0x406e, 0x00}, + {0x406f, 0x00}, + {0x4070, 0x00}, + {0x4071, 0x00}, + {0x4072, 0x00}, + {0x4073, 0x00}, + {0x4074, 0x00}, + {0x4075, 0x00}, + {0x4076, 0x00}, + {0x4077, 0x00}, + {0x4078, 0x00}, + {0x4079, 0x00}, + {0x407a, 0x00}, + {0x407b, 0x00}, + {0x407c, 0x00}, + {0x407d, 0x00}, + {0x407e, 0xcc}, + {0x407f, 0x18}, + {0x4080, 0xff}, + {0x4081, 0xff}, + {0x4082, 0x01}, + {0x4083, 0x53}, + {0x4084, 0x01}, + {0x4085, 0x2b}, + {0x4086, 0x00}, + {0x4087, 0xb3}, + {0x4640, 0x40}, + {0x4641, 0x11}, + {0x4642, 0x0e}, + {0x4643, 0xee}, + {0x4646, 0x0f}, + {0x4648, 0x00}, + {0x4649, 0x03}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x5b80, 0x08}, + {0x5c00, 0x08}, + {0x5c80, 0x00}, + {0x5bbe, 0x12}, + {0x5c3e, 0x12}, + {0x5cbe, 0x12}, + {0x5b8a, 0x80}, + {0x5b8b, 0x80}, + {0x5b8c, 0x80}, + {0x5b8d, 0x80}, + {0x5b8e, 0x80}, + {0x5b8f, 0x40}, + {0x5b90, 0x80}, + {0x5b91, 0x80}, + {0x5b92, 0x80}, + {0x5b93, 0x60}, + {0x5b94, 0x00}, + {0x5b95, 0x00}, + {0x5b96, 0x40}, + {0x5b97, 0x80}, + {0x5b98, 0x10}, + {0x5b99, 0x00}, + {0x5b9a, 0x00}, + {0x5b9b, 0x00}, + {0x5b9c, 0x00}, + {0x5b9d, 0x00}, + {0x5b9e, 0x00}, + {0x5b9f, 0x00}, + {0x5ba0, 0x00}, + {0x5ba1, 0x00}, + {0x5ba2, 0x00}, + {0x5ba3, 0x00}, + {0x5ba4, 0x00}, + {0x5ba5, 0x00}, + {0x5ba6, 0x00}, + {0x5ba7, 0x00}, + {0x5ba8, 0x00}, + {0x5ba9, 0xc0}, + {0x5baa, 0x01}, + {0x5bab, 0x40}, + {0x5bac, 0x02}, + {0x5bad, 0x40}, + {0x5bae, 0x00}, + {0x5baf, 0x50}, + {0x5bb0, 0x00}, + {0x5bb1, 0x60}, + {0x5bb2, 0x00}, + {0x5bb3, 0xc0}, + {0x5c0a, 0x80}, + {0x5c0b, 0x80}, + {0x5c0c, 0x80}, + {0x5c0d, 0x80}, + {0x5c0e, 0x60}, + {0x5c0f, 0x80}, + {0x5c10, 0x80}, + {0x5c11, 0x80}, + {0x5c12, 0x60}, + {0x5c13, 0x20}, + {0x5c14, 0x80}, + {0x5c15, 0x80}, + {0x5c16, 0x80}, + {0x5c17, 0x20}, + {0x5c18, 0x00}, + {0x5c19, 0x80}, + {0x5c1a, 0x40}, + {0x5c1b, 0x20}, + {0x5c1c, 0x00}, + {0x5c1d, 0x00}, + {0x5c1e, 0x80}, + {0x5c1f, 0x00}, + {0x5c20, 0x00}, + {0x5c21, 0x00}, + {0x5c22, 0x00}, + {0x5c23, 0x00}, + {0x5c24, 0x00}, + {0x5c25, 0x00}, + {0x5c26, 0x00}, + {0x5c27, 0x00}, + {0x5c28, 0x02}, + {0x5c29, 0x00}, + {0x5c2a, 0x02}, + {0x5c2b, 0x76}, + {0x5c2c, 0x03}, + {0x5c2d, 0x08}, + {0x5c2e, 0x00}, + {0x5c2f, 0x80}, + {0x5c30, 0x01}, + {0x5c31, 0x00}, + {0x5c32, 0x02}, + {0x5c33, 0x00}, + {0x5c8a, 0x80}, + {0x5c8b, 0x80}, + {0x5c8c, 0x80}, + {0x5c8d, 0x80}, + {0x5c8e, 0x80}, + {0x5c8f, 0x80}, + {0x5c90, 0x80}, + {0x5c91, 0x80}, + {0x5c92, 0x80}, + {0x5c93, 0x60}, + {0x5c94, 0x80}, + {0x5c95, 0x80}, + {0x5c96, 0x80}, + {0x5c97, 0x60}, + {0x5c98, 0x40}, + {0x5c99, 0x80}, + {0x5c9a, 0x80}, + {0x5c9b, 0x80}, + {0x5c9c, 0x40}, + {0x5c9d, 0x20}, + {0x5c9e, 0x80}, + {0x5c9f, 0x80}, + {0x5ca0, 0x80}, + {0x5ca1, 0x20}, + {0x5ca2, 0x00}, + {0x5ca3, 0x80}, + {0x5ca4, 0x80}, + {0x5ca5, 0x80}, + {0x5ca6, 0x00}, + {0x5ca7, 0x00}, + {0x5ca8, 0x01}, + {0x5ca9, 0x00}, + {0x5caa, 0x02}, + {0x5cab, 0x00}, + {0x5cac, 0x03}, + {0x5cad, 0x08}, + {0x5cae, 0x01}, + {0x5caf, 0x00}, + {0x5cb0, 0x02}, + {0x5cb1, 0x00}, + {0x5cb2, 0x03}, + {0x5cb3, 0x08}, + {0x5be7, 0x80}, + {0x5bc9, 0x80}, + {0x5bca, 0x80}, + {0x5bcb, 0x80}, + {0x5bcc, 0x80}, + {0x5bcd, 0x80}, + {0x5bce, 0x80}, + {0x5bcf, 0x80}, + {0x5bd0, 0x80}, + {0x5bd1, 0x80}, + {0x5bd2, 0x20}, + {0x5bd3, 0x80}, + {0x5bd4, 0x40}, + {0x5bd5, 0x20}, + {0x5bd6, 0x00}, + {0x5bd7, 0x00}, + {0x5bd8, 0x00}, + {0x5bd9, 0x00}, + {0x5bda, 0x00}, + {0x5bdb, 0x00}, + {0x5bdc, 0x00}, + {0x5bdd, 0x00}, + {0x5bde, 0x00}, + {0x5bdf, 0x00}, + {0x5be0, 0x00}, + {0x5be1, 0x00}, + {0x5be2, 0x00}, + {0x5be3, 0x00}, + {0x5be4, 0x00}, + {0x5be5, 0x00}, + {0x5be6, 0x00}, + {0x5c49, 0x80}, + {0x5c4a, 0x80}, + {0x5c4b, 0x80}, + {0x5c4c, 0x80}, + {0x5c4d, 0x40}, + {0x5c4e, 0x80}, + {0x5c4f, 0x80}, + {0x5c50, 0x80}, + {0x5c51, 0x60}, + {0x5c52, 0x20}, + {0x5c53, 0x80}, + {0x5c54, 0x80}, + {0x5c55, 0x80}, + {0x5c56, 0x20}, + {0x5c57, 0x00}, + {0x5c58, 0x80}, + {0x5c59, 0x40}, + {0x5c5a, 0x20}, + {0x5c5b, 0x00}, + {0x5c5c, 0x00}, + {0x5c5d, 0x80}, + {0x5c5e, 0x00}, + {0x5c5f, 0x00}, + {0x5c60, 0x00}, + {0x5c61, 0x00}, + {0x5c62, 0x00}, + {0x5c63, 0x00}, + {0x5c64, 0x00}, + {0x5c65, 0x00}, + {0x5c66, 0x00}, + {0x5cc9, 0x80}, + {0x5cca, 0x80}, + {0x5ccb, 0x80}, + {0x5ccc, 0x80}, + {0x5ccd, 0x80}, + {0x5cce, 0x80}, + {0x5ccf, 0x80}, + {0x5cd0, 0x80}, + {0x5cd1, 0x80}, + {0x5cd2, 0x60}, + {0x5cd3, 0x80}, + {0x5cd4, 0x80}, + {0x5cd5, 0x80}, + {0x5cd6, 0x60}, + {0x5cd7, 0x40}, + {0x5cd8, 0x80}, + {0x5cd9, 0x80}, + {0x5cda, 0x80}, + {0x5cdb, 0x40}, + {0x5cdc, 0x20}, + {0x5cdd, 0x80}, + {0x5cde, 0x80}, + {0x5cdf, 0x80}, + {0x5ce0, 0x20}, + {0x5ce1, 0x00}, + {0x5ce2, 0x80}, + {0x5ce3, 0x80}, + {0x5ce4, 0x80}, + {0x5ce5, 0x00}, + {0x5ce6, 0x00}, + {0x5b84, 0x02}, + {0x5b85, 0xcc}, + {0x5bb4, 0x05}, + {0x5bb5, 0xc6}, + {0x5c04, 0x02}, + {0x5c05, 0xcc}, + {0x5c34, 0x05}, + {0x5c35, 0x33}, + {0x5c84, 0x02}, + {0x5c85, 0xcc}, + {0x5cb4, 0x05}, + {0x5cb5, 0x33}, + {0x5bbf, 0x00}, + {0x5bc0, 0x04}, + {0x5bc1, 0x06}, + {0x5bc2, 0xff}, + {0x5bc3, 0x00}, + {0x5bc4, 0x04}, + {0x5bc5, 0x02}, + {0x5bc6, 0xb8}, + {0x5c3f, 0x00}, + {0x5c40, 0x04}, + {0x5c41, 0x07}, + {0x5c42, 0xff}, + {0x5c43, 0x00}, + {0x5c44, 0x04}, + {0x5c45, 0x03}, + {0x5c46, 0xb8}, + {0x5cbf, 0x00}, + {0x5cc0, 0x20}, + {0x5cc1, 0x07}, + {0x5cc2, 0xff}, + {0x5cc3, 0x00}, + {0x5cc4, 0x20}, + {0x5cc5, 0x03}, + {0x5cc6, 0x00}, + {0x5b86, 0x05}, + {0x5c06, 0x05}, + {0x5c86, 0x05}, + {0x5bb8, 0x01}, + {0x5bb9, 0x01}, + {0x5c38, 0x01}, + {0x5c39, 0x01}, + {0x5cb8, 0x01}, + {0x5cb9, 0x01}, + {0x5bc7, 0x00}, + {0x5bc8, 0x80}, + {0x5c47, 0x00}, + {0x5c48, 0x80}, + {0x5cc7, 0x00}, + {0x5cc8, 0x80}, + {0x5bba, 0x01}, + {0x5bbb, 0x00}, + {0x5c3a, 0x01}, + {0x5c3b, 0x00}, + {0x5cba, 0x01}, + {0x5cbb, 0x00}, + {0x5d74, 0x01}, + {0x5d75, 0x00}, + {0x5d1f, 0x81}, + {0x5d11, 0x00}, + {0x5d12, 0x10}, + {0x5d13, 0x10}, + {0x5d15, 0x05}, + {0x5d16, 0x05}, + {0x5d17, 0x05}, + {0x5d08, 0x03}, + {0x5d09, 0x6b}, + {0x5d0a, 0x03}, + {0x5d0b, 0x6b}, + {0x5d18, 0x03}, + {0x5d19, 0x6b}, + {0x52c6, 0x00}, + {0x52c7, 0x12}, + {0x52c8, 0x04}, + {0x52c9, 0x02}, + {0x52ca, 0x01}, + {0x52cb, 0x01}, + {0x52cc, 0x04}, + {0x52cd, 0x02}, + {0x52ce, 0x01}, + {0x52cf, 0x01}, + {0x52d0, 0x03}, + {0x52d1, 0x08}, + {0x52d2, 0x0c}, + {0x54c6, 0x00}, + {0x54c7, 0x12}, + {0x54c8, 0x04}, + {0x54c9, 0x02}, + {0x54ca, 0x01}, + {0x54cb, 0x01}, + {0x54cc, 0x04}, + {0x54cd, 0x02}, + {0x54ce, 0x01}, + {0x54cf, 0x01}, + {0x54d0, 0x03}, + {0x54d1, 0x08}, + {0x54d2, 0x0c}, + {0x56c6, 0x00}, + {0x56c7, 0x12}, + {0x56c8, 0x04}, + {0x56c9, 0x02}, + {0x56ca, 0x01}, + {0x56cb, 0x01}, + {0x56cc, 0x04}, + {0x56cd, 0x02}, + {0x56ce, 0x01}, + {0x56cf, 0x01}, + {0x56d0, 0x03}, + {0x56d1, 0x08}, + {0x56d2, 0x0c}, + {0x58c6, 0x00}, + {0x58c7, 0x12}, + {0x58c8, 0x04}, + {0x58c9, 0x02}, + {0x58ca, 0x01}, + {0x58cb, 0x01}, + {0x58cc, 0x04}, + {0x58cd, 0x02}, + {0x58ce, 0x01}, + {0x58cf, 0x01}, + {0x58d0, 0x03}, + {0x58d1, 0x08}, + {0x58d2, 0x0c}, + {0x5004, 0x1e}, + {0x610a, 0x07}, + {0x610b, 0x80}, + {0x610c, 0x05}, + {0x610d, 0x00}, + {0x6102, 0x3f}, + {0x5d62, 0x07}, + {0x5d40, 0x02}, + {0x5d41, 0x01}, + {0x5d63, 0x08}, + {0x5d64, 0x01}, + {0x5d65, 0xff}, + {0x5d56, 0x00}, + {0x5d57, 0x20}, + {0x5d58, 0x00}, + {0x5d59, 0x20}, + {0x5d5a, 0x00}, + {0x5d5b, 0x0c}, + {0x5d5c, 0x02}, + {0x5d5d, 0x40}, + {0x5d5e, 0x02}, + {0x5d5f, 0x40}, + {0x5d60, 0x03}, + {0x5d61, 0x40}, + {0x5d4a, 0x02}, + {0x5d4b, 0x40}, + {0x5d4c, 0x02}, + {0x5d4d, 0x40}, + {0x5d4e, 0x02}, + {0x5d4f, 0x40}, + {0x5d50, 0x18}, + {0x5d51, 0x80}, + {0x5d52, 0x18}, + {0x5d53, 0x80}, + {0x5d54, 0x18}, + {0x5d55, 0x80}, + {0x5d46, 0x20}, + {0x5d47, 0x00}, + {0x5d48, 0x22}, + {0x5d49, 0x00}, + {0x5d42, 0x20}, + {0x5d43, 0x00}, + {0x5d44, 0x22}, + {0x5d45, 0x00}, + {0x5b40, 0x01}, + {0x5b41, 0x14}, + {0x5b42, 0x0f}, + {0x5b43, 0xf1}, + {0x5b44, 0x0f}, + {0x5b45, 0xfc}, + {0x5b46, 0x0f}, + {0x5b47, 0xf0}, + {0x5b48, 0x01}, + {0x5b49, 0x02}, + {0x5b4a, 0x00}, + {0x5b4b, 0x0e}, + {0x5b4c, 0x0f}, + {0x5b4d, 0xf1}, + {0x5b4e, 0x0f}, + {0x5b4f, 0xe4}, + {0x5b50, 0x01}, + {0x5b51, 0x2b}, + {0x5b52, 0x01}, + {0x5b53, 0x0f}, + {0x5b54, 0x0f}, + {0x5b55, 0xf1}, + {0x5b56, 0x00}, + {0x5b57, 0x00}, + {0x5b58, 0x0f}, + {0x5b59, 0xeb}, + {0x5b5a, 0x01}, + {0x5b5b, 0x04}, + {0x5b5c, 0x00}, + {0x5b5d, 0x11}, + {0x5b5e, 0x0f}, + {0x5b5f, 0xc8}, + {0x5b60, 0x0f}, + {0x5b61, 0xbd}, + {0x5b62, 0x01}, + {0x5b63, 0x7b}, + {0x5b64, 0x01}, + {0x5b65, 0x11}, + {0x5b66, 0x0f}, + {0x5b67, 0xf4}, + {0x5b68, 0x0f}, + {0x5b69, 0xfb}, + {0x5b6a, 0x0f}, + {0x5b6b, 0xf2}, + {0x5b6c, 0x01}, + {0x5b6d, 0x04}, + {0x5b6e, 0x00}, + {0x5b6f, 0x0a}, + {0x5b70, 0x0f}, + {0x5b71, 0xea}, + {0x5b72, 0x0f}, + {0x5b73, 0xc7}, + {0x5b74, 0x01}, + {0x5b75, 0x4e}, + {0x5b78, 0x00}, + {0x5b79, 0x4c}, + {0x5b7a, 0x00}, + {0x5b7b, 0xb9}, + {0x5b7c, 0x01}, + {0x5b7d, 0x38}, + {0x5b7e, 0x01}, + {0x5280, 0x05}, + {0x5281, 0xf2}, + {0x5282, 0x04}, + {0x5283, 0x00}, + {0x5284, 0x04}, + {0x5285, 0x00}, + {0x5286, 0x07}, + {0x5287, 0x3f}, + {0x4221, 0x13}, + {0x3501, 0x01}, + {0x3502, 0xc8}, + {0x3541, 0x01}, + {0x3542, 0xc8}, + {0x35c1, 0x00}, + {0x35c2, 0x01}, + {0x420e, 0x66}, + {0x420f, 0x5d}, + {0x4210, 0xa8}, + {0x4211, 0x55}, + {0x507a, 0x5f}, + {0x507b, 0x46}, + {0x4f00, 0x00}, + {0x4f01, 0x01}, + {0x4f02, 0x80}, + {0x4f03, 0x2c}, + {0x4f04, 0xf8}, + + {I2C_REG_NULL, 0x00}, +}; + +/* + * hdr_operating_mode: OX03C10_HDR3_DCG_VS_LFM_16BIT + * Note: LFM-bit packed in MIPI RAW 8b format on separate VC (default on MIPI VC1) + */ +static const struct i2c_regval ox03c10_1920x1080_30fps_HDR3_DCG_VS_LFM_PWL16_mipi996[] = { + {0x0103, 0x01}, + {0x0107, 0x01}, + {I2C_REG_DELAY, 6}, + {0x4d5a, 0x1c}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x3208, 0x04}, + {0x4620, 0x04}, + {0x3208, 0x14}, + {0x3208, 0x05}, + {0x4620, 0x04}, + {0x3208, 0x15}, + {0x3208, 0x02}, + {0x3507, 0x00}, + {0x3208, 0x12}, + {0x3208, 0xa2}, + {0x0301, 0xc8}, + {0x0303, 0x01}, + {0x0304, 0x01}, + {0x0305, 0x2c}, + {0x0306, 0x04}, + {0x0307, 0x01}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x00}, + {0x0323, 0x05}, + {0x0324, 0x01}, + {0x0325, 0x2c}, + {0x0400, 0xe0}, + {0x0401, 0x80}, + {0x0403, 0xde}, + {0x0404, 0x34}, + {0x0405, 0x3b}, + {0x0406, 0xde}, + {0x0407, 0x08}, + {0x0408, 0xe0}, + {0x0409, 0x7f}, + {0x040a, 0xde}, + {0x040b, 0x34}, + {0x040c, 0x47}, + {0x040d, 0xd8}, + {0x040e, 0x08}, + {0x2803, 0xfe}, + {0x280b, 0x00}, + {0x280c, 0x79}, + {0x3001, 0x03}, + {0x3002, 0xf8}, + {0x3005, 0x80}, + {0x3007, 0x01}, + {0x3008, 0x80}, + {0x3012, 0x41}, + {0x3020, 0x05}, + {0x3700, 0x28}, + {0x3701, 0x15}, + {0x3702, 0x19}, + {0x3703, 0x23}, + {0x3704, 0x0a}, + {0x3705, 0x00}, + {0x3706, 0x3e}, + {0x3707, 0x0d}, + {0x3708, 0x50}, + {0x3709, 0x5a}, + {0x370a, 0x00}, + {0x370b, 0x96}, + {0x3711, 0x11}, + {0x3712, 0x13}, + {0x3717, 0x02}, + {0x3718, 0x73}, + {0x372c, 0x40}, + {0x3733, 0x01}, + {0x3738, 0x36}, + {0x3739, 0x36}, + {0x373a, 0x25}, + {0x373b, 0x25}, + {0x373f, 0x21}, + {0x3740, 0x21}, + {0x3741, 0x21}, + {0x3742, 0x21}, + {0x3747, 0x28}, + {0x3748, 0x28}, + {0x3749, 0x19}, + {0x3755, 0x1a}, + {0x3756, 0x0a}, + {0x3757, 0x1c}, + {0x3765, 0x19}, + {0x3766, 0x05}, + {0x3767, 0x05}, + {0x3768, 0x13}, + {0x376c, 0x07}, + {0x3778, 0x20}, + {0x377c, 0xc8}, + {0x3781, 0x02}, + {0x3783, 0x02}, + {0x379c, 0x58}, + {0x379e, 0x00}, + {0x379f, 0x00}, + {0x37a0, 0x00}, + {0x37bc, 0x22}, + {0x37c0, 0x01}, + {0x37c4, 0x3e}, + {0x37c5, 0x3e}, + {0x37c6, 0x2a}, + {0x37c7, 0x28}, + {0x37c8, 0x02}, + {0x37c9, 0x12}, + {0x37cb, 0x29}, + {0x37cd, 0x29}, + {0x37d2, 0x00}, + {0x37d3, 0x73}, + {0x37d6, 0x00}, + {0x37d7, 0x6b}, + {0x37dc, 0x00}, + {0x37df, 0x54}, + {0x37e2, 0x00}, + {0x37e3, 0x00}, + {0x37f8, 0x00}, + {0x37f9, 0x01}, + {0x37fa, 0x00}, + {0x37fb, 0x19}, + {0x3c03, 0x01}, + {0x3c04, 0x01}, + {0x3c06, 0x21}, + {0x3c08, 0x01}, + {0x3c09, 0x01}, + {0x3c0a, 0x01}, + {0x3c0b, 0x21}, + {0x3c13, 0x21}, + {0x3c14, 0x82}, + {0x3c16, 0x13}, + {0x3c21, 0x00}, + {0x3c22, 0xf3}, + {0x3c37, 0x12}, + {0x3c38, 0x31}, + {0x3c3c, 0x00}, + {0x3c3d, 0x03}, + {0x3c44, 0x16}, + {0x3c5c, 0x8a}, + {0x3c5f, 0x03}, + {0x3c61, 0x80}, + {0x3c6f, 0x2b}, + {0x3c70, 0x5f}, + {0x3c71, 0x2c}, + {0x3c72, 0x2c}, + {0x3c73, 0x2c}, + {0x3c76, 0x12}, + {0x3182, 0x12}, + {0x320e, 0x00}, + {0x320f, 0x00}, + {0x3211, 0x61}, + {0x3215, 0xcd}, + {0x3219, 0x08}, + {0x3506, 0x30}, + {0x350a, 0x01}, + {0x350b, 0x00}, + {0x350c, 0x00}, + {0x3586, 0x60}, + {0x358a, 0x01}, + {0x358b, 0x00}, + {0x358c, 0x00}, + {0x3541, 0x00}, + {0x3542, 0x04}, + {0x3548, 0x04}, + {0x3549, 0x40}, + {0x354a, 0x01}, + {0x354b, 0x00}, + {0x354c, 0x00}, + {0x35c1, 0x00}, + {0x35c2, 0x02}, + {0x35c6, 0xa0}, + {0x3600, 0x8f}, + {0x3605, 0x16}, + {0x3609, 0xf0}, + {0x360a, 0x01}, + {0x360e, 0x1d}, + {0x360f, 0x10}, + {0x3610, 0x70}, + {0x3611, 0x3a}, + {0x3612, 0x28}, + {0x361a, 0x29}, + {0x361b, 0x6c}, + {0x361c, 0x0b}, + {0x361d, 0x00}, + {0x361e, 0xfc}, + {0x362a, 0x00}, + {0x364d, 0x0f}, + {0x364e, 0x18}, + {0x364f, 0x12}, + {0x3653, 0x1c}, + {0x3654, 0x00}, + {0x3655, 0x1f}, + {0x3656, 0x1f}, + {0x3657, 0x0c}, + {0x3658, 0x0a}, + {0x3659, 0x14}, + {0x365a, 0x18}, + {0x365b, 0x14}, + {0x365c, 0x10}, + {0x365e, 0x12}, + {0x3674, 0x08}, + {0x3677, 0x3a}, + {0x3678, 0x3a}, + {0x3679, 0x19}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3806, 0x05}, + {0x3807, 0x0b}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x05}, + {0x380b, 0x00}, + {0x380c, 0x04}, + {0x380d, 0xd3}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x381c, 0x18}, + {0x381e, 0x01}, + {0x381f, 0x01}, + {0x3820, 0x00}, + {0x3821, 0x19}, + {0x3832, 0x00}, + {0x3834, 0x00}, + {0x384c, 0x02}, + {0x384d, 0x53}, + {0x3850, 0x00}, + {0x3851, 0x42}, + {0x3852, 0x00}, + {0x3853, 0x40}, + {0x3858, 0x04}, + {0x388c, 0x02}, + {0x388d, 0x71}, + {0x3b40, 0x05}, + {0x3b41, 0x40}, + {0x3b42, 0x00}, + {0x3b43, 0x90}, + {0x3b44, 0x00}, + {0x3b45, 0x20}, + {0x3b46, 0x00}, + {0x3b47, 0x20}, + {0x3b48, 0x19}, + {0x3b49, 0x12}, + {0x3b4a, 0x16}, + {0x3b4b, 0x2e}, + {0x3b4c, 0x00}, + {0x3b4d, 0x00}, + {0x3b86, 0x00}, + {0x3b87, 0x34}, + {0x3b88, 0x00}, + {0x3b89, 0x08}, + {0x3b8a, 0x05}, + {0x3b8b, 0x00}, + {0x3b8c, 0x07}, + {0x3b8d, 0x80}, + {0x3b8e, 0x00}, + {0x3b8f, 0x00}, + {0x3b92, 0x05}, + {0x3b93, 0x00}, + {0x3b94, 0x07}, + {0x3b95, 0x80}, + {0x3b9e, 0x09}, + {0x3d82, 0x73}, + {0x3d85, 0x05}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d99, 0x00}, + {0x3d9a, 0x9f}, + {0x3d9b, 0x00}, + {0x3d9c, 0xa0}, + {0x3da4, 0x00}, + {0x3da7, 0x50}, + {0x420e, 0xff}, + {0x420f, 0xff}, + {0x4210, 0xff}, + {0x4211, 0xff}, + {0x421e, 0x02}, + {0x421f, 0x45}, + {0x4220, 0xe1}, + {0x4221, 0x05}, + {0x4301, 0x0f}, + {0x4307, 0x03}, + {0x4308, 0x13}, + {0x430a, 0x53}, + {0x430d, 0x93}, + {0x430f, 0x57}, + {0x4310, 0x95}, + {0x4311, 0x16}, + {0x4316, 0x00}, + {0x4317, 0x08}, + {0x4319, 0x09}, + {0x431a, 0x00}, + {0x431b, 0x22}, + {0x431d, 0x2a}, + {0x431e, 0x11}, + {0x431f, 0x30}, + {0x4320, 0x59}, + {0x4323, 0x80}, + {0x4324, 0x00}, + {0x4503, 0x4e}, + {0x4505, 0x00}, + {0x4509, 0x00}, + {0x450a, 0x00}, + {0x4580, 0xf8}, + {0x4583, 0x07}, + {0x4584, 0x6a}, + {0x4585, 0x08}, + {0x4586, 0x05}, + {0x4587, 0x04}, + {0x4588, 0x73}, + {0x4589, 0x05}, + {0x458a, 0x1f}, + {0x458b, 0x02}, + {0x458c, 0xdc}, + {0x458d, 0x03}, + {0x458e, 0x02}, + {0x4597, 0x07}, + {0x4598, 0x40}, + {0x4599, 0x0e}, + {0x459a, 0x0e}, + {0x459b, 0xfb}, + {0x459c, 0xf3}, + {0x4602, 0x00}, + {0x4603, 0x13}, + {0x4604, 0x00}, + {0x4609, 0x0a}, + {0x460a, 0x00}, + {0x4610, 0x00}, + {0x4611, 0x70}, + {0x4612, 0x00}, + {0x4613, 0x0c}, + {0x4614, 0x00}, + {0x4615, 0x70}, + {0x4616, 0x00}, + {0x4617, 0x0c}, + {0x4800, 0x04}, + {0x480a, 0x22}, + {0x4813, 0xe4}, + {0x4814, 0x2a}, + {0x4837, 0x0d}, + {0x484b, 0x47}, + {0x484f, 0x40}, + {0x4887, 0x51}, + {0x4d00, 0x4a}, + {0x4d01, 0x18}, + {0x4d05, 0xff}, + {0x4d06, 0x88}, + {0x4d08, 0x63}, + {0x4d09, 0xdf}, + {0x4d15, 0x7d}, + {0x4d1a, 0x20}, + {0x4d30, 0x0a}, + {0x4d31, 0x00}, + {0x4d34, 0x7d}, + {0x4d3c, 0x7d}, + {0x4f00, 0x3f}, + {0x4f01, 0xff}, + {0x4f02, 0xff}, + {0x4f03, 0x2c}, + {0x4f04, 0xe0}, + {0x6a00, 0x00}, + {0x6a01, 0x20}, + {0x6a02, 0x00}, + {0x6a03, 0x20}, + {0x6a04, 0x02}, + {0x6a05, 0x80}, + {0x6a06, 0x01}, + {0x6a07, 0xe0}, + {0x6a08, 0xcf}, + {0x6a09, 0x01}, + {0x6a0a, 0x40}, + {0x6a20, 0x00}, + {0x6a21, 0x02}, + {0x6a22, 0x00}, + {0x6a23, 0x00}, + {0x6a24, 0x00}, + {0x6a25, 0xf0}, + {0x6a26, 0x00}, + {0x6a27, 0x00}, + {0x6a28, 0x00}, + {0x5000, 0x8f}, + {0x5001, 0x65}, + {0x5002, 0x7f}, + {0x5003, 0x6a}, + {0x5004, 0x3e}, + {0x5005, 0x1e}, + {0x5006, 0x1e}, + {0x5007, 0x1e}, + {0x5008, 0x00}, + {0x500c, 0x00}, + {0x502c, 0x00}, + {0x502e, 0x00}, + {0x502f, 0x00}, + {0x504b, 0x00}, + {0x5053, 0x00}, + {0x505b, 0x00}, + {0x5063, 0x00}, + {0x5070, 0x00}, + {0x5074, 0x04}, + {0x507a, 0x00}, + {0x507b, 0x00}, + {0x5500, 0x02}, + {0x5700, 0x02}, + {0x5900, 0x02}, + {0x6007, 0x04}, + {0x6008, 0x05}, + {0x6009, 0x02}, + {0x600b, 0x08}, + {0x600c, 0x07}, + {0x600d, 0x88}, + {0x6016, 0x00}, + {0x6027, 0x04}, + {0x6028, 0x05}, + {0x6029, 0x02}, + {0x602b, 0x08}, + {0x602c, 0x07}, + {0x602d, 0x88}, + {0x6047, 0x04}, + {0x6048, 0x05}, + {0x6049, 0x02}, + {0x604b, 0x08}, + {0x604c, 0x07}, + {0x604d, 0x88}, + {0x6067, 0x04}, + {0x6068, 0x05}, + {0x6069, 0x02}, + {0x606b, 0x08}, + {0x606c, 0x07}, + {0x606d, 0x88}, + {0x6087, 0x04}, + {0x6088, 0x05}, + {0x6089, 0x02}, + {0x608b, 0x08}, + {0x608c, 0x07}, + {0x608d, 0x88}, + {0x5e00, 0x02}, + {0x5e01, 0x0b}, + {0x5e02, 0x00}, + {0x5e03, 0x00}, + {0x5e04, 0x00}, + {0x5e05, 0x0b}, + {0x5e06, 0x0c}, + {0x5e07, 0x0c}, + {0x5e08, 0x0c}, + {0x5e09, 0x0c}, + {0x5e0a, 0x0c}, + {0x5e0b, 0x0d}, + {0x5e0c, 0x0d}, + {0x5e0d, 0x0d}, + {0x5e0e, 0x0d}, + {0x5e0f, 0x0d}, + {0x5e10, 0x0d}, + {0x5e11, 0x0d}, + {0x5e12, 0x0e}, + {0x5e13, 0x0e}, + {0x5e14, 0x0e}, + {0x5e15, 0x0e}, + {0x5e16, 0x0e}, + {0x5e17, 0x0e}, + {0x5e18, 0x0e}, + {0x5e19, 0x10}, + {0x5e1a, 0x11}, + {0x5e1b, 0x11}, + {0x5e1c, 0x12}, + {0x5e1d, 0x12}, + {0x5e1e, 0x14}, + {0x5e1f, 0x15}, + {0x5e20, 0x16}, + {0x5e21, 0x17}, + {0x5e22, 0x00}, + {0x5e23, 0x08}, + {0x5e26, 0x00}, + {0x5e27, 0x00}, + {0x5e29, 0x00}, + {0x5e2a, 0x00}, + {0x5e2c, 0x00}, + {0x5e2d, 0x00}, + {0x5e2f, 0x03}, + {0x5e30, 0xff}, + {0x5e32, 0x04}, + {0x5e33, 0x00}, + {0x5e34, 0x00}, + {0x5e35, 0x04}, + {0x5e36, 0x00}, + {0x5e37, 0x00}, + {0x5e38, 0x04}, + {0x5e39, 0x00}, + {0x5e3a, 0x00}, + {0x5e3b, 0x04}, + {0x5e3c, 0x00}, + {0x5e3d, 0x00}, + {0x5e3e, 0x04}, + {0x5e3f, 0x00}, + {0x5e40, 0x00}, + {0x5e41, 0x06}, + {0x5e42, 0x00}, + {0x5e43, 0x00}, + {0x5e44, 0x06}, + {0x5e45, 0x00}, + {0x5e46, 0x00}, + {0x5e47, 0x06}, + {0x5e48, 0x00}, + {0x5e49, 0x00}, + {0x5e4a, 0x06}, + {0x5e4b, 0x00}, + {0x5e4c, 0x00}, + {0x5e4d, 0x06}, + {0x5e4e, 0x00}, + {0x5e50, 0x06}, + {0x5e51, 0x00}, + {0x5e53, 0x06}, + {0x5e54, 0x00}, + {0x5e56, 0x08}, + {0x5e57, 0x00}, + {0x5e59, 0x08}, + {0x5e5a, 0x00}, + {0x5e5c, 0x08}, + {0x5e5d, 0x00}, + {0x5e5f, 0x08}, + {0x5e60, 0x00}, + {0x5e62, 0x08}, + {0x5e63, 0x00}, + {0x5e65, 0x08}, + {0x5e66, 0x00}, + {0x5e68, 0x08}, + {0x5e69, 0x00}, + {0x5e6b, 0x16}, + {0x5e6c, 0x00}, + {0x5e6e, 0x20}, + {0x5e6f, 0x00}, + {0x5e71, 0x18}, + {0x5e72, 0x00}, + {0x5e74, 0x18}, + {0x5e75, 0x00}, + {0x5e77, 0x17}, + {0x5e78, 0xff}, + {0x5e7a, 0x00}, + {0x5e7b, 0x00}, + {0x5e7d, 0x00}, + {0x5e7e, 0x00}, + {0x5e80, 0x00}, + {0x5e81, 0x00}, + {0x5e83, 0x00}, + {0x5e84, 0x00}, + {0x5f00, 0x02}, + {0x5f01, 0x08}, + {0x5f02, 0x09}, + {0x5f03, 0x0a}, + {0x5f04, 0x0b}, + {0x5f05, 0x0c}, + {0x5f06, 0x0c}, + {0x5f07, 0x0c}, + {0x5f08, 0x0c}, + {0x5f09, 0x0c}, + {0x5f0a, 0x0d}, + {0x5f0b, 0x0d}, + {0x5f0c, 0x0d}, + {0x5f0d, 0x0d}, + {0x5f0e, 0x0d}, + {0x5f0f, 0x0e}, + {0x5f10, 0x0e}, + {0x5f11, 0x0e}, + {0x5f12, 0x0e}, + {0x5f13, 0x0f}, + {0x5f14, 0x0f}, + {0x5f15, 0x10}, + {0x5f16, 0x11}, + {0x5f17, 0x11}, + {0x5f18, 0x12}, + {0x5f19, 0x12}, + {0x5f1a, 0x13}, + {0x5f1b, 0x13}, + {0x5f1c, 0x14}, + {0x5f1d, 0x14}, + {0x5f1e, 0x16}, + {0x5f1f, 0x16}, + {0x5f20, 0x16}, + {0x5f21, 0x08}, + {0x5f22, 0x00}, + {0x5f23, 0x01}, + {0x5f26, 0x02}, + {0x5f27, 0x00}, + {0x5f29, 0x02}, + {0x5f2a, 0x00}, + {0x5f2c, 0x02}, + {0x5f2d, 0x00}, + {0x5f2f, 0x02}, + {0x5f30, 0x00}, + {0x5f32, 0x02}, + {0x5f33, 0x00}, + {0x5f34, 0x00}, + {0x5f35, 0x02}, + {0x5f36, 0x00}, + {0x5f37, 0x00}, + {0x5f38, 0x02}, + {0x5f39, 0x00}, + {0x5f3a, 0x00}, + {0x5f3b, 0x02}, + {0x5f3c, 0x00}, + {0x5f3d, 0x00}, + {0x5f3e, 0x02}, + {0x5f3f, 0x00}, + {0x5f40, 0x00}, + {0x5f41, 0x02}, + {0x5f42, 0x00}, + {0x5f43, 0x00}, + {0x5f44, 0x02}, + {0x5f45, 0x00}, + {0x5f46, 0x00}, + {0x5f47, 0x04}, + {0x5f48, 0x00}, + {0x5f49, 0x00}, + {0x5f4a, 0x04}, + {0x5f4b, 0x00}, + {0x5f4c, 0x00}, + {0x5f4d, 0x04}, + {0x5f4e, 0x00}, + {0x5f50, 0x04}, + {0x5f51, 0x00}, + {0x5f53, 0x04}, + {0x5f54, 0x00}, + {0x5f56, 0x04}, + {0x5f57, 0x00}, + {0x5f59, 0x04}, + {0x5f5a, 0x00}, + {0x5f5c, 0x04}, + {0x5f5d, 0x00}, + {0x5f5f, 0x08}, + {0x5f60, 0x00}, + {0x5f62, 0x08}, + {0x5f63, 0x00}, + {0x5f65, 0x08}, + {0x5f66, 0x00}, + {0x5f68, 0x08}, + {0x5f69, 0x00}, + {0x5f6b, 0x08}, + {0x5f6c, 0x00}, + {0x5f6e, 0x10}, + {0x5f6f, 0x00}, + {0x5f71, 0x10}, + {0x5f72, 0x00}, + {0x5f74, 0x10}, + {0x5f75, 0x00}, + {0x5f77, 0x10}, + {0x5f78, 0x00}, + {0x5f7a, 0x20}, + {0x5f7b, 0x00}, + {0x5f7d, 0x20}, + {0x5f7e, 0x00}, + {0x5f80, 0x20}, + {0x5f81, 0x00}, + {0x5f83, 0x00}, + {0x5f84, 0xff}, + {0x5240, 0x0f}, + {0x5243, 0x00}, + {0x5244, 0x00}, + {0x5245, 0x00}, + {0x5246, 0x00}, + {0x5247, 0x00}, + {0x5248, 0x00}, + {0x5249, 0x00}, + {0x5440, 0x0f}, + {0x5443, 0x00}, + {0x5445, 0x00}, + {0x5447, 0x00}, + {0x5448, 0x00}, + {0x5449, 0x00}, + {0x5640, 0x0f}, + {0x5642, 0x00}, + {0x5643, 0x00}, + {0x5644, 0x00}, + {0x5645, 0x00}, + {0x5646, 0x00}, + {0x5647, 0x00}, + {0x5649, 0x00}, + {0x5840, 0x0f}, + {0x5842, 0x00}, + {0x5843, 0x00}, + {0x5845, 0x00}, + {0x5846, 0x00}, + {0x5847, 0x00}, + {0x5848, 0x00}, + {0x5849, 0x00}, + {0x4001, 0x2b}, + {0x4008, 0x02}, + {0x4009, 0x03}, + {0x4018, 0x12}, + {0x4022, 0x40}, + {0x4023, 0x20}, + {0x4026, 0x00}, + {0x4027, 0x40}, + {0x4028, 0x00}, + {0x4029, 0x40}, + {0x402a, 0x00}, + {0x402b, 0x40}, + {0x402c, 0x00}, + {0x402d, 0x40}, + {0x405e, 0x00}, + {0x405f, 0x00}, + {0x4060, 0x00}, + {0x4061, 0x00}, + {0x4062, 0x00}, + {0x4063, 0x00}, + {0x4064, 0x00}, + {0x4065, 0x00}, + {0x4066, 0x00}, + {0x4067, 0x00}, + {0x4068, 0x00}, + {0x4069, 0x00}, + {0x406a, 0x00}, + {0x406b, 0x00}, + {0x406c, 0x00}, + {0x406d, 0x00}, + {0x406e, 0x00}, + {0x406f, 0x00}, + {0x4070, 0x00}, + {0x4071, 0x00}, + {0x4072, 0x00}, + {0x4073, 0x00}, + {0x4074, 0x00}, + {0x4075, 0x00}, + {0x4076, 0x00}, + {0x4077, 0x00}, + {0x4078, 0x00}, + {0x4079, 0x00}, + {0x407a, 0x00}, + {0x407b, 0x00}, + {0x407c, 0x00}, + {0x407d, 0x00}, + {0x407e, 0xcc}, + {0x407f, 0x18}, + {0x4080, 0xff}, + {0x4081, 0xff}, + {0x4082, 0x01}, + {0x4083, 0x53}, + {0x4084, 0x01}, + {0x4085, 0x2b}, + {0x4086, 0x00}, + {0x4087, 0xb3}, + {0x4640, 0x40}, + {0x4641, 0x11}, + {0x4642, 0x0e}, + {0x4643, 0xee}, + {0x4646, 0x0f}, + {0x4648, 0x00}, + {0x4649, 0x03}, + {0x4f04, 0xf8}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x5003, 0x7a}, + {0x5b80, 0x08}, + {0x5c00, 0x08}, + {0x5c80, 0x00}, + {0x5bbe, 0x12}, + {0x5c3e, 0x12}, + {0x5cbe, 0x12}, + {0x5b8a, 0x80}, + {0x5b8b, 0x80}, + {0x5b8c, 0x80}, + {0x5b8d, 0x80}, + {0x5b8e, 0x60}, + {0x5b8f, 0x80}, + {0x5b90, 0x80}, + {0x5b91, 0x80}, + {0x5b92, 0x80}, + {0x5b93, 0x20}, + {0x5b94, 0x80}, + {0x5b95, 0x80}, + {0x5b96, 0x80}, + {0x5b97, 0x20}, + {0x5b98, 0x00}, + {0x5b99, 0x80}, + {0x5b9a, 0x40}, + {0x5b9b, 0x20}, + {0x5b9c, 0x00}, + {0x5b9d, 0x00}, + {0x5b9e, 0x80}, + {0x5b9f, 0x00}, + {0x5ba0, 0x00}, + {0x5ba1, 0x00}, + {0x5ba2, 0x00}, + {0x5ba3, 0x00}, + {0x5ba4, 0x00}, + {0x5ba5, 0x00}, + {0x5ba6, 0x00}, + {0x5ba7, 0x00}, + {0x5ba8, 0x02}, + {0x5ba9, 0x00}, + {0x5baa, 0x02}, + {0x5bab, 0x76}, + {0x5bac, 0x03}, + {0x5bad, 0x08}, + {0x5bae, 0x00}, + {0x5baf, 0x80}, + {0x5bb0, 0x00}, + {0x5bb1, 0xc0}, + {0x5bb2, 0x01}, + {0x5bb3, 0x00}, + {0x5c0a, 0x80}, + {0x5c0b, 0x80}, + {0x5c0c, 0x80}, + {0x5c0d, 0x80}, + {0x5c0e, 0x60}, + {0x5c0f, 0x80}, + {0x5c10, 0x80}, + {0x5c11, 0x80}, + {0x5c12, 0x60}, + {0x5c13, 0x20}, + {0x5c14, 0x80}, + {0x5c15, 0x80}, + {0x5c16, 0x80}, + {0x5c17, 0x20}, + {0x5c18, 0x00}, + {0x5c19, 0x80}, + {0x5c1a, 0x40}, + {0x5c1b, 0x20}, + {0x5c1c, 0x00}, + {0x5c1d, 0x00}, + {0x5c1e, 0x80}, + {0x5c1f, 0x00}, + {0x5c20, 0x00}, + {0x5c21, 0x00}, + {0x5c22, 0x00}, + {0x5c23, 0x00}, + {0x5c24, 0x00}, + {0x5c25, 0x00}, + {0x5c26, 0x00}, + {0x5c27, 0x00}, + {0x5c28, 0x02}, + {0x5c29, 0x00}, + {0x5c2a, 0x02}, + {0x5c2b, 0x76}, + {0x5c2c, 0x03}, + {0x5c2d, 0x08}, + {0x5c2e, 0x00}, + {0x5c2f, 0x80}, + {0x5c30, 0x00}, + {0x5c31, 0xc0}, + {0x5c32, 0x01}, + {0x5c33, 0x00}, + {0x5c8a, 0x80}, + {0x5c8b, 0x80}, + {0x5c8c, 0x80}, + {0x5c8d, 0x80}, + {0x5c8e, 0x80}, + {0x5c8f, 0x80}, + {0x5c90, 0x80}, + {0x5c91, 0x80}, + {0x5c92, 0x80}, + {0x5c93, 0x60}, + {0x5c94, 0x80}, + {0x5c95, 0x80}, + {0x5c96, 0x80}, + {0x5c97, 0x60}, + {0x5c98, 0x40}, + {0x5c99, 0x80}, + {0x5c9a, 0x80}, + {0x5c9b, 0x80}, + {0x5c9c, 0x40}, + {0x5c9d, 0x00}, + {0x5c9e, 0x80}, + {0x5c9f, 0x80}, + {0x5ca0, 0x80}, + {0x5ca1, 0x20}, + {0x5ca2, 0x00}, + {0x5ca3, 0x80}, + {0x5ca4, 0x80}, + {0x5ca5, 0x00}, + {0x5ca6, 0x00}, + {0x5ca7, 0x00}, + {0x5ca8, 0x01}, + {0x5ca9, 0x00}, + {0x5caa, 0x02}, + {0x5cab, 0x00}, + {0x5cac, 0x03}, + {0x5cad, 0x08}, + {0x5cae, 0x01}, + {0x5caf, 0x00}, + {0x5cb0, 0x02}, + {0x5cb1, 0x00}, + {0x5cb2, 0x03}, + {0x5cb3, 0x08}, + {0x5be7, 0x80}, + {0x5bc9, 0x80}, + {0x5bca, 0x80}, + {0x5bcb, 0x80}, + {0x5bcc, 0x80}, + {0x5bcd, 0x80}, + {0x5bce, 0x80}, + {0x5bcf, 0x80}, + {0x5bd0, 0x80}, + {0x5bd1, 0x80}, + {0x5bd2, 0x20}, + {0x5bd3, 0x80}, + {0x5bd4, 0x40}, + {0x5bd5, 0x20}, + {0x5bd6, 0x00}, + {0x5bd7, 0x00}, + {0x5bd8, 0x00}, + {0x5bd9, 0x00}, + {0x5bda, 0x00}, + {0x5bdb, 0x00}, + {0x5bdc, 0x00}, + {0x5bdd, 0x00}, + {0x5bde, 0x00}, + {0x5bdf, 0x00}, + {0x5be0, 0x00}, + {0x5be1, 0x00}, + {0x5be2, 0x00}, + {0x5be3, 0x00}, + {0x5be4, 0x00}, + {0x5be5, 0x00}, + {0x5be6, 0x00}, + {0x5c49, 0x80}, + {0x5c4a, 0x80}, + {0x5c4b, 0x80}, + {0x5c4c, 0x80}, + {0x5c4d, 0x40}, + {0x5c4e, 0x80}, + {0x5c4f, 0x80}, + {0x5c50, 0x80}, + {0x5c51, 0x60}, + {0x5c52, 0x20}, + {0x5c53, 0x80}, + {0x5c54, 0x80}, + {0x5c55, 0x80}, + {0x5c56, 0x20}, + {0x5c57, 0x00}, + {0x5c58, 0x80}, + {0x5c59, 0x40}, + {0x5c5a, 0x20}, + {0x5c5b, 0x00}, + {0x5c5c, 0x00}, + {0x5c5d, 0x80}, + {0x5c5e, 0x00}, + {0x5c5f, 0x00}, + {0x5c60, 0x00}, + {0x5c61, 0x00}, + {0x5c62, 0x00}, + {0x5c63, 0x00}, + {0x5c64, 0x00}, + {0x5c65, 0x00}, + {0x5c66, 0x00}, + {0x5cc9, 0x80}, + {0x5cca, 0x80}, + {0x5ccb, 0x80}, + {0x5ccc, 0x80}, + {0x5ccd, 0x80}, + {0x5cce, 0x80}, + {0x5ccf, 0x80}, + {0x5cd0, 0x80}, + {0x5cd1, 0x80}, + {0x5cd2, 0x60}, + {0x5cd3, 0x80}, + {0x5cd4, 0x80}, + {0x5cd5, 0x80}, + {0x5cd6, 0x60}, + {0x5cd7, 0x40}, + {0x5cd8, 0x80}, + {0x5cd9, 0x80}, + {0x5cda, 0x80}, + {0x5cdb, 0x40}, + {0x5cdc, 0x20}, + {0x5cdd, 0x80}, + {0x5cde, 0x80}, + {0x5cdf, 0x80}, + {0x5ce0, 0x20}, + {0x5ce1, 0x00}, + {0x5ce2, 0x80}, + {0x5ce3, 0x80}, + {0x5ce4, 0x80}, + {0x5ce5, 0x00}, + {0x5ce6, 0x00}, + {0x5d74, 0x01}, + {0x5d75, 0x00}, + {0x5d1f, 0x81}, + {0x5d11, 0x00}, + {0x5d12, 0x10}, + {0x5d13, 0x10}, + {0x5d15, 0x05}, + {0x5d16, 0x05}, + {0x5d17, 0x05}, + {0x5d08, 0x03}, + {0x5d09, 0xb6}, + {0x5d0a, 0x03}, + {0x5d0b, 0xb6}, + {0x5d18, 0x03}, + {0x5d19, 0xb6}, + {0x5d62, 0x01}, + {0x5d40, 0x02}, + {0x5d41, 0x01}, + {0x5d63, 0x1f}, + {0x5d64, 0x00}, + {0x5d65, 0x80}, + {0x5d56, 0x00}, + {0x5d57, 0x20}, + {0x5d58, 0x00}, + {0x5d59, 0x20}, + {0x5d5a, 0x00}, + {0x5d5b, 0x0c}, + {0x5d5c, 0x02}, + {0x5d5d, 0x40}, + {0x5d5e, 0x02}, + {0x5d5f, 0x40}, + {0x5d60, 0x03}, + {0x5d61, 0x40}, + {0x5d4a, 0x02}, + {0x5d4b, 0x40}, + {0x5d4c, 0x02}, + {0x5d4d, 0x40}, + {0x5d4e, 0x02}, + {0x5d4f, 0x40}, + {0x5d50, 0x18}, + {0x5d51, 0x80}, + {0x5d52, 0x18}, + {0x5d53, 0x80}, + {0x5d54, 0x18}, + {0x5d55, 0x80}, + {0x5d46, 0x20}, + {0x5d47, 0x00}, + {0x5d48, 0x22}, + {0x5d49, 0x00}, + {0x5d42, 0x20}, + {0x5d43, 0x00}, + {0x5d44, 0x22}, + {0x5d45, 0x00}, + {0x5004, 0x1e}, + {0x4221, 0x03}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x380c, 0x04}, + {0x380d, 0x47}, + {0x384c, 0x02}, + {0x384d, 0x0d}, + {0x388c, 0x02}, + {0x388d, 0x2b}, + {0x420e, 0x54}, + {0x420f, 0xa0}, + {0x4210, 0xca}, + {0x4211, 0xf2}, + {0x507a, 0x5f}, + {0x507b, 0x46}, + {0x3802, 0x00}, + {0x3803, 0x68}, + {0x3806, 0x04}, + {0x3807, 0xa7}, + {0x380a, 0x04}, + {0x380b, 0x38}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x380c, 0x08}, + {0x380d, 0x8e}, + {0x384c, 0x04}, + {0x384d, 0x1a}, + {0x388c, 0x04}, + {0x388d, 0x56}, + {0x0304, 0x00}, + {0x0305, 0xf9}, + {0x4837, 0x10}, + {0x0408, 0x78}, + {0x0409, 0x00}, + {0x040a, 0xd1}, + {0x040b, 0x1e}, + {0x040c, 0x2e}, + {0x040d, 0x44}, + {0x040e, 0x0c}, + + {I2C_REG_NULL, 0x00}, +}; + +// Switch to linear bypass mode: LCG RAW10 +static const struct i2c_regval ox03c10_switch_linear_lcg_raw10[] = { + {0x4221, 0x05}, + {0x5002, 0x3f}, // PWL 1 & 0 disable, Re-timing enable, Statistic block 4/3/2/1/0 enable + {0x5003, 0x2a}, // Combine enable, Combine sync buffer enable, HDR sync buffer enable + {0x502c, 0x0f}, // Manual set V/S/M/L channel exposure index enable + {0x504b, 0x04}, // Manual exposure index for L channel + {0x5053, 0x03}, // Manual exposure index for M channel + {0x505b, 0x02}, // Manual exposure index for S channel + {0x5063, 0x01}, // Manual exposure index for V channel + {0x5074, 0x59}, // Manual combine out option: Non-combine out + // Manual select exposure out when in non-combine out mode: 1 + // 0x49: HCG, 0x59: LCG, 0x69: SPD, 0x79: VS + // Manual exposure mode: enable & 2 exposure combine + {0x4319, 0x43}, // Force VFIFO/MIPI bitwidth for other group1, Use SPD in combine, Enable DCG combine + {0x431a, 0x01}, // mipi_bitw_man0: 10bit + + {I2C_REG_NULL, 0x00}, +}; + +static struct rkmodule_hdr_compr ox03c10_hdr_compr_12 = { + .point = 30, + .src_bit = 20, + .k_shift = 7, + .data_src = {0, 256, 768, 1792, 3840, 7936, 12032, 16128, 20224, 24320, + 32512, 40704, 48896, 57088, 65280, 73472, 81664, 89856, 106240, 122624, + 139008, 155392, 171776, 188160, 204544, 270080, 401152, 532224, 794368, 1056512}, + .data_compr = {0, 256, 320, 384, 448, 512, 576, 640, 704, 768, + 832, 928, 1024, 1120, 1216, 1312, 1408, 1504, 1632, 1760, + 1888, 2016, 2144, 2272, 2400, 2688, 3152, 3456, 3840, 4096}, + .slope_k = {128, 1024, 2048, 4096, 8192, 8192, 8192, 8192, 8192, 16384, + 10922, 10922, 10922, 10922, 10922, 10922, 10922, 16384, 16384, 16384, + 16384, 16384, 16384, 16384, 29127, 36157, 55188, 87381, 131072, 0}, +}; + +static struct rkmodule_hdr_compr ox03c10_hdr_compr_16 = { + .point = 30, + .src_bit = 20, + .k_shift = 12, + .data_src = {0, 2048, 2048, 2048, 2048, 4096, 8192, 12288, 16384, 20480, + 24576, 32768, 40960, 49152, 57344, 65536, 73728, 81920, 98304, 114688, + 131072, 147456, 163840, 180224, 196608, 262144, 393216, 524288, 786432, 1048576}, + .data_compr = {0, 2048, 2048, 2048, 2048, 3071, 4095, 5119, 6143, 7167, + 8191, 9727, 11263, 12799, 14335, 15871, 17407, 18943, 20991, 23039, + 25087, 27135, 29183, 31231, 33279, 38911, 47103, 53247, 59391, 65534}, + .slope_k = {4096, 0, 0, 0, 8200, 16384, 16384, 16384, 16384, 16384, + 21845, 21845, 21845, 21845, 21845, 21845, 21845, 32768, 32768, 32768, + 32768, 32768, 32768, 32768, 47662, 65536, 87381, 174762, 174762, 0}, +}; + +/* + * The width and height must be configured to be + * the same as the current output resolution of the sensor. + * The input width of the isp needs to be 16 aligned. + * The input height of the isp needs to be 8 aligned. + * If the width or height does not meet the alignment rules, + * you can configure the cropping parameters with the following function to + * crop out the appropriate resolution. + * struct v4l2_subdev_pad_ops { + * .get_selection + * } + */ +static const struct ox03c10_mode supported_modes[] = { + { /* NO_HDR: RAW10 */ + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0200, + .hts_def = 0x10FE, + .vts_def = 0x02AE * 2, + .exp_mode = EXP_NORMAL, + .bpp = 10, + .link_freq_idx = 0, + .hdr_mode = NO_HDR, + .hdr_compr = NULL, + .reg_list = ox03c10_1920x1080_30fps_HDR3_DCG_VS_PWL12_mipi600, + .linear_reg_list = ox03c10_switch_linear_lcg_raw10, +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + .vc[PAD0] = 0, +#else + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, +#endif /* LINUX_VERSION_CODE */ + }, + { /* HDR_COMPR: OX03C10_HDR3_DCG_VS_12BIT */ + .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12, + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0200, + .hts_def = 0x10FE, + .vts_def = 0x02AE * 2, + .exp_mode = EXP_HDR3_DCG_VS, + .bpp = 12, + .link_freq_idx = 0, + .hdr_mode = HDR_COMPR, + .hdr_compr = &ox03c10_hdr_compr_12, + .hdr_operating_mode = OX03C10_HDR3_DCG_VS_12BIT, + .reg_list = ox03c10_1920x1080_30fps_HDR3_DCG_VS_PWL12_mipi600, +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + .vc[PAD0] = 0, +#else + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, +#endif /* LINUX_VERSION_CODE */ + }, + { /* HDR_COMPR: OX03C10_HDR3_DCG_SPD_12BIT */ + .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12, + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0200, + .hts_def = 0x10FE, + .vts_def = 0x02AE * 2, + .exp_mode = EXP_HDR3_DCG_SPD, + .bpp = 12, + .link_freq_idx = 0, + .hdr_mode = HDR_COMPR, + .hdr_compr = &ox03c10_hdr_compr_12, + .hdr_operating_mode = OX03C10_HDR3_DCG_SPD_12BIT, + .reg_list = ox03c10_1920x1080_30fps_HDR3_DCG_SPD_PWL12_mipi600, +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + .vc[PAD0] = 0, +#else + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, +#endif /* LINUX_VERSION_CODE */ + }, + { /* HDR_COMPR: OX03C10_HDR3_DCG_VS_LFM_16BIT */ + .bus_fmt = MEDIA_BUS_FMT_SBGGR16_1X16, + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0038, + .hts_def = 0x10FE, + .vts_def = 0x02AE * 2, + .exp_mode = EXP_HDR3_DCG_VS, + .bpp = 16, + .link_freq_idx = 1, + .hdr_mode = HDR_COMPR, + .hdr_compr = &ox03c10_hdr_compr_16, + .hdr_operating_mode = OX03C10_HDR3_DCG_VS_LFM_16BIT, + .reg_list = ox03c10_1920x1080_30fps_HDR3_DCG_VS_LFM_PWL16_mipi996, +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + .vc[PAD0] = 0, +#else + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0, +#endif /* LINUX_VERSION_CODE */ + }, +}; + +static const s64 link_freq_menu_items[] = { + OX03C10_LINK_FREQ_300MHZ, + OX03C10_LINK_FREQ_480MHZ, +}; + +static const char * const ox03c10_test_pattern_menu[] = { + "Disabled", + "Vertical Color Bar Type 1", + "Vertical Color Bar Type 2", + "Vertical Color Bar Type 3", + "Vertical Color Bar Type 4" +}; + +/* Write registers up to 4 at a time */ +static int __maybe_unused ox03c10_i2c_write_reg(struct i2c_client *client, + u16 reg_addr, u32 val_len, u32 reg_val) +{ + u32 buf_i, val_i; + u8 buf[6]; + u8 *val_p; + __be32 val_be; + + dev_info(&client->dev, "i2c addr(0x%02x) write: 0x%04x = 0x%08x (%d)\n", + client->addr, reg_addr, reg_val, val_len); + + if (val_len > 4) + return -EINVAL; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xff; + buf_i = 2; + + val_be = cpu_to_be32(reg_val); + val_p = (u8 *)&val_be; + val_i = 4 - val_len; + + while (val_i < 4) + buf[buf_i++] = val_p[val_i++]; + + if (i2c_master_send(client, buf, (val_len + 2)) != (val_len + 2)) { + dev_err(&client->dev, + "%s: writing register 0x%04x from 0x%02x failed\n", + __func__, reg_addr, client->addr); + return -EIO; + } + + return 0; +} + +/* Read registers up to 4 at a time */ +static int __maybe_unused ox03c10_i2c_read_reg(struct i2c_client *client, + u16 reg_addr, u32 val_len, u32 *reg_val) +{ + struct i2c_msg msgs[2]; + u8 *data_be_p; + __be32 data_be = 0; + __be16 reg_addr_be = cpu_to_be16(reg_addr); + u8 *reg_be_p; + int ret; + + if (val_len > 4 || !val_len) + return -EINVAL; + + data_be_p = (u8 *)&data_be; + reg_be_p = (u8 *)®_addr_be; + + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = reg_be_p; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = val_len; + msgs[1].buf = &data_be_p[4 - val_len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) { + dev_err(&client->dev, + "%s: reading register 0x%04x from 0x%02x failed\n", + __func__, reg_addr, client->addr); + return -EIO; + } + + *reg_val = be32_to_cpu(data_be); + +#if 0 + dev_info(&client->dev, "i2c addr(0x%02x) read: 0x%04x = 0x%08x (%d)\n", + client->addr, reg_addr, *reg_val, val_len); +#endif + + return 0; +} + +static int __maybe_unused ox03c10_i2c_write_array(struct i2c_client *client, + const struct i2c_regval *regs) +{ + u32 i = 0, delay_us = 0; + int ret = 0; + + for (i = 0; (ret == 0) && (regs[i].reg_addr != I2C_REG_NULL); i++) { + if (regs[i].reg_addr != I2C_REG_DELAY) { + ret = ox03c10_i2c_write_reg(client, regs[i].reg_addr, + OX03C10_REG_VALUE_08BIT, regs[i].reg_val); + } else { + if (regs[i].reg_val != 0) { + dev_info(&client->dev, "delay %d ms\n", regs[i].reg_val); + + delay_us = regs[i].reg_val * 1000; + usleep_range(delay_us, delay_us + 100); + } + } + } + + return ret; +} + +static const struct ox03c10_mode *ox03c10_find_mode(int hdr_mode, int hdr_operating_mode) +{ + unsigned int i = 0, cur_best_fit = 0; + + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (supported_modes[i].hdr_mode == hdr_mode) { + if (hdr_mode == NO_HDR) { // NO_HDR Mode + cur_best_fit = i; + break; + } else { // HDR_COMPR Mode + if (supported_modes[i].hdr_operating_mode == hdr_operating_mode) { + cur_best_fit = i; + break; + } + } + } + } + + return &supported_modes[cur_best_fit]; +} + +static int __ox03c10_power_on(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + int ret = 0; + + dev_info(dev, "ox03c10 device power on\n"); + + ret = regulator_enable(ox03c10->poc_regulator); + if (ret < 0) { + dev_err(dev, "Unable to turn PoC regulator on\n"); + return ret; + } + + return 0; +} + +static void __ox03c10_power_off(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + int ret = 0; + + dev_info(dev, "ox03c10 device power off\n"); + + ret = regulator_disable(ox03c10->poc_regulator); + if (ret < 0) + dev_warn(dev, "Unable to turn PoC regulator off\n"); +} + +static int ox03c10_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + int ret = 0; + + ret = __ox03c10_power_on(ox03c10); + + return ret; +} + +static int ox03c10_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + __ox03c10_power_off(ox03c10); + + return 0; +} + +static const struct dev_pm_ops ox03c10_pm_ops = { + SET_RUNTIME_PM_OPS( + ox03c10_runtime_suspend, ox03c10_runtime_resume, NULL) +}; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static int ox03c10_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->state, 0); +#else + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, 0); +#endif + const struct ox03c10_mode *def_mode = &ox03c10->supported_modes[0]; + + mutex_lock(&ox03c10->mutex); + + /* Initialize try_fmt */ + try_fmt->width = def_mode->width; + try_fmt->height = def_mode->height; + try_fmt->code = def_mode->bus_fmt; + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&ox03c10->mutex); + /* No crop or compose */ + + return 0; +} +#endif + +static int ox03c10_s_power(struct v4l2_subdev *sd, int on) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + struct i2c_client *client = ox03c10->client; + int ret = 0; + + mutex_lock(&ox03c10->mutex); + + /* If the power state is not modified - no work to do. */ + if (ox03c10->power_on == !!on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ox03c10->power_on = true; + } else { + pm_runtime_put(&client->dev); + ox03c10->power_on = false; + } + +unlock_and_return: + mutex_unlock(&ox03c10->mutex); + + return ret; +} + +static void ox03c10_get_module_inf(struct ox03c10 *ox03c10, + struct rkmodule_inf *inf) +{ + memset(inf, 0, sizeof(*inf)); + strscpy(inf->base.sensor, OX03C10_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, ox03c10->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, ox03c10->len_name, sizeof(inf->base.lens)); +} + +static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, + struct preisp_hdrae_exp_s *ae) +{ + int ret = 0; + u32 l_dgain = 1024; + u32 m_dgain = 1024; + u32 s_dgain = 1024; + u32 l_exp = ae->long_exp_reg; + u32 m_exp = ae->middle_exp_reg; + u32 s_exp = ae->short_exp_reg; + u32 l_again = ae->long_gain_reg; + u32 m_again = ae->middle_gain_reg; + u32 s_again = ae->short_gain_reg; + + if (!ox03c10->has_init_exp && !ox03c10->streaming) { + ox03c10->init_hdrae_exp = *ae; + ox03c10->has_init_exp = true; + dev_dbg(&ox03c10->client->dev, "ox03c10 don't stream, record exp for hdr!\n"); + return ret; + } + + dev_dbg(&ox03c10->client->dev, + "rev exp req: L_exp: 0x%x, 0x%x, M_exp: 0x%x, 0x%x S_exp: 0x%x, 0x%x\n", + l_exp, l_again, m_exp, m_again, s_exp, s_again); + + if (l_exp < 4) + l_exp = 4; + if (s_exp < 1) + s_exp = 1; + if (s_exp > 35 && ox03c10->cur_mode->exp_mode == EXP_HDR3_DCG_VS) + s_exp = 35; + + if (l_again < 16) { + l_again = 16; + } else if (l_again <= 31) { + } else if (l_again <= 47) { + l_again = (l_again - 16) << 1; + } else if (l_again <= 63) { + l_again = (l_again - 32) << 2; + } else if (l_again <= 95) { + l_again = (l_again - 48) << 3; + } else if (l_again >= 248) { + l_dgain = div_u64(l_again * 1024, 248); + l_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set l_gain val:0x%x not support", + __func__, l_again); + return -EINVAL; + } + + if (m_again < 16) { + m_again = 16; + } else if (m_again <= 31) { + } else if (m_again <= 47) { + m_again = (m_again - 16) << 1; + } else if (m_again <= 63) { + m_again = (m_again - 32) << 2; + } else if (m_again <= 95) { + m_again = (m_again - 48) << 3; + } else if (m_again >= 248) { + m_dgain = div_u64(m_again * 1024, 248); + m_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set m_gain val:0x%x not support", + __func__, m_again); + return -EINVAL; + } + + if (s_again < 16) { + s_again = 16; + } else if (s_again <= 31) { + } else if (s_again <= 47) { + s_again = (s_again - 16) << 1; + } else if (s_again <= 63) { + s_again = (s_again - 32) << 2; + } else if (s_again <= 95) { + s_again = (s_again - 48) << 3; + } else if (s_again >= 248) { + s_dgain = div_u64(s_again * 1024, 248); + s_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set s_gain val:0x%x not support", + __func__, s_again); + return -EINVAL; + } + + dev_dbg(&ox03c10->client->dev, + "l_again 0x%x l_dgain 0x%x, m_again 0x%x m_dgain 0x%x, s_again 0x%x s_dgain 0x%x\n", + l_again, l_dgain, m_again, m_dgain, s_again, s_dgain); + + if (ox03c10->streaming) + ret |= ox03c10_i2c_write_reg(ox03c10->client, OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_START_DATA); + // dcg exposure + ret |= ox03c10_i2c_write_reg(ox03c10->client, OX03C10_REG_EXPOSURE_DCG_H, + OX03C10_REG_VALUE_16BIT, + l_exp); + + // hcg real gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_HCG_H, + OX03C10_REG_VALUE_08BIT, + (l_again >> 4) & 0x0f); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_HCG_L, + OX03C10_REG_VALUE_08BIT, + (l_again << 4) & 0xf0); + // hcg digital gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_HCG_H, + OX03C10_REG_VALUE_08BIT, + (l_dgain >> 10) & 0xf); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_HCG_M, + OX03C10_REG_VALUE_08BIT, + (l_dgain >> 2) & 0xff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_HCG_L, + OX03C10_REG_VALUE_08BIT, + (l_dgain << 6) & 0xc0); + + // lcg real gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_LCG_H, + OX03C10_REG_VALUE_08BIT, + (m_again >> 4) & 0x0f); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_LCG_L, + OX03C10_REG_VALUE_08BIT, + (m_again << 4) & 0xf0); + // lcg digital gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_LCG_H, + OX03C10_REG_VALUE_08BIT, + (m_dgain >> 10) & 0xf); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_LCG_M, + OX03C10_REG_VALUE_08BIT, + (m_dgain >> 2) & 0xff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_LCG_L, + OX03C10_REG_VALUE_08BIT, + (m_dgain << 6) & 0xc0); + + if (ox03c10->cur_mode->exp_mode == EXP_HDR3_DCG_VS) { + // vs exposure + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_EXPOSURE_VS_H, + OX03C10_REG_VALUE_16BIT, + s_exp); + + // vs real gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_VS_H, + OX03C10_REG_VALUE_08BIT, + (s_again >> 4) & 0x0f); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_VS_L, + OX03C10_REG_VALUE_08BIT, + (s_again << 4) & 0xf0); + + // vs digital gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_VS_H, + OX03C10_REG_VALUE_08BIT, + (s_dgain >> 10) & 0xf); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_VS_M, + OX03C10_REG_VALUE_08BIT, + (s_dgain >> 2) & 0xff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_VS_L, + OX03C10_REG_VALUE_08BIT, + (s_dgain << 6) & 0xc0); + } else if (ox03c10->cur_mode->exp_mode == EXP_HDR3_DCG_SPD) { + // spd exposure + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_EXPOSURE_SPD_H, + OX03C10_REG_VALUE_16BIT, + s_exp); + + // spd real gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_SPD_H, + OX03C10_REG_VALUE_08BIT, + (s_again >> 4) & 0x0f); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_AGAIN_SPD_L, + OX03C10_REG_VALUE_08BIT, + (s_again << 4) & 0xf0); + + // spd digital gain + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_SPD_H, + OX03C10_REG_VALUE_08BIT, + (s_dgain >> 10) & 0xf); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_SPD_M, + OX03C10_REG_VALUE_08BIT, + (s_dgain >> 2) & 0xff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_DGAIN_SPD_L, + OX03C10_REG_VALUE_08BIT, + (s_dgain << 6) & 0xc0); + } + + if (ox03c10->streaming) { + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_END_DATA); + ret |= ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_LAUNCH); + } + + return ret; +} + +static int ox03c10_set_wb_gain(struct ox03c10 *ox03c10, + struct rkmodule_wb_gain_group *wb_gain_group) +{ + struct rkmodule_wb_gain wb_gain; + u16 reg_bgain, reg_gbgain, reg_grgain, reg_rgain; + int i = 0; + int ret = 0; +#ifdef DEBUG + u32 bgain, gbgain, grgain, rgain; +#endif + + if (!ox03c10->has_init_wbgain && !ox03c10->streaming) { + ox03c10->init_wbgain = *wb_gain_group; + ox03c10->has_init_wbgain = true; + dev_info(&ox03c10->client->dev, "ox03c10 don't stream, record wbgain!\n"); + return ret; + } + + for (i = 0; i < wb_gain_group->group_num; i++) { + switch (wb_gain_group->wb_gain_type[i]) { + case RKMODULE_HCG_WB_GAIN: + reg_bgain = OX03C10_REG_HCG_B_GAIN; + reg_gbgain = OX03C10_REG_HCG_GB_GAIN; + reg_grgain = OX03C10_REG_HCG_GR_GAIN; + reg_rgain = OX03C10_REG_HCG_R_GAIN; + break; + case RKMODULE_LCG_WB_GAIN: + reg_bgain = OX03C10_REG_LCG_B_GAIN; + reg_gbgain = OX03C10_REG_LCG_GB_GAIN; + reg_grgain = OX03C10_REG_LCG_GR_GAIN; + reg_rgain = OX03C10_REG_LCG_R_GAIN; + break; + case RKMODULE_SPD_WB_GAIN: + reg_bgain = OX03C10_REG_SPD_B_GAIN; + reg_gbgain = OX03C10_REG_SPD_GB_GAIN; + reg_grgain = OX03C10_REG_SPD_GR_GAIN; + reg_rgain = OX03C10_REG_SPD_R_GAIN; + break; + case RKMODULE_VS_WB_GAIN: + reg_bgain = OX03C10_REG_VS_B_GAIN; + reg_gbgain = OX03C10_REG_VS_GB_GAIN; + reg_grgain = OX03C10_REG_VS_GR_GAIN; + reg_rgain = OX03C10_REG_VS_R_GAIN; + break; + default: + return -EINVAL; + } + wb_gain = wb_gain_group->wb_gain[i]; + ret = ox03c10_i2c_write_reg(ox03c10->client, reg_bgain, + OX03C10_REG_VALUE_16BIT, wb_gain.b_gain & 0xffff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, reg_grgain, + OX03C10_REG_VALUE_16BIT, wb_gain.gr_gain & 0xffff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, reg_gbgain, + OX03C10_REG_VALUE_16BIT, wb_gain.gb_gain & 0xffff); + ret |= ox03c10_i2c_write_reg(ox03c10->client, reg_rgain, + OX03C10_REG_VALUE_16BIT, wb_gain.r_gain & 0xffff); + dev_info(&ox03c10->client->dev, + "write wb gain, type:%d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n", + wb_gain_group->wb_gain_type[i], + wb_gain.b_gain, wb_gain.gb_gain, + wb_gain.gr_gain, wb_gain.r_gain); +#ifdef DEBUG + ret |= ox03c10_i2c_read_reg(ox03c10->client, reg_bgain, + OX03C10_REG_VALUE_16BIT, &bgain); + ret |= ox03c10_i2c_read_reg(ox03c10->client, reg_gbgain, + OX03C10_REG_VALUE_16BIT, &gbgain); + ret |= ox03c10_i2c_read_reg(ox03c10->client, reg_grgain, + OX03C10_REG_VALUE_16BIT, &grgain); + ret |= ox03c10_i2c_read_reg(ox03c10->client, reg_rgain, + OX03C10_REG_VALUE_16BIT, &rgain); + dev_info(&ox03c10->client->dev, + "read wb gain, type %d, b:0x%x, gb:0x%x, gr:0x%x, r:0x%x\n", + wb_gain_group->wb_gain_type[i], bgain, gbgain, grgain, rgain); +#endif + } + + return ret; +} + +static int ox03c10_set_blc(struct ox03c10 *ox03c10, + struct rkmodule_blc_group *blc_group) +{ + u32 reg_blc = 0; + u32 blc_val = 0; + int i = 0; + int ret = 0; + + for (i = 0; i < blc_group->group_num; i++) { + switch (blc_group->blc_type[i]) { + case RKMODULE_HCG_BLC: + reg_blc = OX03C10_REG_HCG_BLC; + break; + case RKMODULE_LCG_BLC: + reg_blc = OX03C10_REG_LCG_BLC; + break; + case RKMODULE_SPD_BLC: + reg_blc = OX03C10_REG_SPD_BLC; + break; + case RKMODULE_VS_BLC: + reg_blc = OX03C10_REG_VS_BLC; + break; + default: + return -EINVAL; + } + blc_val = blc_group->blc[i]; + ret = ox03c10_i2c_write_reg(ox03c10->client, reg_blc, + OX03C10_REG_VALUE_16BIT, blc_val & 0x3ff); + dev_info(&ox03c10->client->dev, + "write blc, type:%d, blc_val:0x%x\n", + blc_group->blc_type[i], + blc_val); +#ifdef DEBUG + ret |= ox03c10_i2c_read_reg(ox03c10->client, reg_blc, + OX03C10_REG_VALUE_16BIT, &blc_val); + dev_info(&ox03c10->client->dev, + "read blc, type %d, blc_val:0x%x\n", + blc_group->blc_type[i], blc_val); +#endif + } + + return ret; +} + +static int ox03c10_get_channel_info(struct ox03c10 *ox03c10, struct rkmodule_channel_info *ch_info) +{ + if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX) + return -EINVAL; + + ch_info->vc = ox03c10->cur_mode->vc[ch_info->index]; + ch_info->width = ox03c10->cur_mode->width; + ch_info->height = ox03c10->cur_mode->height; + ch_info->bus_fmt = ox03c10->cur_mode->bus_fmt; + if (ox03c10->cur_mode->bus_fmt == MEDIA_BUS_FMT_SBGGR16_1X16) { + ch_info->data_type = 0x2a; + ch_info->data_bit = 16; + } + + return 0; +} + +static int ox03c10_select_exp_mode(struct ox03c10 *ox03c10, u32 exp_mode) +{ + int ret = -EINVAL; + u32 i, h, w, hdr_mode; + + w = ox03c10->cur_mode->width; + h = ox03c10->cur_mode->height; + hdr_mode = ox03c10->cur_mode->hdr_mode; + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (w == supported_modes[i].width && + h == supported_modes[i].height && + supported_modes[i].hdr_mode == hdr_mode && + supported_modes[i].exp_mode == exp_mode) { + ox03c10->cur_mode = &supported_modes[i]; + w = ox03c10->cur_mode->hts_def - ox03c10->cur_mode->width; + h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height; + __v4l2_ctrl_modify_range(ox03c10->hblank, w, w, 1, w); + __v4l2_ctrl_modify_range(ox03c10->vblank, h, + OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, h); + ret = 0; + break; + } + } + + return ret; +} + +static long ox03c10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + struct rkmodule_hdr_cfg *hdr = NULL; + struct rkmodule_dcg_ratio *dcg_ratio = NULL; + struct rkmodule_wb_gain_group *wb_gain_group = NULL; + struct rkmodule_blc_group *blc_group = NULL; + struct rkmodule_channel_info *ch_info = NULL; + u32 *exp_mode = NULL; + u32 i, h, w; + long ret = 0; + + dev_dbg(&ox03c10->client->dev, "ioctl cmd = 0x%08x\n", cmd); + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + ox03c10_get_module_inf(ox03c10, (struct rkmodule_inf *)arg); + break; + case RKMODULE_GET_HDR_CFG: + hdr = (struct rkmodule_hdr_cfg *)arg; + hdr->esp.mode = HDR_NORMAL_VC; + hdr->hdr_mode = ox03c10->cur_mode->hdr_mode; + if (hdr->hdr_mode == HDR_COMPR) + hdr->compr = *ox03c10->cur_mode->hdr_compr; + break; + case RKMODULE_SET_HDR_CFG: + hdr = (struct rkmodule_hdr_cfg *)arg; + if (ox03c10->cur_mode->hdr_mode == HDR_COMPR) + hdr->hdr_mode = ox03c10->cur_mode->hdr_mode; + w = ox03c10->cur_mode->width; + h = ox03c10->cur_mode->height; + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (w == supported_modes[i].width && + h == supported_modes[i].height && + supported_modes[i].hdr_mode == hdr->hdr_mode) { + ox03c10->cur_mode = &supported_modes[i]; + break; + } + } + if (i == ARRAY_SIZE(supported_modes)) { + dev_err(&ox03c10->client->dev, + "not find hdr mode:%d %dx%d config\n", + hdr->hdr_mode, w, h); + ret = -EINVAL; + } else { + w = ox03c10->cur_mode->hts_def - ox03c10->cur_mode->width; + h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height; + __v4l2_ctrl_modify_range(ox03c10->hblank, w, w, 1, w); + __v4l2_ctrl_modify_range(ox03c10->vblank, h, + OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, h); + } + break; + case PREISP_CMD_SET_HDRAE_EXP: + return ox03c10_set_hdrae(ox03c10, arg); + case RKMODULE_GET_DCG_RATIO: + dcg_ratio = (struct rkmodule_dcg_ratio *)arg; + *dcg_ratio = ox03c10->dcg_ratio; + break; + case RKMODULE_GET_SPD_RATIO: + dcg_ratio = (struct rkmodule_dcg_ratio *)arg; + *dcg_ratio = ox03c10->spd_ratio; + break; + case RKMODULE_SET_WB_GAIN: + wb_gain_group = (struct rkmodule_wb_gain_group *)arg; + ret = ox03c10_set_wb_gain(ox03c10, wb_gain_group); + break; + case RKMODULE_SET_BLC: + blc_group = (struct rkmodule_blc_group *)arg; + ret = ox03c10_set_blc(ox03c10, blc_group); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = (struct rkmodule_channel_info *)arg; + ret = ox03c10_get_channel_info(ox03c10, ch_info); + break; + case RKMODULE_GET_EXP_MODE: + exp_mode = (u32 *)arg; + *exp_mode = ox03c10->cur_mode->exp_mode; + break; + case RKMODULE_SET_EXP_MODE: + ret = ox03c10_select_exp_mode(ox03c10, *(u32 *)arg); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long ox03c10_compat_ioctl32(struct v4l2_subdev *sd, unsigned int cmd, + unsigned long arg) +{ + void __user *up = compat_ptr(arg); + struct rkmodule_inf *inf = NULL; + struct rkmodule_awb_cfg *cfg = NULL; + struct rkmodule_hdr_cfg *hdr = NULL; + struct preisp_hdrae_exp_s *hdrae = NULL; + struct rkmodule_dcg_ratio *dcg_ratio = NULL; + struct rkmodule_wb_gain_group *wb_gain_group = NULL; + struct rkmodule_blc_group *blc_group = NULL; + struct rkmodule_channel_info *ch_info = NULL; + u32 exp_mode = 0; + long ret = 0; + + switch (cmd) { + case RKMODULE_GET_MODULE_INFO: + inf = kzalloc(sizeof(*inf), GFP_KERNEL); + if (!inf) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, inf); + if (!ret) { + if (copy_to_user(up, inf, sizeof(*inf))) { + kfree(inf); + return -EFAULT; + } + } + kfree(inf); + break; + case RKMODULE_AWB_CFG: + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + ret = -ENOMEM; + return ret; + } + + if (copy_from_user(cfg, up, sizeof(*cfg))) { + kfree(cfg); + return -EFAULT; + } + ret = ox03c10_ioctl(sd, cmd, cfg); + kfree(cfg); + break; + case RKMODULE_GET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, hdr); + if (!ret) { + if (copy_to_user(up, hdr, sizeof(*hdr))) { + kfree(hdr); + return -EFAULT; + } + } + kfree(hdr); + break; + case RKMODULE_SET_HDR_CFG: + hdr = kzalloc(sizeof(*hdr), GFP_KERNEL); + if (!hdr) { + ret = -ENOMEM; + return ret; + } + + if (copy_from_user(hdr, up, sizeof(*hdr))) { + kfree(hdr); + return -EFAULT; + } + ret = ox03c10_ioctl(sd, cmd, hdr); + kfree(hdr); + break; + case PREISP_CMD_SET_HDRAE_EXP: + hdrae = kzalloc(sizeof(*hdrae), GFP_KERNEL); + if (!hdrae) { + ret = -ENOMEM; + return ret; + } + + if (copy_from_user(hdrae, up, sizeof(*hdrae))) { + kfree(hdrae); + return -EFAULT; + } + ret = ox03c10_ioctl(sd, cmd, hdrae); + kfree(hdrae); + break; + case RKMODULE_GET_DCG_RATIO: + dcg_ratio = kzalloc(sizeof(*dcg_ratio), GFP_KERNEL); + if (!dcg_ratio) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, dcg_ratio); + if (!ret) { + ret = copy_to_user(up, dcg_ratio, sizeof(*dcg_ratio)); + if (ret) + return -EFAULT; + } + kfree(dcg_ratio); + break; + case RKMODULE_GET_SPD_RATIO: + dcg_ratio = kzalloc(sizeof(*dcg_ratio), GFP_KERNEL); + if (!dcg_ratio) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, dcg_ratio); + if (!ret) { + ret = copy_to_user(up, dcg_ratio, sizeof(*dcg_ratio)); + if (ret) + return -EFAULT; + } + kfree(dcg_ratio); + break; + case RKMODULE_SET_WB_GAIN: + wb_gain_group = kzalloc(sizeof(*wb_gain_group), GFP_KERNEL); + if (!wb_gain_group) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, wb_gain_group); + if (!ret) { + ret = copy_to_user(up, wb_gain_group, sizeof(*wb_gain_group)); + if (ret) + return -EFAULT; + } + kfree(wb_gain_group); + break; + case RKMODULE_SET_BLC: + blc_group = kzalloc(sizeof(*blc_group), GFP_KERNEL); + if (!blc_group) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, blc_group); + if (!ret) { + ret = copy_to_user(up, blc_group, sizeof(*blc_group)); + if (ret) + return -EFAULT; + } + kfree(blc_group); + break; + case RKMODULE_GET_CHANNEL_INFO: + ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL); + if (!ch_info) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, ch_info); + if (!ret) { + ret = copy_to_user(up, ch_info, sizeof(*ch_info)); + if (ret) + ret = -EFAULT; + } + kfree(ch_info); + break; + case RKMODULE_GET_EXP_MODE: + ret = ox03c10_ioctl(sd, cmd, &exp_mode); + if (!ret) { + ret = copy_to_user(up, &exp_mode, sizeof(exp_mode)); + if (ret) + return -EFAULT; + } + break; + case RKMODULE_SET_EXP_MODE: + if (copy_from_user(&exp_mode, up, sizeof(u32))) + return -EFAULT; + ret = ox03c10_ioctl(sd, cmd, &exp_mode); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} +#endif /* CONFIG_COMPAT */ + +static int ox03c10_check_sensor_id(struct ox03c10 *ox03c10) +{ + struct i2c_client *client = ox03c10->client; + struct device *dev = &client->dev; + u32 sensor_id = 0; + int ret = 0, loop = 0; + + for (loop = 0; loop < 3; loop++) { + if (loop != 0) { + dev_info(dev, "check sensor id retry (%d)", loop); + msleep(10); + } + + ret = ox03c10_i2c_read_reg(client, OX03C10_REG_CHIP_ID, + OX03C10_REG_VALUE_16BIT, &sensor_id); + if (ret == 0) { + if (sensor_id != OX03C10_CHIP_ID) { + dev_err(dev, "Unexpected sensor id(%06x)\n", sensor_id); + return -ENODEV; + } else { + dev_info(dev, "Detected OV%06x sensor\n", OX03C10_CHIP_ID); + return 0; + } + } + } + + dev_err(dev, "Check sensor id error, ret = %d\n", ret); + + return -ENODEV; +} + +/* Note: In the Serdes scheme, the function must run after start stream */ +static int ox03c10_get_dcg_and_spd_ratio(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + u32 val = 0; + int ret = 0; + + ox03c10->dcg_ratio.integer = 0; + ret |= ox03c10_i2c_read_reg(ox03c10->client, 0x7057, + OX03C10_REG_VALUE_24BIT, &val); + ox03c10->dcg_ratio.decimal = val & 0x1ffff; + ret |= ox03c10_i2c_read_reg(ox03c10->client, 0x705b, + OX03C10_REG_VALUE_24BIT, &val); + ox03c10->dcg_ratio.div_coeff = val & 0x1ffff; + if (ret != 0 || val == 0) + dev_err(dev, "get dcg ratio fail, ret %d, dcg ratio %d, %d\n", + ret, ox03c10->dcg_ratio.integer, ox03c10->dcg_ratio.decimal); + else + dev_info(dev, "get dcg ratio reg val integer %d, dec 0x%x, div 0x%x\n", + ox03c10->dcg_ratio.integer, ox03c10->dcg_ratio.decimal, ox03c10->dcg_ratio.div_coeff); + + ox03c10->spd_ratio.integer = 0; + ox03c10->spd_ratio.decimal = val & 0x1ffff; + ret |= ox03c10_i2c_read_reg(ox03c10->client, 0x705f, + OX03C10_REG_VALUE_24BIT, &val); + ox03c10->spd_ratio.div_coeff = val & 0x1ffff; + if (ret != 0 || val == 0) + dev_err(dev, "get spd ratio fail, ret %d, spd ratio %d, %d\n", + ret, ox03c10->spd_ratio.integer, ox03c10->spd_ratio.decimal); + else + dev_info(dev, "get spd ratio reg val integer %d, dec 0x%x div 0x%x\n", + ox03c10->spd_ratio.integer, ox03c10->spd_ratio.decimal, ox03c10->spd_ratio.div_coeff); + + return ret; +} + +static int __ox03c10_start_stream(struct ox03c10 *ox03c10) +{ + maxim_remote_ser_t *remote_ser = ox03c10->remote_ser; + struct i2c_client *client = ox03c10->client; + struct device *dev = &client->dev; + int ret = 0; + + if (remote_ser == NULL) { + dev_err(dev, "%s: remote_ser error\n", __func__); + return -EINVAL; + } + + if (remote_ser->ser_ops == NULL) { + dev_err(dev, "%s: remote_ser ser_ops error\n", __func__); + return -EINVAL; + } + + ret = remote_ser->ser_ops->ser_module_init(remote_ser); + if (ret) { + dev_err(dev, "%s: remote_ser module_init error\n", __func__); + return ret; + } + + ret = ox03c10_check_sensor_id(ox03c10); + if (ret) { + dev_err(dev, "%s: ox03c10 check sensor id error\n", __func__); + return ret; + } + + ret = ox03c10_i2c_write_array(client, ox03c10->cur_mode->reg_list); + if (ret) { + dev_err(dev, "%s: ox03c10 reg_list write array error\n", __func__); + return ret; + } + + if (ox03c10->cur_mode->hdr_mode == NO_HDR) { + ret = ox03c10_i2c_write_array(client, ox03c10->cur_mode->linear_reg_list); + if (ret) { + dev_err(dev, "%s: ox03c10 linear_reg_list write array error\n", __func__); + return ret; + } + } + + /* In case these controls are set before streaming */ + ret = __v4l2_ctrl_handler_setup(&ox03c10->ctrl_handler); + if (ret) + return ret; + if (ox03c10->has_init_exp && ox03c10->cur_mode->hdr_mode != NO_HDR) { + ret = ox03c10_ioctl(&ox03c10->subdev, + PREISP_CMD_SET_HDRAE_EXP, + &ox03c10->init_hdrae_exp); + if (ret) { + dev_err(&ox03c10->client->dev, + "init exp fail in hdr mode\n"); + return ret; + } + } + + if (ox03c10->has_init_wbgain) { + ret = ox03c10_ioctl(&ox03c10->subdev, + RKMODULE_SET_WB_GAIN, + &ox03c10->init_wbgain); + if (ret) { + dev_err(&ox03c10->client->dev, + "init wbgain fail\n"); + return ret; + } + } + + /* streaming control register */ + ret = ox03c10_i2c_write_reg(client, + OX03C10_REG_CTRL_MODE, + OX03C10_REG_VALUE_08BIT, + OX03C10_MODE_STREAMING); + if (ret) { + dev_err(dev, "%s: ox03c10 start stream error\n", __func__); + return ret; + } + + ret = remote_ser->ser_ops->ser_pclk_detect(remote_ser); + if (ret) { + dev_err(dev, "%s: remote_ser pclk_detect error\n", __func__); + return ret; + } + + /* note: get dcg and spd ratio after start stream */ + ret = ox03c10_get_dcg_and_spd_ratio(ox03c10); + if (ret) + dev_warn(dev, "get dcg and spd ratio failed\n"); + + return 0; +} + +static int __ox03c10_stop_stream(struct ox03c10 *ox03c10) +{ + maxim_remote_ser_t *remote_ser = ox03c10->remote_ser; + struct i2c_client *client = ox03c10->client; + struct device *dev = &client->dev; + int ret = 0; + + ox03c10->has_init_exp = false; + ox03c10->has_init_wbgain = false; + + /* streaming control register */ + ret = ox03c10_i2c_write_reg(client, + OX03C10_REG_CTRL_MODE, + OX03C10_REG_VALUE_08BIT, + OX03C10_MODE_SW_STANDBY); + if (ret) { + dev_err(dev, "%s: ox03c10 stop stream error\n", __func__); + return ret; + } + + if (remote_ser == NULL) { + dev_err(dev, "%s: remote_ser error\n", __func__); + return -EINVAL; + } + + if (remote_ser->ser_ops == NULL) { + dev_err(dev, "%s: remote_ser ser_ops error\n", __func__); + return -EINVAL; + } + + ret = remote_ser->ser_ops->ser_module_deinit(remote_ser); + if (ret) { + dev_err(dev, "%s: remote_ser module_deinit error\n", __func__); + return ret; + } + + return 0; +} + +static int ox03c10_s_stream(struct v4l2_subdev *sd, int on) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + struct i2c_client *client = ox03c10->client; + int ret = 0; + + dev_info(&client->dev, "%s: on = %d\n", __func__, on); + + mutex_lock(&ox03c10->mutex); + on = !!on; + if (on == ox03c10->streaming) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = __ox03c10_start_stream(ox03c10); + if (ret) { + v4l2_err(sd, "start stream failed while write regs\n"); + pm_runtime_put(&client->dev); + goto unlock_and_return; + } + } else { + __ox03c10_stop_stream(ox03c10); + pm_runtime_put(&client->dev); + } + + ox03c10->streaming = on; + +unlock_and_return: + mutex_unlock(&ox03c10->mutex); + + return ret; +} + +static int ox03c10_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + const struct ox03c10_mode *mode = ox03c10->cur_mode; + + fi->interval = mode->max_fps; + + return 0; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +#else +static int ox03c10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + if (code->index != 0) + return -EINVAL; + code->code = ox03c10->cur_mode->bus_fmt; + + return 0; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +#else +static int ox03c10_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + if (fse->index >= ox03c10->cfg_modes_num) + return -EINVAL; + + if (fse->code != ox03c10->supported_modes[fse->index].bus_fmt) + return -EINVAL; + + fse->min_width = ox03c10->supported_modes[fse->index].width; + fse->max_width = ox03c10->supported_modes[fse->index].width; + fse->max_height = ox03c10->supported_modes[fse->index].height; + fse->min_height = ox03c10->supported_modes[fse->index].height; + + return 0; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_interval_enum *fie) +#else +static int ox03c10_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + if (fie->index >= ox03c10->cfg_modes_num) + return -EINVAL; + + fie->code = ox03c10->supported_modes[fie->index].bus_fmt; + fie->width = ox03c10->supported_modes[fie->index].width; + fie->height = ox03c10->supported_modes[fie->index].height; + fie->interval = ox03c10->supported_modes[fie->index].max_fps; + + return 0; +} + +static int ox03c10_get_reso_dist(const struct ox03c10_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct ox03c10_mode * +ox03c10_find_best_fit(struct ox03c10 *ox03c10, struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < ox03c10->cfg_modes_num; i++) { + dist = ox03c10_get_reso_dist(&ox03c10->supported_modes[i], framefmt); + if ((cur_best_fit_dist == -1 || dist < cur_best_fit_dist) && + (ox03c10->supported_modes[i].bus_fmt == framefmt->code)) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } + } + + return &ox03c10->supported_modes[cur_best_fit]; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +#else +static int ox03c10_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + struct device *dev = &ox03c10->client->dev; + const struct ox03c10_mode *mode; + u64 link_freq = 0, pixel_rate = 0; + s64 h_blank, vblank_def; + u8 data_lanes = ox03c10->bus_cfg.bus.mipi_csi2.num_data_lanes; + + mutex_lock(&ox03c10->mutex); + + mode = ox03c10_find_best_fit(ox03c10, fmt); + fmt->format.code = mode->bus_fmt; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; + #else + *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; + #endif +#else + mutex_unlock(&ox03c10->mutex); + return -ENOTTY; +#endif + } else { + ox03c10->cur_mode = mode; + + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(ox03c10->hblank, + h_blank, h_blank, 1, h_blank); + + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(ox03c10->vblank, + vblank_def, OX03C10_VTS_MAX - mode->height, 1, vblank_def); + + __v4l2_ctrl_s_ctrl(ox03c10->link_freq, mode->link_freq_idx); + + /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ + link_freq = link_freq_menu_items[mode->link_freq_idx]; + pixel_rate = (u32)link_freq / mode->bpp * 2 * data_lanes; + __v4l2_ctrl_s_ctrl_int64(ox03c10->pixel_rate, pixel_rate); + + dev_info(dev, "mipi_freq_idx = %d, mipi_link_freq = %lld\n", + mode->link_freq_idx, link_freq); + dev_info(dev, "pixel_rate = %lld, bpp = %d\n", + pixel_rate, mode->bpp); + } + + dev_info(dev, "Set format done!(cur_mode: %d)\n", mode->hdr_mode); + + mutex_unlock(&ox03c10->mutex); + + return 0; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +#else +static int ox03c10_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + const struct ox03c10_mode *mode = ox03c10->cur_mode; + + mutex_lock(&ox03c10->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); + #else + fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + #endif +#else + mutex_unlock(&ox03c10->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = mode->bus_fmt; + fmt->format.field = V4L2_FIELD_NONE; + /* format info: width/height/data type/virctual channel */ + if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) + fmt->reserved[0] = mode->vc[fmt->pad]; + else + fmt->reserved[0] = mode->vc[PAD0]; + } + mutex_unlock(&ox03c10->mutex); + + return 0; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_selection *sel) +#else +static int ox03c10_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +#endif +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) { + sel->r.left = 0; + sel->r.width = ox03c10->cur_mode->width; + sel->r.top = 0; + sel->r.height = ox03c10->cur_mode->height; + return 0; + } + + return -EINVAL; +} + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE +static int ox03c10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_config *config) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2 = ox03c10->bus_cfg.bus.mipi_csi2; + + return 0; +} +#elif KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE +static int ox03c10_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_config *config) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + u32 val = 0; + u8 data_lanes = ox03c10->bus_cfg.bus.mipi_csi2.num_data_lanes; + + val |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + val |= (1 << (data_lanes - 1)); + + val |= V4L2_MBUS_CSI2_CHANNEL_0; + + config->type = V4L2_MBUS_CSI2_DPHY; + config->flags = val; + + return 0; +} +#else +static int ox03c10_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *config) +{ + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + u32 val = 0; + u8 data_lanes = ox03c10->bus_cfg.bus.mipi_csi2.num_data_lanes; + + val |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + val |= (1 << (data_lanes - 1)); + + val |= V4L2_MBUS_CSI2_CHANNEL_0; + + config->type = V4L2_MBUS_CSI2; + config->flags = val; + + return 0; +} +#endif /* LINUX_VERSION_CODE */ + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API +static const struct v4l2_subdev_internal_ops ox03c10_internal_ops = { + .open = ox03c10_open, +}; +#endif + +static const struct v4l2_subdev_core_ops ox03c10_core_ops = { + .s_power = ox03c10_s_power, + .ioctl = ox03c10_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = ox03c10_compat_ioctl32, +#endif +}; + +static const struct v4l2_subdev_video_ops ox03c10_video_ops = { + .s_stream = ox03c10_s_stream, + .g_frame_interval = ox03c10_g_frame_interval, +#if KERNEL_VERSION(5, 10, 0) > LINUX_VERSION_CODE + .g_mbus_config = ox03c10_g_mbus_config, +#endif +}; + +static const struct v4l2_subdev_pad_ops ox03c10_pad_ops = { + .enum_mbus_code = ox03c10_enum_mbus_code, + .enum_frame_size = ox03c10_enum_frame_sizes, + .enum_frame_interval = ox03c10_enum_frame_interval, + .get_fmt = ox03c10_get_fmt, + .set_fmt = ox03c10_set_fmt, + .get_selection = ox03c10_get_selection, +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE + .get_mbus_config = ox03c10_g_mbus_config, +#endif +}; + +static const struct v4l2_subdev_ops ox03c10_subdev_ops = { + .core = &ox03c10_core_ops, + .video = &ox03c10_video_ops, + .pad = &ox03c10_pad_ops, +}; + +static int ox03c10_enable_test_pattern(struct ox03c10 *ox03c10, u32 pattern) +{ + u32 val; + + if (pattern) + val = (pattern - 1) | OX03C10_TEST_PATTERN_ENABLE; + else + val = OX03C10_TEST_PATTERN_DISABLE; + + return ox03c10_i2c_write_reg(ox03c10->client, + OX03C10_REG_TEST_PATTERN, + OX03C10_REG_VALUE_08BIT, val); +} + +static int ox03c10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ox03c10 *ox03c10 = container_of(ctrl->handler, + struct ox03c10, ctrl_handler); + struct i2c_client *client = ox03c10->client; + s64 exposure_max = 0; + u16 exp_reg, again_reg, dgain_reg; + u32 again = 16, dgain = 1024; + u32 val = 0; + int ret = 0; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + exposure_max = (ox03c10->cur_mode->height + ctrl->val) / 2 - 12; + __v4l2_ctrl_modify_range(ox03c10->exposure, + ox03c10->exposure->minimum, exposure_max, + ox03c10->exposure->step, + ox03c10->exposure->default_value); + break; + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + // i2c can't be accessed before serdes link ok + if (maxim_remote_ser_is_inited(ox03c10->remote_ser) == false) { + dev_warn(&client->dev, "%s ctrl id = 0x%x before serializer init\n", + __func__, ctrl->id); + return 0; + } + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + if (ox03c10->cur_mode->hdr_mode != NO_HDR) + break; + + dev_info(&client->dev, "%s set exposure: val = 0x%x", __func__, ctrl->val); + + if (ox03c10->streaming) + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_START_DATA); + + // dcg exposure register + exp_reg = OX03C10_REG_EXPOSURE_DCG_H; + ret |= ox03c10_i2c_write_reg(client, + exp_reg, + OX03C10_REG_VALUE_16BIT, + ctrl->val); + + if (ox03c10->streaming) { + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_END_DATA); + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP_UPDATE_LAUNCH); + } + + break; + case V4L2_CID_ANALOGUE_GAIN: + if (ox03c10->cur_mode->hdr_mode != NO_HDR) + break; + /* + *[1, 1.9375, 16, 0, 1, 16, 31, + * 2, 3.875, 8, -16, 1, 32, 47, + * 4, 7.75, 4, -32, 1, 48, 63, + * 8, 15.5, 2,-48, 1, 64, 95, + * 15.5, 247.9375, 16, 0, 1, 248, 3967] + */ + // hcg real gain + if (ctrl->val < 16) { + again = 16; + } else if (ctrl->val <= 31) { + again = ctrl->val; + } else if (ctrl->val <= 47) { + again = (ctrl->val - 16) << 1; + } else if (ctrl->val <= 63) { + again = (ctrl->val - 32) << 2; + } else if (ctrl->val <= 95) { + again = (ctrl->val - 48) << 3; + } else if (ctrl->val >= 248) { + dgain = div_u64(ctrl->val * 1024, 248); + again = 248; + } else { + dev_err(&client->dev, "%s set gain val:0x%x not support", + __func__, ctrl->val); + break; + } + + if (ox03c10->streaming) + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP1_UPDATE_START_DATA); + + // lcg gain register + again_reg = OX03C10_REG_AGAIN_LCG_H; + dgain_reg = OX03C10_REG_DGAIN_LCG_H; + + ret |= ox03c10_i2c_write_reg(client, + again_reg, + OX03C10_REG_VALUE_16BIT, + (again << 4) & 0xff0); + ret |= ox03c10_i2c_write_reg(client, + dgain_reg, + OX03C10_REG_VALUE_24BIT, + (dgain << 6) & 0xfffc0); + + if (ox03c10->streaming) { + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP1_UPDATE_END_DATA); + ret |= ox03c10_i2c_write_reg(client, + OX03C10_GROUP_UPDATE_ADDRESS, + OX03C10_REG_VALUE_08BIT, + OX03C10_GROUP1_UPDATE_LAUNCH); + } + + dev_info(&client->dev, "%s set analog gain(ret = %d): val = 0x%x, again = 0x%x, dgain = 0x%x\n", + __func__, ret, ctrl->val, again, dgain); + break; + case V4L2_CID_VBLANK: + ret = ox03c10_i2c_write_reg(client, + OX03C10_REG_VTS, + OX03C10_REG_VALUE_16BIT, + (ctrl->val + ox03c10->cur_mode->height) / 2); + break; + case V4L2_CID_TEST_PATTERN: + ret = ox03c10_enable_test_pattern(ox03c10, ctrl->val); + break; + case V4L2_CID_HFLIP: + ret = ox03c10_i2c_read_reg(client, + OX03C10_VFLIP_REG, + OX03C10_REG_VALUE_08BIT, + &val); + if (ctrl->val) + val |= MIRROR_BIT_MASK; + else + val &= ~MIRROR_BIT_MASK; + ret |= ox03c10_i2c_write_reg(client, + OX03C10_VFLIP_REG, + OX03C10_REG_VALUE_08BIT, + val); + break; + case V4L2_CID_VFLIP: + ret = ox03c10_i2c_read_reg(client, + OX03C10_VFLIP_REG, + OX03C10_REG_VALUE_08BIT, + &val); + if (ctrl->val) + val |= FLIP_BIT_MASK; + else + val &= ~FLIP_BIT_MASK; + ret |= ox03c10_i2c_write_reg(client, + OX03C10_VFLIP_REG, + OX03C10_REG_VALUE_08BIT, + val); + break; + default: + dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", + __func__, ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ox03c10_ctrl_ops = { + .s_ctrl = ox03c10_set_ctrl, +}; + +static int ox03c10_initialize_controls(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + const struct ox03c10_mode *mode; + struct v4l2_ctrl_handler *handler; + u64 link_freq = 0, pixel_rate = 0; + s64 exposure_max = 0, vblank_def; + u32 h_blank; + u8 data_lanes; + + int ret = 0; + + handler = &ox03c10->ctrl_handler; + mode = ox03c10->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 9); + if (ret) + return ret; + + handler->lock = &ox03c10->mutex; + + /* ctrl handler: link freq */ + ox03c10->link_freq = v4l2_ctrl_new_int_menu(handler, NULL, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, 0, + link_freq_menu_items); + v4l2_ctrl_s_ctrl(ox03c10->link_freq, mode->link_freq_idx); + link_freq = link_freq_menu_items[mode->link_freq_idx]; + dev_info(dev, "mipi_freq_idx = %d, mipi_link_freq = %lld\n", + mode->link_freq_idx, link_freq); + + /* ctrl handler: pixel rate */ + /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ + data_lanes = ox03c10->bus_cfg.bus.mipi_csi2.num_data_lanes; + pixel_rate = (u32)link_freq / mode->bpp * 2 * data_lanes; + + ox03c10->pixel_rate = v4l2_ctrl_new_std(handler, NULL, + V4L2_CID_PIXEL_RATE, + 0, pixel_rate, 1, pixel_rate); + dev_info(dev, "pixel_rate = %lld, bpp = %d\n", pixel_rate, mode->bpp); + + /* ctrl handler: hblank */ + h_blank = mode->hts_def - mode->width; + ox03c10->hblank = v4l2_ctrl_new_std(handler, NULL, + V4L2_CID_HBLANK, + h_blank, h_blank, 1, h_blank); + if (ox03c10->hblank) + ox03c10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* ctrl handler: vblank */ + vblank_def = mode->vts_def - mode->height; + ox03c10->vblank = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, + V4L2_CID_VBLANK, vblank_def, + OX03C10_VTS_MAX, + 1, vblank_def); + + /* ctrl handler: exposure */ + exposure_max = mode->vts_def / 2 - 12; + dev_info(dev, "exposure_max = %lld\n", exposure_max); + ox03c10->exposure = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, + V4L2_CID_EXPOSURE, + OX03C10_EXPOSURE_HCG_MIN, exposure_max, + OX03C10_EXPOSURE_HCG_STEP, mode->exp_def); + + /* ctrl handler: test pattern */ + ox03c10->test_pattern = v4l2_ctrl_new_std_menu_items(handler, &ox03c10_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ox03c10_test_pattern_menu) - 1, + 0, 0, ox03c10_test_pattern_menu); + + /* ctrl handler: analogue gain */ + ox03c10->anal_gain = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, + OX03C10_GAIN_MIN, OX03C10_GAIN_MAX, + OX03C10_GAIN_STEP, OX03C10_GAIN_DEFAULT); + + /* ctrl handler: hflip */ + ox03c10->h_flip = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + /* ctrl handler: vflip */ + ox03c10->v_flip = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + if (handler->error) { + ret = handler->error; + dev_err(&ox03c10->client->dev, + "Failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + ox03c10->subdev.ctrl_handler = handler; + ox03c10->has_init_exp = false; + ox03c10->has_init_wbgain = false; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int ox03c10_parse_dt(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + struct device_node *of_node = dev->of_node; + u32 value = 0; + int ret = 0; + + dev_info(dev, "=== ox03c10 parse dt ===\n"); + + ret = of_property_read_u32(of_node, "cam-i2c-addr-def", &value); + if (ret == 0) { + dev_info(dev, "cam-i2c-addr-def property: 0x%x", value); + ox03c10->cam_i2c_addr_def = value; + } else { + ox03c10->cam_i2c_addr_def = OX03C10_I2C_ADDR_DEF; + } + + return 0; +} + +static int ox03c10_mipi_data_lanes_parse(struct ox03c10 *ox03c10) +{ + struct device *dev = &ox03c10->client->dev; + struct device_node *endpoint = NULL; + u8 mipi_data_lanes; + int ret = 0; + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!endpoint) { + dev_err(dev, "Failed to get endpoint\n"); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), + &ox03c10->bus_cfg); + if (ret) { + dev_err(dev, "Failed to get bus config\n"); + return -EINVAL; + } + mipi_data_lanes = ox03c10->bus_cfg.bus.mipi_csi2.num_data_lanes; + dev_info(dev, "mipi csi2 phy data lanes = %d\n", mipi_data_lanes); + + return 0; +} + +static int ox03c10_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device_node *node = dev->of_node; + struct ox03c10 *ox03c10 = NULL; + struct v4l2_subdev *sd = NULL; + maxim_remote_ser_t *remote_ser = NULL; + char facing[2]; + u32 hdr_mode = 0, hdr_operating_mode = 0; + int ret = 0; + + dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16, + (DRIVER_VERSION & 0xff00) >> 8, DRIVER_VERSION & 0x00ff); + + ox03c10 = devm_kzalloc(dev, sizeof(*ox03c10), GFP_KERNEL); + if (!ox03c10) { + dev_err(dev, "ox03c10 probe no memory error\n"); + return -ENOMEM; + } + + ox03c10->client = client; + ox03c10->cam_i2c_addr_map = client->addr; + + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, + &ox03c10->module_index); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, + &ox03c10->module_facing); + ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME, + &ox03c10->module_name); + ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, + &ox03c10->len_name); + if (ret) { + dev_err(dev, "could not get module information!\n"); + return -EINVAL; + } + + // poc regulator + ox03c10->poc_regulator = devm_regulator_get(dev, "poc"); + if (IS_ERR(ox03c10->poc_regulator)) { + if (PTR_ERR(ox03c10->poc_regulator) != -EPROBE_DEFER) + dev_err(dev, "Unable to get PoC regulator (%ld)\n", + PTR_ERR(ox03c10->poc_regulator)); + else + dev_err(dev, "Get PoC regulator deferred\n"); + + ret = PTR_ERR(ox03c10->poc_regulator); + + return ret; + } + + /* hdr mode */ + ret = of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); + if (ret) { + hdr_mode = NO_HDR; + dev_warn(dev, "Get hdr mode failed! no hdr default\n"); + } + + if (hdr_mode != NO_HDR) { + // HDR Operating Mode + ret = of_property_read_u32(node, OF_CAMERA_HDR_OPERATING_MODE, + &hdr_operating_mode); + if (ret) + hdr_operating_mode = OX03C10_HDR3_DCG_VS_12BIT; + if (hdr_operating_mode >= OX03C10_HDR_OPERATING_MODE_MAX) + hdr_operating_mode = OX03C10_HDR3_DCG_VS_12BIT; + dev_info(dev, "HDR_COMPR mode, hdr_operating_mode: %d\n", hdr_operating_mode); + } else { + dev_info(dev, "NO_HDR mode\n"); + hdr_operating_mode = OX03C10_HDR_OPERATING_MODE_MAX; + } + + ox03c10_mipi_data_lanes_parse(ox03c10); + ox03c10->supported_modes = supported_modes; + ox03c10->cfg_modes_num = ARRAY_SIZE(supported_modes); + ox03c10->cur_mode = ox03c10_find_mode(hdr_mode, hdr_operating_mode); + + mutex_init(&ox03c10->mutex); + + ret = __ox03c10_power_on(ox03c10); + if (ret) + goto err_destroy_mutex; + + pm_runtime_set_active(dev); + pm_runtime_get_noresume(dev); + pm_runtime_enable(dev); + + sd = &ox03c10->subdev; + v4l2_i2c_subdev_init(sd, client, &ox03c10_subdev_ops); + ret = ox03c10_initialize_controls(ox03c10); + if (ret) + goto err_power_off; + +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + sd->internal_ops = &ox03c10_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; +#endif + +#if defined(CONFIG_MEDIA_CONTROLLER) + ox03c10->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &ox03c10->pad); + if (ret < 0) + goto err_free_handler; +#endif + + v4l2_set_subdevdata(sd, ox03c10); + + memset(facing, 0, sizeof(facing)); + if (strcmp(ox03c10->module_facing, "back") == 0) + facing[0] = 'b'; + else + facing[0] = 'f'; + + snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", + ox03c10->module_index, facing, OX03C10_NAME, + dev_name(sd->dev)); + +#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE + ret = v4l2_async_register_subdev_sensor(sd); +#else + ret = v4l2_async_register_subdev_sensor_common(sd); +#endif + if (ret) { + dev_err(dev, "v4l2 async register subdev failed\n"); + goto err_clean_entity; + } + + ox03c10_parse_dt(ox03c10); + + /* remote serializer bind */ + ox03c10->remote_ser = NULL; + remote_ser = maxim_remote_cam_bind_ser(dev); + if (remote_ser != NULL) { + dev_info(dev, "remote serializer bind success\n"); + + remote_ser->cam_i2c_addr_def = ox03c10->cam_i2c_addr_def; + remote_ser->cam_i2c_addr_map = ox03c10->cam_i2c_addr_map; + + ox03c10->remote_ser = remote_ser; + } else { + dev_err(dev, "remote serializer bind fail\n"); + } + + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return 0; + +err_clean_entity: +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + +err_free_handler: + v4l2_ctrl_handler_free(&ox03c10->ctrl_handler); + +err_power_off: + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + __ox03c10_power_off(ox03c10); + +err_destroy_mutex: + mutex_destroy(&ox03c10->mutex); + + return ret; +} + +#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE +static int ox03c10_remove(struct i2c_client *client) +#else +static void ox03c10_remove(struct i2c_client *client) +#endif +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ox03c10 *ox03c10 = v4l2_get_subdevdata(sd); + + v4l2_async_unregister_subdev(sd); + +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&sd->entity); +#endif + v4l2_ctrl_handler_free(&ox03c10->ctrl_handler); + + mutex_destroy(&ox03c10->mutex); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + __ox03c10_power_off(ox03c10); + pm_runtime_set_suspended(&client->dev); + +#if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE + return 0; +#endif +} + +static const struct of_device_id ox03c10_of_match[] = { + { .compatible = "maxim,ovti,ox03c10" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ox03c10_of_match); + +static struct i2c_driver ox03c10_i2c_driver = { + .driver = { + .name = "maxim-ox03c10", + .pm = &ox03c10_pm_ops, + .of_match_table = of_match_ptr(ox03c10_of_match), + }, + .probe = &ox03c10_probe, + .remove = &ox03c10_remove, +}; + +module_i2c_driver(ox03c10_i2c_driver); + +MODULE_AUTHOR("Cai Wenzhong "); +MODULE_DESCRIPTION("Maxim Remote Sensor OmniVision OX03C10 Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/mis2031.c b/drivers/media/i2c/mis2031.c index d1f411d63e4c..e73a3a6c0fc7 100644 --- a/drivers/media/i2c/mis2031.c +++ b/drivers/media/i2c/mis2031.c @@ -1639,7 +1639,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&mis2031_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/os02k10.c b/drivers/media/i2c/os02k10.c index 79a4067953c6..f2eddec31993 100644 --- a/drivers/media/i2c/os02k10.c +++ b/drivers/media/i2c/os02k10.c @@ -2281,7 +2281,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&os02k10_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/os04d10.c b/drivers/media/i2c/os04d10.c index 9840e472ae94..41a1f743af5d 100644 --- a/drivers/media/i2c/os04d10.c +++ b/drivers/media/i2c/os04d10.c @@ -1903,7 +1903,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&os04d10_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/os12d40.c b/drivers/media/i2c/os12d40.c index 3cccd683a472..8b5a86877fc2 100644 --- a/drivers/media/i2c/os12d40.c +++ b/drivers/media/i2c/os12d40.c @@ -73,6 +73,16 @@ #define ANALOG_GAIN_DEFAULT 1024 #define OS12D40_REG_GROUP 0x3208 +#define OS12D40_GROUP_UPDATE_START_DATA 0x00 +#define OS12D40_GROUP_UPDATE_END_DATA 0x10 +#define OS12D40_GROUP_UPDATE_LAUNCH 0xA0 + +#define OS12D40_GROUP1_UPDATE_START_DATA 0x01 +#define OS12D40_GROUP1_UPDATE_END_DATA 0x11 +#define OS12D40_GROUP1_UPDATE_LAUNCH 0xA1 + +#define OS12D40_REG_XOFFSET_L 0x3811 +#define OS12D40_REG_YOFFSET_L 0x3813 #define OS12D40_REG_FLIP 0x3820 #define OS12D40_REG_MIRROR 0x3821 #define MIRROR_BIT_MASK BIT(2) @@ -98,7 +108,6 @@ #define OF_CAMERA_PINCTRL_STATE_SLEEP "rockchip,camera_sleep" #define OS12D40_NAME "os12d40" -#define OS12D40_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR10_1X10 #define USE_4_CELL (1) @@ -127,6 +136,7 @@ struct regval { }; struct os12d40_mode { + u32 bus_fmt; u32 width; u32 height; struct v4l2_fract max_fps; @@ -1129,9 +1139,823 @@ static const struct regval os12d40_4512x2512_regs_4lane[] = { {REG_NULL, 0x00}, }; +static const struct regval os12d40_2256x1256_regs_4lane[] = { + // Sysclk 90Mhz, MIPI4_996Mbps/Lane, 30Fps. + //Line_length =1080, Frame_length =2776 + {0x0103, 0x01}, + {0x0301, 0x80}, + {0x0302, 0x01}, + {0x0304, 0x01}, + {0x0305, 0xf0}, + {0x0306, 0x04}, + {0x0307, 0x01}, + {0x0309, 0x00}, + {0x0320, 0x20}, + {0x0324, 0x01}, + {0x0325, 0xc2}, + {0x0326, 0xd3}, + {0x032b, 0x06}, + {0x0344, 0x01}, + {0x0345, 0xb8}, + {0x0346, 0xcb}, + {0x0350, 0x02}, + {0x0360, 0x09}, + {0x3002, 0x80}, + {0x300d, 0x11}, + {0x300e, 0x11}, + {0x3012, 0x41}, + {0x3016, 0xf0}, + {0x3017, 0xd0}, + {0x3018, 0xf0}, + {0x3019, 0xc2}, + {0x301a, 0xf0}, + {0x301b, 0x34}, + {0x301c, 0x91}, + {0x301d, 0x02}, + {0x301e, 0x98}, + {0x301f, 0x21}, + {0x3022, 0xf0}, + {0x3027, 0x2e}, + {0x302c, 0x01}, + {0x302d, 0x00}, + {0x302e, 0x00}, + {0x302f, 0x00}, + {0x3030, 0x03}, + {0x3044, 0xc2}, + {0x304b, 0x00}, + {0x30d4, 0x00}, + {0x3209, 0x00}, + {0x320a, 0x00}, + {0x320b, 0x00}, + {0x320c, 0x00}, + {0x320d, 0x01}, + {0x3216, 0x01}, + {0x3218, 0x80}, + {0x33c0, 0x00}, + {0x33c3, 0x00}, + {0x33c4, 0x00}, + {0x3400, 0x04}, + {0x3408, 0x05}, + {0x340c, 0x10}, + {0x340e, 0x30}, + {0x3421, 0x08}, + {0x3422, 0x00}, + {0x3423, 0x15}, + {0x3424, 0x40}, + {0x3425, 0x10}, + {0x3426, 0x20}, + {0x3500, 0x00}, + {0x3501, 0x05}, + {0x3502, 0x60}, + {0x3504, 0x08}, + {0x3508, 0x01}, + {0x3509, 0x00}, + {0x350a, 0x01}, + {0x350b, 0x00}, + {0x350c, 0x00}, + {0x350e, 0x00}, + {0x3510, 0x01}, + {0x3511, 0x00}, + {0x3512, 0x00}, + {0x3513, 0x01}, + {0x3514, 0x00}, + {0x3515, 0x00}, + {0x3516, 0x01}, + {0x3517, 0x00}, + {0x3518, 0x00}, + {0x352d, 0x00}, + {0x352e, 0x00}, + {0x352f, 0x00}, + {0x3541, 0x00}, + {0x3542, 0x40}, + {0x3548, 0x01}, + {0x3549, 0x00}, + {0x354a, 0x01}, + {0x354b, 0x00}, + {0x354c, 0x00}, + {0x354e, 0x00}, + {0x3550, 0x01}, + {0x3551, 0x00}, + {0x3552, 0x00}, + {0x3581, 0x00}, + {0x3582, 0x40}, + {0x3588, 0x01}, + {0x3589, 0x00}, + {0x358a, 0x01}, + {0x358b, 0x00}, + {0x358c, 0x00}, + {0x3590, 0x01}, + {0x3591, 0x00}, + {0x3592, 0x00}, + {0x3610, 0x80}, + {0x3615, 0x27}, + {0x3617, 0x5a}, + {0x3624, 0x88}, + {0x3628, 0x77}, + {0x3644, 0x20}, + {0x3652, 0x00}, + {0x3653, 0x00}, + {0x3663, 0x6b}, + {0x3660, 0x4f}, + {0x3661, 0xd0}, + {0x3662, 0x09}, + {0x3680, 0xc1}, + {0x3683, 0x80}, + {0x3684, 0x03}, + {0x3685, 0x52}, + {0x3687, 0xd2}, + {0x3689, 0x27}, + {0x368a, 0x38}, + {0x368b, 0x08}, + {0x368c, 0x06}, + {0x368e, 0x00}, + {0x3692, 0x00}, + {0x3693, 0x00}, + {0x3696, 0x26}, + {0x3697, 0x1f}, + {0x3698, 0x1d}, + {0x3699, 0x59}, + {0x369a, 0x01}, + {0x369b, 0x20}, + {0x3700, 0x2e}, + {0x3701, 0x06}, + {0x3702, 0x4f}, + {0x3703, 0x28}, + {0x3704, 0x07}, + {0x3705, 0x00}, + {0x3706, 0x2f}, + {0x3707, 0x08}, + {0x3708, 0x2d}, + {0x3709, 0x5d}, + {0x370a, 0x00}, + {0x370b, 0x69}, + {0x370c, 0x0c}, + {0x3711, 0x30}, + {0x3712, 0x00}, + {0x3713, 0x00}, + {0x3714, 0x63}, + {0x371a, 0x1c}, + {0x371b, 0xd0}, + {0x371c, 0x04}, + {0x371d, 0x24}, + {0x371e, 0x13}, + {0x371f, 0x0c}, + {0x3720, 0x08}, + {0x3721, 0x15}, + {0x3724, 0x08}, + {0x3725, 0x32}, + {0x3727, 0x22}, + {0x3728, 0x11}, + {0x3729, 0x00}, + {0x372a, 0x00}, + {0x372b, 0x00}, + {0x3752, 0x02}, + {0x3753, 0x03}, + {0x3754, 0xee}, + {0x3760, 0x04}, + {0x3761, 0x14}, + {0x3762, 0x04}, + {0x3765, 0x08}, + {0x3766, 0x0c}, + {0x3767, 0x00}, + {0x376a, 0x00}, + {0x376b, 0x00}, + {0x376d, 0x1b}, + {0x376f, 0x02}, + {0x37d9, 0x08}, + {0x37f6, 0x07}, + {0x37f7, 0x04}, + {0x37f8, 0x2d}, + {0x37f9, 0x02}, + {0x37fa, 0x02}, + {0x37fb, 0x02}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x40}, + {0x3804, 0x12}, + {0x3805, 0x1f}, + {0x3806, 0x0a}, + {0x3807, 0x1f}, + {0x3808, 0x08}, + {0x3809, 0xd0}, + {0x380a, 0x04}, + {0x380b, 0xe8}, + {0x380c, 0x04}, + {0x380d, 0x38}, + {0x380e, 0x0a}, + {0x380f, 0xd8}, + {0x3810, 0x00}, + {0x3811, 0x21}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3814, 0x22}, + {0x3815, 0x22}, + {0x381a, 0x00}, + {0x381b, 0x01}, + {0x381e, 0x00}, + {0x381f, 0x02}, + {0x3820, 0x01}, + {0x3821, 0x0d}, + {0x3822, 0x00}, + {0x3823, 0x04}, + {0x3824, 0x00}, + {0x3825, 0x00}, + {0x3826, 0x00}, + {0x3827, 0x64}, + {0x3828, 0xf7}, + {0x382a, 0x83}, + {0x382c, 0x00}, + {0x382d, 0x00}, + {0x3835, 0x00}, + {0x3836, 0x00}, + {0x3837, 0x08}, + {0x3839, 0x00}, + {0x383b, 0x00}, + {0x383c, 0x00}, + {0x383d, 0x08}, + {0x383e, 0x00}, + {0x383f, 0x33}, + {0x3842, 0x00}, + {0x3856, 0x00}, + {0x3857, 0x08}, + {0x3858, 0x00}, + {0x3859, 0x10}, + {0x3865, 0x70}, + {0x3867, 0x08}, + {0x3868, 0x00}, + {0x3904, 0x33}, + {0x3907, 0x33}, + {0x390a, 0x9a}, + {0x3914, 0x34}, + {0x3938, 0x4b}, + {0x3939, 0x0c}, + {0x393b, 0x4b}, + {0x393c, 0x0c}, + {0x393e, 0x40}, + {0x393f, 0x0c}, + {0x394a, 0x01}, + {0x394b, 0xa5}, + {0x3975, 0x05}, + {0x3979, 0x32}, + {0x397d, 0x69}, + {0x3981, 0x15}, + {0x3983, 0x33}, + {0x3985, 0x1a}, + {0x3986, 0x08}, + {0x398a, 0x09}, + {0x39cd, 0x00}, + {0x39ce, 0x24}, + {0x39cf, 0x40}, + {0x39d0, 0x0a}, + {0x39d1, 0x50}, + {0x39d2, 0x05}, + {0x39d3, 0x94}, + {0x39d4, 0x01}, + {0x39d5, 0x79}, + {0x3a12, 0x00}, + {0x3a13, 0x00}, + {0x3a14, 0x00}, + {0x3a15, 0x00}, + {0x3a16, 0x00}, + {0x3a18, 0x04}, + {0x3a1a, 0x05}, + {0x3a1c, 0x0a}, + {0x3a1e, 0x03}, + {0x3a1f, 0x34}, + {0x3a22, 0x12}, + {0x3a24, 0x00}, + {0x3a25, 0xfe}, + {0x3a26, 0x01}, + {0x3a27, 0x01}, + {0x3a2a, 0xa8}, + {0x3a2b, 0xa8}, + {0x3a36, 0x00}, + {0x3d84, 0x00}, + {0x3d85, 0x1b}, + {0x3d88, 0x00}, + {0x3d89, 0x00}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d8c, 0xa3}, + {0x3d8d, 0xc4}, + {0x3da4, 0x04}, + {0x3daa, 0xa0}, + {0x3dab, 0x10}, + {0x3dac, 0xa1}, + {0x3dad, 0x8c}, + {0x3dae, 0xa1}, + {0x3daf, 0xb3}, + {0x3e00, 0x0e}, + {0x3e01, 0x0e}, + {0x3e02, 0x0e}, + {0x3e03, 0x0e}, + {0x3e04, 0x0e}, + {0x3e05, 0x0e}, + {0x3e06, 0x0e}, + {0x3e07, 0x0e}, + {0x3e09, 0x47}, + {0x3e0b, 0x25}, + {0x3e0d, 0x13}, + {0x3e0f, 0x09}, + {0x3e11, 0x07}, + {0x3e13, 0x06}, + {0x3e15, 0x05}, + {0x3e17, 0x04}, + {0x3e18, 0x38}, + {0x3e19, 0x38}, + {0x3e1a, 0x13}, + {0x3e1b, 0x30}, + {0x3e1c, 0x07}, + {0x3e1d, 0x06}, + {0x3e1e, 0x05}, + {0x3e1f, 0x04}, + {0x3e20, 0x0f}, + {0x3e21, 0x0f}, + {0x3e22, 0x0f}, + {0x3e23, 0x0f}, + {0x3e24, 0x0f}, + {0x3e25, 0x0f}, + {0x3e26, 0x0f}, + {0x3e27, 0x0f}, + {0x3e28, 0x07}, + {0x3e29, 0x07}, + {0x3e2a, 0x07}, + {0x3e2b, 0x02}, + {0x3e2c, 0x07}, + {0x3e2d, 0x07}, + {0x3e30, 0x07}, + {0x3e3a, 0x02}, + {0x3e3b, 0xdf}, + {0x3e3c, 0xff}, + {0x3e3d, 0x44}, + {0x3e3e, 0x00}, + {0x3e3f, 0x00}, + {0x3e40, 0xc1}, + {0x3e42, 0x54}, + {0x3e43, 0x54}, + {0x3e44, 0x54}, + {0x3e45, 0x54}, + {0x3f00, 0x10}, + {0x3f01, 0x26}, + {0x3f03, 0x40}, + {0x4002, 0xf3}, + {0x4009, 0x02}, + {0x400e, 0xc6}, + {0x400f, 0x00}, + {0x4010, 0x28}, + {0x4011, 0x01}, + {0x4012, 0x0d}, + {0x4015, 0x02}, + {0x4016, 0x11}, + {0x4017, 0x00}, + {0x4018, 0x03}, + {0x401a, 0x40}, + {0x401e, 0x00}, + {0x401f, 0xcc}, + {0x4020, 0x04}, + {0x4021, 0x00}, + {0x4022, 0x04}, + {0x4023, 0x00}, + {0x4024, 0x04}, + {0x4025, 0x00}, + {0x4026, 0x04}, + {0x4027, 0x00}, + {0x4028, 0x01}, + {0x4030, 0x00}, + {0x4031, 0x10}, + {0x4032, 0x00}, + {0x4033, 0x10}, + {0x4034, 0x08}, + {0x4035, 0x10}, + {0x4036, 0x08}, + {0x4037, 0x10}, + {0x4040, 0x08}, + {0x4041, 0x10}, + {0x4042, 0x08}, + {0x4043, 0x10}, + {0x4044, 0x00}, + {0x4045, 0x10}, + {0x4046, 0x00}, + {0x4047, 0x10}, + {0x4050, 0x00}, + {0x4051, 0x00}, + {0x4056, 0x25}, + {0x4102, 0xf3}, + {0x4109, 0x02}, + {0x410e, 0xc6}, + {0x410f, 0x00}, + {0x4110, 0x28}, + {0x4111, 0x01}, + {0x4112, 0x0d}, + {0x4115, 0x04}, + {0x4116, 0x1b}, + {0x4117, 0x00}, + {0x4118, 0x07}, + {0x411a, 0x40}, + {0x411e, 0x00}, + {0x411f, 0xcc}, + {0x4128, 0x01}, + {0x4156, 0x25}, + {0x4702, 0xf3}, + {0x4709, 0x02}, + {0x470e, 0xc6}, + {0x470f, 0x00}, + {0x4710, 0x28}, + {0x4711, 0x01}, + {0x4712, 0x0d}, + {0x4715, 0x04}, + {0x4716, 0x1b}, + {0x4717, 0x00}, + {0x4718, 0x07}, + {0x471a, 0x40}, + {0x471e, 0x00}, + {0x471f, 0xcc}, + {0x4728, 0x01}, + {0x4756, 0x25}, + {0x4301, 0x00}, + {0x4303, 0x00}, + {0x4305, 0x00}, + {0x4307, 0x00}, + {0x4308, 0x00}, + {0x430b, 0xff}, + {0x430d, 0x00}, + {0x430e, 0x00}, + {0x4503, 0x0f}, + {0x4504, 0x82}, + {0x4508, 0x00}, + {0x451d, 0x00}, + {0x451e, 0x00}, + {0x451f, 0x00}, + {0x4523, 0x00}, + {0x4526, 0x00}, + {0x4527, 0x00}, + {0x4530, 0x00}, + {0x4547, 0x06}, + {0x4640, 0x00}, + {0x4641, 0x30}, + {0x4643, 0x00}, + {0x4645, 0x13}, + {0x464a, 0x00}, + {0x464b, 0x30}, + {0x4680, 0x00}, + {0x4681, 0x24}, + {0x4683, 0x0c}, + {0x4800, 0x64}, + {0x480b, 0x10}, + {0x480c, 0x80}, + {0x480e, 0x04}, + {0x480f, 0x32}, + {0x4826, 0x32}, + {0x4833, 0x18}, + {0x4837, 0x10}, + {0x484b, 0x27}, + {0x4850, 0x47}, + {0x4853, 0x04}, + {0x4860, 0x00}, + {0x4861, 0xec}, + {0x4862, 0x04}, + {0x4883, 0x00}, + {0x4885, 0x10}, + {0x4888, 0x10}, + {0x4889, 0x03}, + {0x4d00, 0x04}, + {0x4d01, 0x8f}, + {0x4d02, 0xb9}, + {0x4d03, 0xc1}, + {0x4d04, 0xb6}, + {0x4d05, 0x7e}, + {0x5000, 0xeb}, + {0x5001, 0xcb}, + {0x5002, 0x15}, + {0x5003, 0x01}, + {0x5007, 0x1e}, + {0x5008, 0x00}, + {0x5009, 0x00}, + {0x500a, 0x00}, + {0x500b, 0x30}, + {0x500c, 0x12}, + {0x500d, 0x1f}, + {0x500e, 0x0a}, + {0x500f, 0x0f}, + {0x504b, 0x40}, + {0x5081, 0x00}, + {0x50c4, 0xaa}, + {0x50d0, 0x00}, + {0x50d1, 0x10}, + {0x50d2, 0x01}, + {0x50d3, 0xb3}, + {0x515a, 0x06}, + {0x515b, 0x06}, + {0x515c, 0x02}, + {0x515d, 0x02}, + {0x515e, 0x02}, + {0x515f, 0x06}, + {0x5160, 0x0a}, + {0x5161, 0x0e}, + {0x5180, 0x09}, + {0x5181, 0x10}, + {0x5182, 0x05}, + {0x5183, 0x20}, + {0x5184, 0x00}, + {0x5185, 0x10}, + {0x5186, 0x00}, + {0x5187, 0x10}, + {0x5188, 0x12}, + {0x5189, 0x00}, + {0x518a, 0x0a}, + {0x518b, 0x20}, + {0x518d, 0x09}, + {0x5192, 0x00}, + {0x5193, 0x18}, + {0x51d2, 0x10}, + {0x51da, 0x00}, + {0x51db, 0x30}, + {0x5250, 0x8e}, + {0x5251, 0x00}, + {0x5252, 0x10}, + {0x5254, 0x00}, + {0x5255, 0x70}, + {0x5256, 0x00}, + {0x5257, 0xc7}, + {0x5258, 0x12}, + {0x5259, 0x10}, + {0x525a, 0x0a}, + {0x525b, 0x30}, + {0x525e, 0x00}, + {0x525f, 0x18}, + {0x5260, 0x00}, + {0x5261, 0x10}, + {0x5262, 0x00}, + {0x5263, 0x10}, + {0x5264, 0x12}, + {0x5265, 0x00}, + {0x5266, 0x0a}, + {0x5267, 0x20}, + {0x5268, 0x00}, + {0x5269, 0x00}, + {0x526a, 0x00}, + {0x526b, 0x00}, + {0x526c, 0x12}, + {0x526d, 0x10}, + {0x526e, 0x0a}, + {0x526f, 0x30}, + {0x5278, 0x08}, + {0x5279, 0x10}, + {0x527a, 0x00}, + {0x527b, 0x00}, + {0x527c, 0x06}, + {0x527d, 0x06}, + {0x527e, 0x02}, + {0x527f, 0x02}, + {0x5280, 0x02}, + {0x5281, 0x06}, + {0x5282, 0x0a}, + {0x5283, 0x0e}, + {0x5381, 0x00}, + {0x53c4, 0xaa}, + {0x545a, 0x06}, + {0x545b, 0x06}, + {0x545c, 0x02}, + {0x545d, 0x02}, + {0x545e, 0x02}, + {0x545f, 0x06}, + {0x5460, 0x0a}, + {0x5461, 0x0e}, + {0x5480, 0x09}, + {0x5481, 0x10}, + {0x5482, 0x05}, + {0x5483, 0x20}, + {0x5484, 0x00}, + {0x5485, 0x08}, + {0x5486, 0x00}, + {0x5487, 0x00}, + {0x5488, 0x09}, + {0x5489, 0x00}, + {0x548a, 0x05}, + {0x548b, 0x20}, + {0x548d, 0x09}, + {0x54d2, 0x10}, + {0x54da, 0x00}, + {0x54da, 0x00}, + {0x54db, 0x30}, + {0x54db, 0x30}, + {0x5550, 0xec}, + {0x5551, 0x00}, + {0x5552, 0x10}, + {0x5554, 0x00}, + {0x5555, 0x72}, + {0x5556, 0x00}, + {0x5557, 0xca}, + {0x5558, 0x12}, + {0x5559, 0x10}, + {0x555a, 0x0a}, + {0x555b, 0x30}, + {0x555e, 0x00}, + {0x555f, 0x18}, + {0x5560, 0x00}, + {0x5561, 0x00}, + {0x5562, 0x00}, + {0x5563, 0x08}, + {0x5564, 0x12}, + {0x5565, 0x10}, + {0x5566, 0x0a}, + {0x5567, 0x30}, + {0x5568, 0x00}, + {0x5569, 0x00}, + {0x556a, 0x00}, + {0x556b, 0x00}, + {0x556c, 0x12}, + {0x556d, 0x10}, + {0x556e, 0x0a}, + {0x556f, 0x30}, + {0x557c, 0x06}, + {0x557d, 0x06}, + {0x557e, 0x02}, + {0x557f, 0x02}, + {0x5580, 0x02}, + {0x5581, 0x06}, + {0x5582, 0x0a}, + {0x5583, 0x0e}, + {0x5681, 0x00}, + {0x56c4, 0xaa}, + {0x575a, 0x06}, + {0x575b, 0x06}, + {0x575c, 0x02}, + {0x575d, 0x02}, + {0x575e, 0x02}, + {0x575f, 0x06}, + {0x5760, 0x0a}, + {0x5761, 0x0e}, + {0x5780, 0x09}, + {0x5781, 0x10}, + {0x5782, 0x05}, + {0x5783, 0x20}, + {0x5784, 0x00}, + {0x5785, 0x08}, + {0x5786, 0x00}, + {0x5787, 0x00}, + {0x5788, 0x09}, + {0x5789, 0x00}, + {0x578a, 0x05}, + {0x578b, 0x20}, + {0x578d, 0x09}, + {0x5792, 0x00}, + {0x5793, 0x18}, + {0x57d2, 0x10}, + {0x57da, 0x00}, + {0x57db, 0x30}, + {0x5850, 0xec}, + {0x5851, 0x00}, + {0x5852, 0x10}, + {0x5854, 0x00}, + {0x5855, 0x72}, + {0x5856, 0x00}, + {0x5857, 0xca}, + {0x5858, 0x12}, + {0x5859, 0x10}, + {0x585a, 0x0a}, + {0x585b, 0x30}, + {0x585e, 0x00}, + {0x585f, 0x18}, + {0x5860, 0x00}, + {0x5861, 0x00}, + {0x5862, 0x00}, + {0x5863, 0x08}, + {0x5864, 0x12}, + {0x5865, 0x10}, + {0x5866, 0x0a}, + {0x5867, 0x30}, + {0x5868, 0x00}, + {0x5869, 0x00}, + {0x586a, 0x00}, + {0x586b, 0x00}, + {0x586c, 0x12}, + {0x586d, 0x10}, + {0x586e, 0x0a}, + {0x586f, 0x30}, + {0x587c, 0x06}, + {0x587d, 0x06}, + {0x587e, 0x02}, + {0x587f, 0x02}, + {0x5880, 0x02}, + {0x5881, 0x06}, + {0x5882, 0x0a}, + {0x5883, 0x0e}, + {0x5f06, 0x10}, + {0x5f07, 0x20}, + {0x5f08, 0x0c}, + {0x5f09, 0x0c}, + {0x5f0a, 0x04}, + {0x5f0b, 0x04}, + {0x5f0c, 0x04}, + {0x5f0d, 0x0c}, + {0x5f0e, 0x14}, + {0x5f0f, 0x1c}, + {0x5f10, 0x01}, + {0x5f11, 0x01}, + {0x5f18, 0x12}, + {0x5f19, 0x20}, + {0x5f1a, 0x0a}, + {0x5f1b, 0x40}, + {0x5f1d, 0x10}, + {0x5f1f, 0x00}, + {0x5f20, 0x12}, + {0x5f21, 0x00}, + {0x5f22, 0x0a}, + {0x5f23, 0x40}, + {0x5f25, 0x09}, + {0x5f2a, 0x00}, + {0x5f2b, 0x18}, + {0x6600, 0x00}, + {0x6601, 0x00}, + {0x6602, 0x00}, + {0x6603, 0x83}, + {0x6960, 0x0f}, + {0x69a2, 0x09}, + {0x69a3, 0x00}, + {0x69a6, 0x05}, + {0x69a7, 0x10}, + {0x69aa, 0x09}, + {0x69ab, 0x00}, + {0x69ae, 0x05}, + {0x69af, 0x10}, + {0x69b2, 0x09}, + {0x69b3, 0x00}, + {0x69b6, 0x05}, + {0x69b7, 0x10}, + {0x69ba, 0x09}, + {0x69bb, 0x00}, + {0x69be, 0x05}, + {0x69bf, 0x10}, + {0x6a24, 0x09}, + {0x6a25, 0x00}, + {0x6a2a, 0x05}, + {0x6a2b, 0x10}, + {0x6a61, 0x40}, + {0x6a64, 0x09}, + {0x6a65, 0x00}, + {0x6a6a, 0x05}, + {0x6a6b, 0x10}, + {0x6a23, 0x00}, + {0x6a27, 0x00}, + {0x6a63, 0x00}, + {0x6a67, 0x00}, + {0x69a1, 0x00}, + {0x69a5, 0x00}, + {0x69a9, 0x00}, + {0x69ad, 0x00}, + {0x69b1, 0x00}, + {0x69b5, 0x00}, + {0x69b9, 0x00}, + {0x69bd, 0x00}, + {0xfff4, 0x01}, + {0xfff6, 0x00}, + {0x0361, 0x07}, + {0x3644, 0x20}, + {0x5000, 0x2b}, + {0x5001, 0x0b}, + {0x50d4, 0x00}, + {0x5171, 0xbe}, + {0x3222, 0x03}, + {0x3208, 0x06}, + {0x3938, 0x41}, + {0x393b, 0x41}, + {0x3208, 0x16}, + {0x3208, 0x07}, + {0x3938, 0x43}, + {0x393b, 0x44}, + {0x3208, 0x17}, + {0x3208, 0x08}, + {0x3938, 0x45}, + {0x393b, 0x46}, + {0x3208, 0x18}, + {0x3208, 0x09}, + {0x3938, 0x4b}, + {0x393b, 0x4b}, + {0x3208, 0x19}, + {0x5000, 0x29}, + {0x5001, 0x01}, + {REG_NULL, 0x00}, +}; static const struct os12d40_mode supported_modes_4lane[] = { { + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 2256, + .height = 1256, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0500, + .hts_def = 0x438 * 8, + .vts_def = 0x0ad8, + .reg_list = os12d40_2256x1256_regs_4lane, + .hdr_mode = NO_HDR, + }, + { + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .width = 4512, .height = 2512, .max_fps = { @@ -1321,7 +2145,7 @@ static int os12d40_set_fmt(struct v4l2_subdev *sd, mutex_lock(&os12d40->mutex); mode = os12d40_find_best_fit(os12d40, fmt); - fmt->format.code = OS12D40_MEDIA_BUS_FMT; + fmt->format.code = mode->bus_fmt; fmt->format.width = mode->width; fmt->format.height = mode->height; fmt->format.field = V4L2_FIELD_NONE; @@ -1366,7 +2190,7 @@ static int os12d40_get_fmt(struct v4l2_subdev *sd, } else { fmt->format.width = mode->width; fmt->format.height = mode->height; - fmt->format.code = OS12D40_MEDIA_BUS_FMT; + fmt->format.code = mode->bus_fmt; fmt->format.field = V4L2_FIELD_NONE; } mutex_unlock(&os12d40->mutex); @@ -1378,9 +2202,11 @@ static int os12d40_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_mbus_code_enum *code) { + struct os12d40 *os12d40 = to_os12d40(sd); + if (code->index != 0) return -EINVAL; - code->code = OS12D40_MEDIA_BUS_FMT; + code->code = os12d40->cur_mode->bus_fmt; return 0; } @@ -1394,9 +2220,6 @@ static int os12d40_enum_frame_sizes(struct v4l2_subdev *sd, if (fse->index >= os12d40->cfg_num) return -EINVAL; - if (fse->code != OS12D40_MEDIA_BUS_FMT) - return -EINVAL; - fse->min_width = supported_modes[fse->index].width; fse->max_width = supported_modes[fse->index].width; fse->max_height = supported_modes[fse->index].height; @@ -1487,7 +2310,10 @@ static long os12d40_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKMODULE_GET_BAYER_MODE: bayer_mode = (u32 *)arg; #ifdef USE_4_CELL - *bayer_mode = RKMODULE_QUARD_BAYER; + if (os12d40->cur_mode->width == 4512) + *bayer_mode = RKMODULE_QUARD_BAYER; + else + *bayer_mode = RKMODULE_NORMAL_BAYER; #else *bayer_mode = RKMODULE_NORMAL_BAYER; #endif @@ -1845,7 +2671,7 @@ static int os12d40_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) /* Initialize try_fmt */ try_fmt->width = def_mode->width; try_fmt->height = def_mode->height; - try_fmt->code = OS12D40_MEDIA_BUS_FMT; + try_fmt->code = def_mode->bus_fmt; try_fmt->field = V4L2_FIELD_NONE; mutex_unlock(&os12d40->mutex); @@ -1864,7 +2690,7 @@ static int os12d40_enum_frame_interval(struct v4l2_subdev *sd, if (fie->index >= os12d40->cfg_num) return -EINVAL; - fie->code = OS12D40_MEDIA_BUS_FMT; + fie->code = supported_modes[fie->index].bus_fmt; fie->width = supported_modes[fie->index].width; fie->height = supported_modes[fie->index].height; fie->interval = supported_modes[fie->index].max_fps; @@ -1892,10 +2718,17 @@ static int os12d40_get_selection(struct v4l2_subdev *sd, struct os12d40 *os12d40 = to_os12d40(sd); if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) { - sel->r.left = CROP_START(os12d40->cur_mode->width, DST_WIDTH); - sel->r.width = DST_WIDTH; - sel->r.top = CROP_START(os12d40->cur_mode->height, DST_HEIGHT); - sel->r.height = DST_HEIGHT; + if (os12d40->cur_mode->width == 4512) { + sel->r.left = CROP_START(os12d40->cur_mode->width, DST_WIDTH); + sel->r.width = DST_WIDTH; + sel->r.top = CROP_START(os12d40->cur_mode->height, DST_HEIGHT); + sel->r.height = DST_HEIGHT; + } else { + sel->r.left = 0; + sel->r.width = os12d40->cur_mode->width; + sel->r.top = 0; + sel->r.height = os12d40->cur_mode->height; + } return 0; } return -EINVAL; @@ -1951,6 +2784,7 @@ static int os12d40_set_ctrl(struct v4l2_ctrl *ctrl) int ret = 0; u32 again = 0; u32 dgain = 0; + u32 offset = 0; /* Propagate change of current control to all related controls */ switch (ctrl->id) { @@ -2010,25 +2844,81 @@ static int os12d40_set_ctrl(struct v4l2_ctrl *ctrl) ret = os12d40_read_reg(os12d40->client, OS12D40_REG_MIRROR, OS12D40_REG_VALUE_08BIT, &val); - if (ctrl->val) - val |= MIRROR_BIT_MASK; - else + if (ctrl->val) { val &= ~MIRROR_BIT_MASK; + if (os12d40->cur_mode->width == 2256) + offset = 0x22; + else + offset = 0x40; + } else { + val |= MIRROR_BIT_MASK; + if (os12d40->cur_mode->width == 2256) + offset = 0x21; + else +#if USE_4_CELL + offset = 0x3e; +#else + offset = 0x3f; +#endif + } + if (os12d40->streaming) + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP_UPDATE_START_DATA); + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_XOFFSET_L, + OS12D40_REG_VALUE_08BIT, + offset); ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_MIRROR, OS12D40_REG_VALUE_08BIT, val); + if (os12d40->streaming) { + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP_UPDATE_END_DATA); + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP_UPDATE_LAUNCH); + } break; case V4L2_CID_VFLIP: ret = os12d40_read_reg(os12d40->client, OS12D40_REG_FLIP, OS12D40_REG_VALUE_08BIT, &val); - if (ctrl->val) + if (ctrl->val) { val |= FLIP_BIT_MASK; - else + if (os12d40->cur_mode->width == 2256) + offset = 0x05; + else +#if USE_4_CELL + offset = 0x06; +#else + offset = 0x07; +#endif + } else { val &= ~FLIP_BIT_MASK; + if (os12d40->cur_mode->width == 2256) + offset = 0x04; + else + offset = 0x08; + } + if (os12d40->streaming) + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP1_UPDATE_START_DATA); + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_YOFFSET_L, + OS12D40_REG_VALUE_08BIT, + offset); ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_FLIP, OS12D40_REG_VALUE_08BIT, val); + if (os12d40->streaming) { + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP1_UPDATE_END_DATA); + ret |= os12d40_write_reg(os12d40->client, OS12D40_REG_GROUP, + OS12D40_REG_VALUE_08BIT, + OS12D40_GROUP1_UPDATE_LAUNCH); + } break; default: dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", diff --git a/drivers/media/i2c/ov50c40.c b/drivers/media/i2c/ov50c40.c index 3f92712ea728..973faff5c87a 100644 --- a/drivers/media/i2c/ov50c40.c +++ b/drivers/media/i2c/ov50c40.c @@ -3914,6 +3914,7 @@ static const struct regval ov50c40_10bit_8192x6144_dphy_12fps_regs[] = { {REG_NULL, 0x00}, }; +#ifdef DEBUG static const struct regval ov50c40_10bit_4096x3072_cphy_regs[] = { {0x0103, 0x01}, {0x0301, 0xc0}, @@ -4504,6 +4505,7 @@ static const struct regval ov50c40_10bit_4096x3072_cphy_regs[] = { {0x5d45, 0x05}, {REG_NULL, 0x00}, }; +#endif static const struct regval ov50c40_10bit_4096x3072_cphy_30fps_regs[] = { {0x0103, 0x01}, @@ -5828,6 +5830,7 @@ static const struct ov50c40_mode supported_modes_dphy[] = { }; static const struct ov50c40_mode supported_modes_cphy[] = { +#ifdef DEBUG { .bus_fmt = MEDIA_BUS_FMT_SGBRG10_1X10, .width = 4096, @@ -5846,6 +5849,7 @@ static const struct ov50c40_mode supported_modes_cphy[] = { .spd = &ov50c40_spd, .vc[PAD0] = 0, }, +#endif { .bus_fmt = MEDIA_BUS_FMT_SGBRG10_1X10, .width = 4096, diff --git a/drivers/media/i2c/ox03c10.c b/drivers/media/i2c/ox03c10.c index dbda76a17443..99c80bb726b1 100644 --- a/drivers/media/i2c/ox03c10.c +++ b/drivers/media/i2c/ox03c10.c @@ -33,7 +33,7 @@ #endif #define OX03C10_LANES 4 -#define OX03C10_BITS_PER_SAMPLE 12 +#define OX03C10_BITS_PER_SAMPLE 10 #define OX03C10_LINK_FREQ_300MHZ 300000000 #define OX03C10_LINK_FREQ_480MHZ 480000000 /* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */ @@ -57,7 +57,7 @@ #define OX03C10_GAIN_MIN 0x10 #define OX03C10_GAIN_MAX 0xf7f #define OX03C10_GAIN_STEP 0x01 -#define OX03C10_GAIN_DEFAULT 0x10 +#define OX03C10_GAIN_DEFAULT 0x30 // exposure ctrl reg for DCG #define OX03C10_EXPOSURE_HCG_MIN 4 #define OX03C10_EXPOSURE_HCG_STEP 1 @@ -224,7 +224,9 @@ struct ox03c10 { const char *module_name; const char *len_name; bool has_init_exp; + bool has_init_wbgain; struct preisp_hdrae_exp_s init_hdrae_exp; + struct rkmodule_wb_gain_group init_wbgain; struct rkmodule_dcg_ratio dcg_ratio; struct rkmodule_dcg_ratio spd_ratio; }; @@ -478,15 +480,15 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x3b41, 0x40}, {0x3b42, 0x00}, {0x3b43, 0x90}, - {0x3b44, 0x00}, - {0x3b45, 0x20}, - {0x3b46, 0x00}, - {0x3b47, 0x20}, + {0x3b44, 0x02}, + {0x3b45, 0x00}, + {0x3b46, 0x02}, + {0x3b47, 0x00}, {0x3b48, 0x19}, {0x3b49, 0x12}, {0x3b4a, 0x16}, {0x3b4b, 0x2e}, - {0x3b4c, 0x00}, + {0x3b4c, 0x03}, {0x3b4d, 0x00}, {0x3b86, 0x00}, {0x3b87, 0x34}, @@ -529,7 +531,7 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x4310, 0x95}, {0x4311, 0x16}, {0x4316, 0x00}, - {0x4317, 0x08}, + {0x4317, 0x38}, {0x4319, 0x03}, {0x431a, 0x00}, {0x431b, 0x00}, @@ -560,8 +562,8 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x4598, 0x40}, {0x4599, 0x0e}, {0x459a, 0x0e}, - {0x459b, 0xfb}, - {0x459c, 0xf3}, + {0x459b, 0xf5}, + {0x459c, 0xf1}, {0x4602, 0x00}, {0x4603, 0x13}, {0x4604, 0x00}, @@ -988,18 +990,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x4649, 0x03}, {0x4d09, 0xff}, {0x4d09, 0xdf}, - {0x5019, 0x00}, - {0x501a, 0xff}, - {0x501b, 0xff}, - {0x501d, 0x00}, - {0x501e, 0x23}, - {0x501f, 0x8e}, - {0x5021, 0x00}, - {0x5022, 0x00}, - {0x5023, 0x50}, - {0x5025, 0x00}, - {0x5026, 0x23}, - {0x5027, 0x8e}, {0x5b80, 0x01}, {0x5c00, 0x08}, {0x5c80, 0x00}, @@ -1485,8 +1475,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x5886, 0x07}, {0x5887, 0x3f}, {0x4221, 0x13}, - {0x380e, 0x03}, - {0x380f, 0x37}, {0x3501, 0x01}, {0x3502, 0xc8}, {0x3541, 0x01}, @@ -1505,7 +1493,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600[] = { {0x4f02, 0x80}, {0x4f03, 0x2c}, {0x4f04, 0xf8}, - {0x0100, 0x01}, {REG_NULL, 0x00}, }; @@ -1756,15 +1743,15 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x3b41, 0x40}, {0x3b42, 0x00}, {0x3b43, 0x90}, - {0x3b44, 0x00}, - {0x3b45, 0x20}, - {0x3b46, 0x00}, - {0x3b47, 0x20}, + {0x3b44, 0x02}, + {0x3b45, 0x00}, + {0x3b46, 0x02}, + {0x3b47, 0x00}, {0x3b48, 0x19}, {0x3b49, 0x12}, {0x3b4a, 0x16}, {0x3b4b, 0x2e}, - {0x3b4c, 0x00}, + {0x3b4c, 0x03}, {0x3b4d, 0x00}, {0x3b86, 0x00}, {0x3b87, 0x34}, @@ -1807,7 +1794,7 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x4310, 0x95}, {0x4311, 0x16}, {0x4316, 0x00}, - {0x4317, 0x08}, + {0x4317, 0x38}, {0x4319, 0x01}, {0x431a, 0x00}, {0x431b, 0x00}, @@ -1838,8 +1825,8 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x4598, 0x40}, {0x4599, 0x0e}, {0x459a, 0x0e}, - {0x459b, 0xfb}, - {0x459c, 0xf3}, + {0x459b, 0xf5}, + {0x459c, 0xf1}, {0x4602, 0x00}, {0x4603, 0x13}, {0x4604, 0x00}, @@ -2266,18 +2253,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x4649, 0x03}, {0x4d09, 0xff}, {0x4d09, 0xdf}, - {0x5019, 0x00}, - {0x501a, 0xff}, - {0x501b, 0xff}, - {0x501d, 0x00}, - {0x501e, 0x23}, - {0x501f, 0x8e}, - {0x5021, 0x00}, - {0x5022, 0x00}, - {0x5023, 0x50}, - {0x5025, 0x00}, - {0x5026, 0x23}, - {0x5027, 0x8e}, {0x5b80, 0x08}, {0x5c00, 0x08}, {0x5c80, 0x00}, @@ -2763,8 +2738,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x5886, 0x07}, {0x5887, 0x3f}, {0x4221, 0x13}, - {0x380e, 0x03}, - {0x380f, 0x37}, {0x3501, 0x01}, {0x3502, 0xc8}, {0x3541, 0x01}, @@ -2782,7 +2755,6 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600[] = { {0x4f02, 0x80}, {0x4f03, 0x2c}, {0x4f04, 0xf8}, - {0x0100, 0x01}, {REG_NULL, 0xff}, }; @@ -3855,7 +3827,1091 @@ static const struct regval ox03c10_1920x1080_30fps_HDR3_LFM_PWL16_mipi996[] = { {0x040c, 0x2e}, {0x040d, 0x44}, {0x040e, 0x0c}, - {0x0100, 0x01}, + {REG_NULL, 0xff}, +}; + +static const struct regval ox03c10_1920x1080_30fps_linear_raw10_mipi996[] = { + {0x0103, 0x01}, + {0x0107, 0x01}, + {0x4d5a, 0x1c}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x3208, 0x04}, + {0x4620, 0x04}, + {0x3208, 0x14}, + {0x3208, 0x05}, + {0x4620, 0x04}, + {0x3208, 0x15}, + {0x3208, 0x02}, + {0x3507, 0x00}, + {0x3208, 0x12}, + {0x3208, 0xa2}, + {0x0301, 0xc8}, + {0x0303, 0x01}, + {0x0304, 0x01}, + {0x0305, 0x2c}, + {0x0306, 0x04}, + {0x0307, 0x01}, + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x00}, + {0x0323, 0x05}, + {0x0324, 0x01}, + {0x0325, 0x2c}, + {0x0400, 0xe0}, + {0x0401, 0x80}, + {0x0403, 0xde}, + {0x0404, 0x34}, + {0x0405, 0x3b}, + {0x0406, 0xde}, + {0x0407, 0x08}, + {0x0408, 0xe0}, + {0x0409, 0x7f}, + {0x040a, 0xde}, + {0x040b, 0x34}, + {0x040c, 0x47}, + {0x040d, 0xd8}, + {0x040e, 0x08}, + {0x2803, 0xfe}, + {0x280b, 0x00}, + {0x280c, 0x79}, + {0x3001, 0x03}, + {0x3002, 0xf8}, + {0x3005, 0x80}, + {0x3007, 0x01}, + {0x3008, 0x80}, + {0x3012, 0x41}, + {0x3020, 0x05}, + {0x3700, 0x28}, + {0x3701, 0x15}, + {0x3702, 0x19}, + {0x3703, 0x23}, + {0x3704, 0x0a}, + {0x3705, 0x00}, + {0x3706, 0x3e}, + {0x3707, 0x0d}, + {0x3708, 0x50}, + {0x3709, 0x5a}, + {0x370a, 0x00}, + {0x370b, 0x96}, + {0x3711, 0x11}, + {0x3712, 0x13}, + {0x3717, 0x02}, + {0x3718, 0x73}, + {0x372c, 0x40}, + {0x3733, 0x01}, + {0x3738, 0x36}, + {0x3739, 0x36}, + {0x373a, 0x25}, + {0x373b, 0x25}, + {0x373f, 0x21}, + {0x3740, 0x21}, + {0x3741, 0x21}, + {0x3742, 0x21}, + {0x3747, 0x28}, + {0x3748, 0x28}, + {0x3749, 0x19}, + {0x3755, 0x1a}, + {0x3756, 0x0a}, + {0x3757, 0x1c}, + {0x3765, 0x19}, + {0x3766, 0x05}, + {0x3767, 0x05}, + {0x3768, 0x13}, + {0x376c, 0x07}, + {0x3778, 0x20}, + {0x377c, 0xc8}, + {0x3781, 0x02}, + {0x3783, 0x02}, + {0x379c, 0x58}, + {0x379e, 0x00}, + {0x379f, 0x00}, + {0x37a0, 0x00}, + {0x37bc, 0x22}, + {0x37c0, 0x01}, + {0x37c4, 0x3e}, + {0x37c5, 0x3e}, + {0x37c6, 0x2a}, + {0x37c7, 0x28}, + {0x37c8, 0x02}, + {0x37c9, 0x12}, + {0x37cb, 0x29}, + {0x37cd, 0x29}, + {0x37d2, 0x00}, + {0x37d3, 0x73}, + {0x37d6, 0x00}, + {0x37d7, 0x6b}, + {0x37dc, 0x00}, + {0x37df, 0x54}, + {0x37e2, 0x00}, + {0x37e3, 0x00}, + {0x37f8, 0x00}, + {0x37f9, 0x01}, + {0x37fa, 0x00}, + {0x37fb, 0x19}, + {0x3c03, 0x01}, + {0x3c04, 0x01}, + {0x3c06, 0x21}, + {0x3c08, 0x01}, + {0x3c09, 0x01}, + {0x3c0a, 0x01}, + {0x3c0b, 0x21}, + {0x3c13, 0x21}, + {0x3c14, 0x82}, + {0x3c16, 0x13}, + {0x3c21, 0x00}, + {0x3c22, 0xf3}, + {0x3c37, 0x12}, + {0x3c38, 0x31}, + {0x3c3c, 0x00}, + {0x3c3d, 0x03}, + {0x3c44, 0x16}, + {0x3c5c, 0x8a}, + {0x3c5f, 0x03}, + {0x3c61, 0x80}, + {0x3c6f, 0x2b}, + {0x3c70, 0x5f}, + {0x3c71, 0x2c}, + {0x3c72, 0x2c}, + {0x3c73, 0x2c}, + {0x3c76, 0x12}, + {0x3182, 0x12}, + {0x320e, 0x00}, + {0x320f, 0x00}, + {0x3211, 0x61}, + {0x3215, 0xcd}, + {0x3219, 0x08}, + {0x3506, 0x30}, + {0x350a, 0x01}, + {0x350b, 0x00}, + {0x350c, 0x00}, + {0x3586, 0x60}, + {0x358a, 0x01}, + {0x358b, 0x00}, + {0x358c, 0x00}, + {0x3541, 0x00}, + {0x3542, 0x04}, + {0x3548, 0x04}, + {0x3549, 0x40}, + {0x354a, 0x01}, + {0x354b, 0x00}, + {0x354c, 0x00}, + {0x35c1, 0x00}, + {0x35c2, 0x02}, + {0x35c6, 0xa0}, + {0x3600, 0x8f}, + {0x3605, 0x16}, + {0x3609, 0xf0}, + {0x360a, 0x01}, + {0x360e, 0x1d}, + {0x360f, 0x10}, + {0x3610, 0x70}, + {0x3611, 0x3a}, + {0x3612, 0x28}, + {0x361a, 0x29}, + {0x361b, 0x6c}, + {0x361c, 0x0b}, + {0x361d, 0x00}, + {0x361e, 0xfc}, + {0x362a, 0x00}, + {0x364d, 0x0f}, + {0x364e, 0x18}, + {0x364f, 0x12}, + {0x3653, 0x1c}, + {0x3654, 0x00}, + {0x3655, 0x1f}, + {0x3656, 0x1f}, + {0x3657, 0x0c}, + {0x3658, 0x0a}, + {0x3659, 0x14}, + {0x365a, 0x18}, + {0x365b, 0x14}, + {0x365c, 0x10}, + {0x365e, 0x12}, + {0x3674, 0x08}, + {0x3677, 0x3a}, + {0x3678, 0x3a}, + {0x3679, 0x19}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3806, 0x05}, + {0x3807, 0x0b}, + {0x3808, 0x07}, + {0x3809, 0x80}, + {0x380a, 0x05}, + {0x380b, 0x00}, + {0x380c, 0x04}, + {0x380d, 0xd3}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x381c, 0x18}, + {0x381e, 0x01}, + {0x381f, 0x01}, + {0x3820, 0x00}, + {0x3821, 0x19}, + {0x3832, 0x00}, + {0x3834, 0x00}, + {0x384c, 0x02}, + {0x384d, 0x53}, + {0x3850, 0x00}, + {0x3851, 0x42}, + {0x3852, 0x00}, + {0x3853, 0x40}, + {0x3858, 0x04}, + {0x388c, 0x02}, + {0x388d, 0x71}, + {0x3b40, 0x05}, + {0x3b41, 0x40}, + {0x3b42, 0x00}, + {0x3b43, 0x90}, + {0x3b44, 0x00}, + {0x3b45, 0x20}, + {0x3b46, 0x00}, + {0x3b47, 0x20}, + {0x3b48, 0x19}, + {0x3b49, 0x12}, + {0x3b4a, 0x16}, + {0x3b4b, 0x2e}, + {0x3b4c, 0x00}, + {0x3b4d, 0x00}, + {0x3b86, 0x00}, + {0x3b87, 0x34}, + {0x3b88, 0x00}, + {0x3b89, 0x08}, + {0x3b8a, 0x05}, + {0x3b8b, 0x00}, + {0x3b8c, 0x07}, + {0x3b8d, 0x80}, + {0x3b8e, 0x00}, + {0x3b8f, 0x00}, + {0x3b92, 0x05}, + {0x3b93, 0x00}, + {0x3b94, 0x07}, + {0x3b95, 0x80}, + {0x3b9e, 0x09}, + {0x3d82, 0x73}, + {0x3d85, 0x05}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d99, 0x00}, + {0x3d9a, 0x9f}, + {0x3d9b, 0x00}, + {0x3d9c, 0xa0}, + {0x3da4, 0x00}, + {0x3da7, 0x50}, + {0x420e, 0xff}, + {0x420f, 0xff}, + {0x4210, 0xff}, + {0x4211, 0xff}, + {0x421e, 0x02}, + {0x421f, 0x45}, + {0x4220, 0xe1}, + {0x4221, 0x05}, + {0x4301, 0x0f}, + {0x4307, 0x03}, + {0x4308, 0x13}, + {0x430a, 0x53}, + {0x430d, 0x93}, + {0x430f, 0x57}, + {0x4310, 0x95}, + {0x4311, 0x16}, + {0x4316, 0x00}, + {0x4317, 0x08}, + {0x4319, 0x09}, + {0x431a, 0x00}, + {0x431b, 0x22}, + {0x431d, 0x2a}, + {0x431e, 0x11}, + {0x431f, 0x30}, + {0x4320, 0x59}, + {0x4323, 0x80}, + {0x4324, 0x00}, + {0x4503, 0x4e}, + {0x4505, 0x00}, + {0x4509, 0x00}, + {0x450a, 0x00}, + {0x4580, 0xf8}, + {0x4583, 0x07}, + {0x4584, 0x6a}, + {0x4585, 0x08}, + {0x4586, 0x05}, + {0x4587, 0x04}, + {0x4588, 0x73}, + {0x4589, 0x05}, + {0x458a, 0x1f}, + {0x458b, 0x02}, + {0x458c, 0xdc}, + {0x458d, 0x03}, + {0x458e, 0x02}, + {0x4597, 0x07}, + {0x4598, 0x40}, + {0x4599, 0x0e}, + {0x459a, 0x0e}, + {0x459b, 0xfb}, + {0x459c, 0xf3}, + {0x4602, 0x00}, + {0x4603, 0x13}, + {0x4604, 0x00}, + {0x4609, 0x0a}, + {0x460a, 0x00}, + {0x4610, 0x00}, + {0x4611, 0x70}, + {0x4612, 0x00}, + {0x4613, 0x0c}, + {0x4614, 0x00}, + {0x4615, 0x70}, + {0x4616, 0x00}, + {0x4617, 0x0c}, + {0x4800, 0x04}, + {0x480a, 0x22}, + {0x4813, 0xe4}, + {0x4814, 0x2a}, + {0x4837, 0x0d}, + {0x484b, 0x47}, + {0x484f, 0x40}, + {0x4887, 0x51}, + {0x4d00, 0x4a}, + {0x4d01, 0x18}, + {0x4d05, 0xff}, + {0x4d06, 0x88}, + {0x4d08, 0x63}, + {0x4d09, 0xdf}, + {0x4d15, 0x7d}, + {0x4d1a, 0x20}, + {0x4d30, 0x0a}, + {0x4d31, 0x00}, + {0x4d34, 0x7d}, + {0x4d3c, 0x7d}, + {0x4f00, 0x3f}, + {0x4f01, 0xff}, + {0x4f02, 0xff}, + {0x4f03, 0x2c}, + {0x4f04, 0xe0}, + {0x6a00, 0x00}, + {0x6a01, 0x20}, + {0x6a02, 0x00}, + {0x6a03, 0x20}, + {0x6a04, 0x02}, + {0x6a05, 0x80}, + {0x6a06, 0x01}, + {0x6a07, 0xe0}, + {0x6a08, 0xcf}, + {0x6a09, 0x01}, + {0x6a0a, 0x40}, + {0x6a20, 0x00}, + {0x6a21, 0x02}, + {0x6a22, 0x00}, + {0x6a23, 0x00}, + {0x6a24, 0x00}, + {0x6a25, 0xf0}, + {0x6a26, 0x00}, + {0x6a27, 0x00}, + {0x6a28, 0x00}, + {0x5000, 0x8f}, + {0x5001, 0x65}, + {0x5002, 0x7f}, + {0x5003, 0x6a}, + {0x5004, 0x3e}, + {0x5005, 0x1e}, + {0x5006, 0x1e}, + {0x5007, 0x1e}, + {0x5008, 0x00}, + {0x500c, 0x00}, + {0x502c, 0x00}, + {0x502e, 0x00}, + {0x502f, 0x00}, + {0x504b, 0x00}, + {0x5053, 0x00}, + {0x505b, 0x00}, + {0x5063, 0x00}, + {0x5070, 0x00}, + {0x5074, 0x04}, + {0x507a, 0x00}, + {0x507b, 0x00}, + {0x5500, 0x02}, + {0x5700, 0x02}, + {0x5900, 0x02}, + {0x6007, 0x04}, + {0x6008, 0x05}, + {0x6009, 0x02}, + {0x600b, 0x08}, + {0x600c, 0x07}, + {0x600d, 0x88}, + {0x6016, 0x00}, + {0x6027, 0x04}, + {0x6028, 0x05}, + {0x6029, 0x02}, + {0x602b, 0x08}, + {0x602c, 0x07}, + {0x602d, 0x88}, + {0x6047, 0x04}, + {0x6048, 0x05}, + {0x6049, 0x02}, + {0x604b, 0x08}, + {0x604c, 0x07}, + {0x604d, 0x88}, + {0x6067, 0x04}, + {0x6068, 0x05}, + {0x6069, 0x02}, + {0x606b, 0x08}, + {0x606c, 0x07}, + {0x606d, 0x88}, + {0x6087, 0x04}, + {0x6088, 0x05}, + {0x6089, 0x02}, + {0x608b, 0x08}, + {0x608c, 0x07}, + {0x608d, 0x88}, + {0x5e00, 0x02}, + {0x5e01, 0x0b}, + {0x5e02, 0x00}, + {0x5e03, 0x00}, + {0x5e04, 0x00}, + {0x5e05, 0x0b}, + {0x5e06, 0x0c}, + {0x5e07, 0x0c}, + {0x5e08, 0x0c}, + {0x5e09, 0x0c}, + {0x5e0a, 0x0c}, + {0x5e0b, 0x0d}, + {0x5e0c, 0x0d}, + {0x5e0d, 0x0d}, + {0x5e0e, 0x0d}, + {0x5e0f, 0x0d}, + {0x5e10, 0x0d}, + {0x5e11, 0x0d}, + {0x5e12, 0x0e}, + {0x5e13, 0x0e}, + {0x5e14, 0x0e}, + {0x5e15, 0x0e}, + {0x5e16, 0x0e}, + {0x5e17, 0x0e}, + {0x5e18, 0x0e}, + {0x5e19, 0x10}, + {0x5e1a, 0x11}, + {0x5e1b, 0x11}, + {0x5e1c, 0x12}, + {0x5e1d, 0x12}, + {0x5e1e, 0x14}, + {0x5e1f, 0x15}, + {0x5e20, 0x16}, + {0x5e21, 0x17}, + {0x5e22, 0x00}, + {0x5e23, 0x08}, + {0x5e26, 0x00}, + {0x5e27, 0x00}, + {0x5e29, 0x00}, + {0x5e2a, 0x00}, + {0x5e2c, 0x00}, + {0x5e2d, 0x00}, + {0x5e2f, 0x03}, + {0x5e30, 0xff}, + {0x5e32, 0x04}, + {0x5e33, 0x00}, + {0x5e34, 0x00}, + {0x5e35, 0x04}, + {0x5e36, 0x00}, + {0x5e37, 0x00}, + {0x5e38, 0x04}, + {0x5e39, 0x00}, + {0x5e3a, 0x00}, + {0x5e3b, 0x04}, + {0x5e3c, 0x00}, + {0x5e3d, 0x00}, + {0x5e3e, 0x04}, + {0x5e3f, 0x00}, + {0x5e40, 0x00}, + {0x5e41, 0x06}, + {0x5e42, 0x00}, + {0x5e43, 0x00}, + {0x5e44, 0x06}, + {0x5e45, 0x00}, + {0x5e46, 0x00}, + {0x5e47, 0x06}, + {0x5e48, 0x00}, + {0x5e49, 0x00}, + {0x5e4a, 0x06}, + {0x5e4b, 0x00}, + {0x5e4c, 0x00}, + {0x5e4d, 0x06}, + {0x5e4e, 0x00}, + {0x5e50, 0x06}, + {0x5e51, 0x00}, + {0x5e53, 0x06}, + {0x5e54, 0x00}, + {0x5e56, 0x08}, + {0x5e57, 0x00}, + {0x5e59, 0x08}, + {0x5e5a, 0x00}, + {0x5e5c, 0x08}, + {0x5e5d, 0x00}, + {0x5e5f, 0x08}, + {0x5e60, 0x00}, + {0x5e62, 0x08}, + {0x5e63, 0x00}, + {0x5e65, 0x08}, + {0x5e66, 0x00}, + {0x5e68, 0x08}, + {0x5e69, 0x00}, + {0x5e6b, 0x16}, + {0x5e6c, 0x00}, + {0x5e6e, 0x20}, + {0x5e6f, 0x00}, + {0x5e71, 0x18}, + {0x5e72, 0x00}, + {0x5e74, 0x18}, + {0x5e75, 0x00}, + {0x5e77, 0x17}, + {0x5e78, 0xff}, + {0x5e7a, 0x00}, + {0x5e7b, 0x00}, + {0x5e7d, 0x00}, + {0x5e7e, 0x00}, + {0x5e80, 0x00}, + {0x5e81, 0x00}, + {0x5e83, 0x00}, + {0x5e84, 0x00}, + {0x5f00, 0x02}, + {0x5f01, 0x08}, + {0x5f02, 0x09}, + {0x5f03, 0x0a}, + {0x5f04, 0x0b}, + {0x5f05, 0x0c}, + {0x5f06, 0x0c}, + {0x5f07, 0x0c}, + {0x5f08, 0x0c}, + {0x5f09, 0x0c}, + {0x5f0a, 0x0d}, + {0x5f0b, 0x0d}, + {0x5f0c, 0x0d}, + {0x5f0d, 0x0d}, + {0x5f0e, 0x0d}, + {0x5f0f, 0x0e}, + {0x5f10, 0x0e}, + {0x5f11, 0x0e}, + {0x5f12, 0x0e}, + {0x5f13, 0x0f}, + {0x5f14, 0x0f}, + {0x5f15, 0x10}, + {0x5f16, 0x11}, + {0x5f17, 0x11}, + {0x5f18, 0x12}, + {0x5f19, 0x12}, + {0x5f1a, 0x13}, + {0x5f1b, 0x13}, + {0x5f1c, 0x14}, + {0x5f1d, 0x14}, + {0x5f1e, 0x16}, + {0x5f1f, 0x16}, + {0x5f20, 0x16}, + {0x5f21, 0x08}, + {0x5f22, 0x00}, + {0x5f23, 0x01}, + {0x5f26, 0x02}, + {0x5f27, 0x00}, + {0x5f29, 0x02}, + {0x5f2a, 0x00}, + {0x5f2c, 0x02}, + {0x5f2d, 0x00}, + {0x5f2f, 0x02}, + {0x5f30, 0x00}, + {0x5f32, 0x02}, + {0x5f33, 0x00}, + {0x5f34, 0x00}, + {0x5f35, 0x02}, + {0x5f36, 0x00}, + {0x5f37, 0x00}, + {0x5f38, 0x02}, + {0x5f39, 0x00}, + {0x5f3a, 0x00}, + {0x5f3b, 0x02}, + {0x5f3c, 0x00}, + {0x5f3d, 0x00}, + {0x5f3e, 0x02}, + {0x5f3f, 0x00}, + {0x5f40, 0x00}, + {0x5f41, 0x02}, + {0x5f42, 0x00}, + {0x5f43, 0x00}, + {0x5f44, 0x02}, + {0x5f45, 0x00}, + {0x5f46, 0x00}, + {0x5f47, 0x04}, + {0x5f48, 0x00}, + {0x5f49, 0x00}, + {0x5f4a, 0x04}, + {0x5f4b, 0x00}, + {0x5f4c, 0x00}, + {0x5f4d, 0x04}, + {0x5f4e, 0x00}, + {0x5f50, 0x04}, + {0x5f51, 0x00}, + {0x5f53, 0x04}, + {0x5f54, 0x00}, + {0x5f56, 0x04}, + {0x5f57, 0x00}, + {0x5f59, 0x04}, + {0x5f5a, 0x00}, + {0x5f5c, 0x04}, + {0x5f5d, 0x00}, + {0x5f5f, 0x08}, + {0x5f60, 0x00}, + {0x5f62, 0x08}, + {0x5f63, 0x00}, + {0x5f65, 0x08}, + {0x5f66, 0x00}, + {0x5f68, 0x08}, + {0x5f69, 0x00}, + {0x5f6b, 0x08}, + {0x5f6c, 0x00}, + {0x5f6e, 0x10}, + {0x5f6f, 0x00}, + {0x5f71, 0x10}, + {0x5f72, 0x00}, + {0x5f74, 0x10}, + {0x5f75, 0x00}, + {0x5f77, 0x10}, + {0x5f78, 0x00}, + {0x5f7a, 0x20}, + {0x5f7b, 0x00}, + {0x5f7d, 0x20}, + {0x5f7e, 0x00}, + {0x5f80, 0x20}, + {0x5f81, 0x00}, + {0x5f83, 0x00}, + {0x5f84, 0xff}, + {0x5240, 0x0f}, + {0x5243, 0x00}, + {0x5244, 0x00}, + {0x5245, 0x00}, + {0x5246, 0x00}, + {0x5247, 0x00}, + {0x5248, 0x00}, + {0x5249, 0x00}, + {0x5440, 0x0f}, + {0x5443, 0x00}, + {0x5445, 0x00}, + {0x5447, 0x00}, + {0x5448, 0x00}, + {0x5449, 0x00}, + {0x5640, 0x0f}, + {0x5642, 0x00}, + {0x5643, 0x00}, + {0x5644, 0x00}, + {0x5645, 0x00}, + {0x5646, 0x00}, + {0x5647, 0x00}, + {0x5649, 0x00}, + {0x5840, 0x0f}, + {0x5842, 0x00}, + {0x5843, 0x00}, + {0x5845, 0x00}, + {0x5846, 0x00}, + {0x5847, 0x00}, + {0x5848, 0x00}, + {0x5849, 0x00}, + {0x4001, 0x2b}, + {0x4008, 0x02}, + {0x4009, 0x03}, + {0x4018, 0x12}, + {0x4022, 0x40}, + {0x4023, 0x20}, + {0x4026, 0x00}, + {0x4027, 0x40}, + {0x4028, 0x00}, + {0x4029, 0x40}, + {0x402a, 0x00}, + {0x402b, 0x40}, + {0x402c, 0x00}, + {0x402d, 0x40}, + {0x405e, 0x00}, + {0x405f, 0x00}, + {0x4060, 0x00}, + {0x4061, 0x00}, + {0x4062, 0x00}, + {0x4063, 0x00}, + {0x4064, 0x00}, + {0x4065, 0x00}, + {0x4066, 0x00}, + {0x4067, 0x00}, + {0x4068, 0x00}, + {0x4069, 0x00}, + {0x406a, 0x00}, + {0x406b, 0x00}, + {0x406c, 0x00}, + {0x406d, 0x00}, + {0x406e, 0x00}, + {0x406f, 0x00}, + {0x4070, 0x00}, + {0x4071, 0x00}, + {0x4072, 0x00}, + {0x4073, 0x00}, + {0x4074, 0x00}, + {0x4075, 0x00}, + {0x4076, 0x00}, + {0x4077, 0x00}, + {0x4078, 0x00}, + {0x4079, 0x00}, + {0x407a, 0x00}, + {0x407b, 0x00}, + {0x407c, 0x00}, + {0x407d, 0x00}, + {0x407e, 0xcc}, + {0x407f, 0x18}, + {0x4080, 0xff}, + {0x4081, 0xff}, + {0x4082, 0x01}, + {0x4083, 0x53}, + {0x4084, 0x01}, + {0x4085, 0x2b}, + {0x4086, 0x00}, + {0x4087, 0xb3}, + {0x4640, 0x40}, + {0x4641, 0x11}, + {0x4642, 0x0e}, + {0x4643, 0xee}, + {0x4646, 0x0f}, + {0x4648, 0x00}, + {0x4649, 0x03}, + {0x4f04, 0xf8}, + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + {0x5003, 0x7a}, + {0x5b80, 0x08}, + {0x5c00, 0x08}, + {0x5c80, 0x00}, + {0x5bbe, 0x12}, + {0x5c3e, 0x12}, + {0x5cbe, 0x12}, + {0x5b8a, 0x80}, + {0x5b8b, 0x80}, + {0x5b8c, 0x80}, + {0x5b8d, 0x80}, + {0x5b8e, 0x60}, + {0x5b8f, 0x80}, + {0x5b90, 0x80}, + {0x5b91, 0x80}, + {0x5b92, 0x80}, + {0x5b93, 0x20}, + {0x5b94, 0x80}, + {0x5b95, 0x80}, + {0x5b96, 0x80}, + {0x5b97, 0x20}, + {0x5b98, 0x00}, + {0x5b99, 0x80}, + {0x5b9a, 0x40}, + {0x5b9b, 0x20}, + {0x5b9c, 0x00}, + {0x5b9d, 0x00}, + {0x5b9e, 0x80}, + {0x5b9f, 0x00}, + {0x5ba0, 0x00}, + {0x5ba1, 0x00}, + {0x5ba2, 0x00}, + {0x5ba3, 0x00}, + {0x5ba4, 0x00}, + {0x5ba5, 0x00}, + {0x5ba6, 0x00}, + {0x5ba7, 0x00}, + {0x5ba8, 0x02}, + {0x5ba9, 0x00}, + {0x5baa, 0x02}, + {0x5bab, 0x76}, + {0x5bac, 0x03}, + {0x5bad, 0x08}, + {0x5bae, 0x00}, + {0x5baf, 0x80}, + {0x5bb0, 0x00}, + {0x5bb1, 0xc0}, + {0x5bb2, 0x01}, + {0x5bb3, 0x00}, + {0x5c0a, 0x80}, + {0x5c0b, 0x80}, + {0x5c0c, 0x80}, + {0x5c0d, 0x80}, + {0x5c0e, 0x60}, + {0x5c0f, 0x80}, + {0x5c10, 0x80}, + {0x5c11, 0x80}, + {0x5c12, 0x60}, + {0x5c13, 0x20}, + {0x5c14, 0x80}, + {0x5c15, 0x80}, + {0x5c16, 0x80}, + {0x5c17, 0x20}, + {0x5c18, 0x00}, + {0x5c19, 0x80}, + {0x5c1a, 0x40}, + {0x5c1b, 0x20}, + {0x5c1c, 0x00}, + {0x5c1d, 0x00}, + {0x5c1e, 0x80}, + {0x5c1f, 0x00}, + {0x5c20, 0x00}, + {0x5c21, 0x00}, + {0x5c22, 0x00}, + {0x5c23, 0x00}, + {0x5c24, 0x00}, + {0x5c25, 0x00}, + {0x5c26, 0x00}, + {0x5c27, 0x00}, + {0x5c28, 0x02}, + {0x5c29, 0x00}, + {0x5c2a, 0x02}, + {0x5c2b, 0x76}, + {0x5c2c, 0x03}, + {0x5c2d, 0x08}, + {0x5c2e, 0x00}, + {0x5c2f, 0x80}, + {0x5c30, 0x00}, + {0x5c31, 0xc0}, + {0x5c32, 0x01}, + {0x5c33, 0x00}, + {0x5c8a, 0x80}, + {0x5c8b, 0x80}, + {0x5c8c, 0x80}, + {0x5c8d, 0x80}, + {0x5c8e, 0x80}, + {0x5c8f, 0x80}, + {0x5c90, 0x80}, + {0x5c91, 0x80}, + {0x5c92, 0x80}, + {0x5c93, 0x60}, + {0x5c94, 0x80}, + {0x5c95, 0x80}, + {0x5c96, 0x80}, + {0x5c97, 0x60}, + {0x5c98, 0x40}, + {0x5c99, 0x80}, + {0x5c9a, 0x80}, + {0x5c9b, 0x80}, + {0x5c9c, 0x40}, + {0x5c9d, 0x00}, + {0x5c9e, 0x80}, + {0x5c9f, 0x80}, + {0x5ca0, 0x80}, + {0x5ca1, 0x20}, + {0x5ca2, 0x00}, + {0x5ca3, 0x80}, + {0x5ca4, 0x80}, + {0x5ca5, 0x00}, + {0x5ca6, 0x00}, + {0x5ca7, 0x00}, + {0x5ca8, 0x01}, + {0x5ca9, 0x00}, + {0x5caa, 0x02}, + {0x5cab, 0x00}, + {0x5cac, 0x03}, + {0x5cad, 0x08}, + {0x5cae, 0x01}, + {0x5caf, 0x00}, + {0x5cb0, 0x02}, + {0x5cb1, 0x00}, + {0x5cb2, 0x03}, + {0x5cb3, 0x08}, + {0x5be7, 0x80}, + {0x5bc9, 0x80}, + {0x5bca, 0x80}, + {0x5bcb, 0x80}, + {0x5bcc, 0x80}, + {0x5bcd, 0x80}, + {0x5bce, 0x80}, + {0x5bcf, 0x80}, + {0x5bd0, 0x80}, + {0x5bd1, 0x80}, + {0x5bd2, 0x20}, + {0x5bd3, 0x80}, + {0x5bd4, 0x40}, + {0x5bd5, 0x20}, + {0x5bd6, 0x00}, + {0x5bd7, 0x00}, + {0x5bd8, 0x00}, + {0x5bd9, 0x00}, + {0x5bda, 0x00}, + {0x5bdb, 0x00}, + {0x5bdc, 0x00}, + {0x5bdd, 0x00}, + {0x5bde, 0x00}, + {0x5bdf, 0x00}, + {0x5be0, 0x00}, + {0x5be1, 0x00}, + {0x5be2, 0x00}, + {0x5be3, 0x00}, + {0x5be4, 0x00}, + {0x5be5, 0x00}, + {0x5be6, 0x00}, + {0x5c49, 0x80}, + {0x5c4a, 0x80}, + {0x5c4b, 0x80}, + {0x5c4c, 0x80}, + {0x5c4d, 0x40}, + {0x5c4e, 0x80}, + {0x5c4f, 0x80}, + {0x5c50, 0x80}, + {0x5c51, 0x60}, + {0x5c52, 0x20}, + {0x5c53, 0x80}, + {0x5c54, 0x80}, + {0x5c55, 0x80}, + {0x5c56, 0x20}, + {0x5c57, 0x00}, + {0x5c58, 0x80}, + {0x5c59, 0x40}, + {0x5c5a, 0x20}, + {0x5c5b, 0x00}, + {0x5c5c, 0x00}, + {0x5c5d, 0x80}, + {0x5c5e, 0x00}, + {0x5c5f, 0x00}, + {0x5c60, 0x00}, + {0x5c61, 0x00}, + {0x5c62, 0x00}, + {0x5c63, 0x00}, + {0x5c64, 0x00}, + {0x5c65, 0x00}, + {0x5c66, 0x00}, + {0x5cc9, 0x80}, + {0x5cca, 0x80}, + {0x5ccb, 0x80}, + {0x5ccc, 0x80}, + {0x5ccd, 0x80}, + {0x5cce, 0x80}, + {0x5ccf, 0x80}, + {0x5cd0, 0x80}, + {0x5cd1, 0x80}, + {0x5cd2, 0x60}, + {0x5cd3, 0x80}, + {0x5cd4, 0x80}, + {0x5cd5, 0x80}, + {0x5cd6, 0x60}, + {0x5cd7, 0x40}, + {0x5cd8, 0x80}, + {0x5cd9, 0x80}, + {0x5cda, 0x80}, + {0x5cdb, 0x40}, + {0x5cdc, 0x20}, + {0x5cdd, 0x80}, + {0x5cde, 0x80}, + {0x5cdf, 0x80}, + {0x5ce0, 0x20}, + {0x5ce1, 0x00}, + {0x5ce2, 0x80}, + {0x5ce3, 0x80}, + {0x5ce4, 0x80}, + {0x5ce5, 0x00}, + {0x5ce6, 0x00}, + {0x5d74, 0x01}, + {0x5d75, 0x00}, + {0x5d1f, 0x81}, + {0x5d11, 0x00}, + {0x5d12, 0x10}, + {0x5d13, 0x10}, + {0x5d15, 0x05}, + {0x5d16, 0x05}, + {0x5d17, 0x05}, + {0x5d08, 0x03}, + {0x5d09, 0xb6}, + {0x5d0a, 0x03}, + {0x5d0b, 0xb6}, + {0x5d18, 0x03}, + {0x5d19, 0xb6}, + {0x5d62, 0x01}, + {0x5d40, 0x02}, + {0x5d41, 0x01}, + {0x5d63, 0x1f}, + {0x5d64, 0x00}, + {0x5d65, 0x80}, + {0x5d56, 0x00}, + {0x5d57, 0x20}, + {0x5d58, 0x00}, + {0x5d59, 0x20}, + {0x5d5a, 0x00}, + {0x5d5b, 0x0c}, + {0x5d5c, 0x02}, + {0x5d5d, 0x40}, + {0x5d5e, 0x02}, + {0x5d5f, 0x40}, + {0x5d60, 0x03}, + {0x5d61, 0x40}, + {0x5d4a, 0x02}, + {0x5d4b, 0x40}, + {0x5d4c, 0x02}, + {0x5d4d, 0x40}, + {0x5d4e, 0x02}, + {0x5d4f, 0x40}, + {0x5d50, 0x18}, + {0x5d51, 0x80}, + {0x5d52, 0x18}, + {0x5d53, 0x80}, + {0x5d54, 0x18}, + {0x5d55, 0x80}, + {0x5d46, 0x20}, + {0x5d47, 0x00}, + {0x5d48, 0x22}, + {0x5d49, 0x00}, + {0x5d42, 0x20}, + {0x5d43, 0x00}, + {0x5d44, 0x22}, + {0x5d45, 0x00}, + {0x5004, 0x1e}, + {0x4221, 0x03}, + {0x380e, 0x02}, + {0x380f, 0xae}, + {0x380c, 0x04}, + {0x380d, 0x47}, + {0x384c, 0x02}, + {0x384d, 0x0d}, + {0x388c, 0x02}, + {0x388d, 0x2b}, + {0x420e, 0x54}, + {0x420f, 0xa0}, + {0x4210, 0xca}, + {0x4211, 0xf2}, + {0x507a, 0x5f}, + {0x507b, 0x46}, + {0x3802, 0x00}, + {0x3803, 0x68}, + {0x3806, 0x04}, + {0x3807, 0xa7}, + {0x380a, 0x04}, + {0x380b, 0x38}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x380c, 0x08}, + {0x380d, 0x8e}, + {0x384c, 0x04}, + {0x384d, 0x1a}, + {0x388c, 0x04}, + {0x388d, 0x56}, + {0x0304, 0x00}, + {0x0305, 0xf9}, + {0x4837, 0x10}, + {0x0408, 0x78}, + {0x0409, 0x00}, + {0x040a, 0xd1}, + {0x040b, 0x1e}, + {0x040c, 0x2e}, + {0x040d, 0x44}, + {0x040e, 0x0c}, + + {0x4221, 0x05}, + {0x5002, 0x3f}, + {0x5003, 0x2a}, + {0x502c, 0x0f}, + {0x504b, 0x04}, + {0x5053, 0x03}, + {0x505b, 0x02}, + {0x5063, 0x01}, + {0x5074, 0x59}, + {0x4319, 0x43}, + {0x431a, 0x01}, + {REG_NULL, 0xff}, }; @@ -3890,6 +4946,25 @@ static struct rkmodule_hdr_compr ox03c10_hdr_compr_16 = { }; static const struct ox03c10_mode supported_modes[] = { + { + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 1920, + .height = 1080, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x0200, + .hts_def = 0x10fe, + .vts_def = 0x02ae * 2, + .reg_list = ox03c10_1920x1080_30fps_linear_raw10_mipi996, + .hdr_mode = NO_HDR, + .hdr_compr = NULL, + .bpp = 10, + .mipi_freq_idx = 1, + .vc[PAD0] = 0, + .exp_mode = EXP_NORMAL, + }, { .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12, .width = 1920, @@ -3898,9 +4973,9 @@ static const struct ox03c10_mode supported_modes[] = { .numerator = 10000, .denominator = 300000, }, - .exp_def = 0x0038, + .exp_def = 0x0200, .hts_def = 0x10fe, - .vts_def = 0x0337 * 2, + .vts_def = 0x02ae * 2, .reg_list = ox03c10_1920x1080_30fps_HDR3_VS_PWL12_mipi600, .hdr_mode = HDR_COMPR, .hdr_compr = &ox03c10_hdr_compr_12, @@ -3918,7 +4993,7 @@ static const struct ox03c10_mode supported_modes[] = { .numerator = 10000, .denominator = 300000, }, - .exp_def = 0x0038, + .exp_def = 0x0200, .hts_def = 0x10FE, .vts_def = 0x02AE * 2, .reg_list = ox03c10_1920x1080_30fps_HDR3_LFM_PWL16_mipi996, @@ -3928,7 +5003,10 @@ static const struct ox03c10_mode supported_modes[] = { .mipi_freq_idx = 1, .hdr_operating_mode = OX03C10_HDR3_DCG_VS_LFM_16BIT, .vc[PAD0] = 0, - .exp_mode = EXP_HDR3_DCG_SPD, + .vc[PAD1] = 1, + .vc[PAD2] = 2, + .vc[PAD3] = 3, + .exp_mode = EXP_HDR3_DCG_VS, }, { .bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12, @@ -3938,16 +5016,17 @@ static const struct ox03c10_mode supported_modes[] = { .numerator = 10000, .denominator = 300000, }, - .exp_def = 0x0038, + .exp_def = 0x0200, .hts_def = 0x10fe, - .vts_def = 0x0337, + .vts_def = 0x02ae * 2, .reg_list = ox03c10_1920x1080_30fps_HDR3_SPD_PWL12_mipi600, .hdr_mode = NO_HDR, .hdr_compr = &ox03c10_hdr_compr_12, .bpp = 12, - .mipi_freq_idx = 5, + .mipi_freq_idx = 0, .hdr_operating_mode = OX03C10_HDR3_DCG_SPD_12BIT, .vc[PAD0] = 0, + .exp_mode = EXP_HDR3_DCG_SPD, }, }; @@ -4117,9 +5196,9 @@ static int ox03c10_set_fmt(struct v4l2_subdev *sd, h_blank = mode->hts_def - mode->width; __v4l2_ctrl_modify_range(ox03c10->hblank, h_blank, h_blank, 1, h_blank); - vblank_def = mode->vts_def - mode->height / 2; - __v4l2_ctrl_modify_range(ox03c10->vblank, 46, - mode->height, + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(ox03c10->vblank, vblank_def, + OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, vblank_def); } @@ -4182,9 +5261,6 @@ static int ox03c10_enum_frame_sizes(struct v4l2_subdev *sd, if (fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_SBGGR12_1X12) - return -EINVAL; - fse->min_width = supported_modes[fse->index].width; fse->max_width = supported_modes[fse->index].width; fse->max_height = supported_modes[fse->index].height; @@ -4265,21 +5341,64 @@ static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, l_exp = 4; if (s_exp < 1) s_exp = 1; - if (s_exp > 35) + if (s_exp > 35 && ox03c10->cur_mode->exp_mode == EXP_HDR3_DCG_VS) s_exp = 35; - if (l_again > 248) { - l_dgain = l_again * 1024 / 248; + + if (l_again < 16) { + l_again = 16; + } else if (l_again <= 31) { + } else if (l_again <= 47) { + l_again = (l_again - 16) << 1; + } else if (l_again <= 63) { + l_again = (l_again - 32) << 2; + } else if (l_again <= 95) { + l_again = (l_again - 48) << 3; + } else if (l_again >= 248) { + l_dgain = div_u64(l_again * 1024, 248); l_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set l_gain val:0x%x not support", + __func__, l_again); + return -EINVAL; } - if (m_again > 248) { - m_dgain = m_again * 1024 / 248; + if (m_again < 16) { + m_again = 16; + } else if (m_again <= 31) { + } else if (m_again <= 47) { + m_again = (m_again - 16) << 1; + } else if (m_again <= 63) { + m_again = (m_again - 32) << 2; + } else if (m_again <= 95) { + m_again = (m_again - 48) << 3; + } else if (m_again >= 248) { + m_dgain = div_u64(m_again * 1024, 248); m_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set m_gain val:0x%x not support", + __func__, m_again); + return -EINVAL; } - if (s_again > 248) { - s_dgain = s_again * 1024 / 248; + if (s_again < 16) { + s_again = 16; + } else if (s_again <= 31) { + } else if (s_again <= 47) { + s_again = (s_again - 16) << 1; + } else if (s_again <= 63) { + s_again = (s_again - 32) << 2; + } else if (s_again <= 95) { + s_again = (s_again - 48) << 3; + } else if (s_again >= 248) { + s_dgain = div_u64(s_again * 1024, 248); s_again = 248; + } else { + dev_err(&ox03c10->client->dev, "%s set s_gain val:0x%x not support", + __func__, s_again); + return -EINVAL; } + dev_dbg(&ox03c10->client->dev, + "l_again 0x%x l_dgain 0x%x, m_again 0x%x m_dgain 0x%x, s_again 0x%x s_dgain 0x%x\n", + l_again, l_dgain, m_again, m_dgain, s_again, s_dgain); ret |= ox03c10_write_reg(ox03c10->client, OX03C10_GROUP_UPDATE_ADDRESS, OX03C10_REG_VALUE_08BIT, OX03C10_GROUP_UPDATE_START_DATA); @@ -4304,7 +5423,7 @@ static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_HCG_M, OX03C10_REG_VALUE_08BIT, - (l_dgain >> 8) & 0xff); + (l_dgain >> 2) & 0xff); ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_HCG_L, OX03C10_REG_VALUE_08BIT, @@ -4326,7 +5445,7 @@ static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_LCG_M, OX03C10_REG_VALUE_08BIT, - (m_dgain >> 8) & 0xff); + (m_dgain >> 2) & 0xff); ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_LCG_L, OX03C10_REG_VALUE_08BIT, @@ -4354,7 +5473,7 @@ static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_VS_M, OX03C10_REG_VALUE_08BIT, - (s_dgain >> 8) & 0xff); + (s_dgain >> 2) & 0xff); ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_VS_L, OX03C10_REG_VALUE_08BIT, @@ -4381,7 +5500,7 @@ static int ox03c10_set_hdrae(struct ox03c10 *ox03c10, ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_SPD_M, OX03C10_REG_VALUE_08BIT, - (s_dgain >> 8) & 0xff); + (s_dgain >> 2) & 0xff); ret |= ox03c10_write_reg(ox03c10->client, OX03C10_REG_DGAIN_SPD_L, OX03C10_REG_VALUE_08BIT, @@ -4417,8 +5536,8 @@ static int ox03c10_get_dcg_and_spd_ratio(struct ox03c10 *ox03c10) dev_err(dev, "get dcg ratio fail, ret %d, dcg ratio %d, %d\n", ret, ox03c10->dcg_ratio.integer, ox03c10->dcg_ratio.decimal); else - dev_info(dev, "get dcg ratio reg val %d, %d\n", - ox03c10->dcg_ratio.integer, ox03c10->dcg_ratio.decimal); + dev_info(dev, "get dcg ratio reg val integer %d, dec 0x%x, div 0x%x\n", + ox03c10->dcg_ratio.integer, ox03c10->dcg_ratio.decimal, ox03c10->dcg_ratio.div_coeff); ox03c10->spd_ratio.integer = 0; ox03c10->spd_ratio.decimal = val & 0x1ffff; @@ -4429,8 +5548,8 @@ static int ox03c10_get_dcg_and_spd_ratio(struct ox03c10 *ox03c10) dev_err(dev, "get spd ratio fail, ret %d, spd ratio %d, %d\n", ret, ox03c10->spd_ratio.integer, ox03c10->spd_ratio.decimal); else - dev_info(dev, "get spd ratio reg val %d, %d\n", - ox03c10->spd_ratio.integer, ox03c10->spd_ratio.decimal); + dev_info(dev, "get spd ratio reg val integer %d, dec 0x%x div 0x%x\n", + ox03c10->spd_ratio.integer, ox03c10->spd_ratio.decimal, ox03c10->spd_ratio.div_coeff); ox03c10_write_reg(ox03c10->client, OX03C10_REG_CTRL_MODE, OX03C10_REG_VALUE_08BIT, OX03C10_MODE_SW_STANDBY); @@ -4448,6 +5567,12 @@ static int ox03c10_set_wb_gain(struct ox03c10 *ox03c10, u32 bgain, gbgain, grgain, rgain; #endif + if (!ox03c10->has_init_wbgain && !ox03c10->streaming) { + ox03c10->init_wbgain = *wb_gain_group; + ox03c10->has_init_wbgain = true; + dev_dbg(&ox03c10->client->dev, "ox03c10 don't stream, record wbgain!\n"); + return ret; + } for (i = 0; i < wb_gain_group->group_num; i++) { switch (wb_gain_group->wb_gain_type[i]) { case RKMODULE_HCG_WB_GAIN: @@ -4581,7 +5706,7 @@ static int ox03c10_select_exp_mode(struct ox03c10 *ox03c10, u32 exp_mode) supported_modes[i].exp_mode == exp_mode) { ox03c10->cur_mode = &supported_modes[i]; w = ox03c10->cur_mode->hts_def - ox03c10->cur_mode->width; - h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height / 2; + h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height; __v4l2_ctrl_modify_range(ox03c10->hblank, w, w, 1, w); __v4l2_ctrl_modify_range(ox03c10->vblank, h, OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, h); @@ -4592,6 +5717,53 @@ static int ox03c10_select_exp_mode(struct ox03c10 *ox03c10, u32 exp_mode) return ret; } +static int ox03c10_select_cmps_mode(struct ox03c10 *ox03c10, u32 cmps_mode) +{ + int ret = -EINVAL; + u32 i, h, w, hdr_mode, exp_mode; + int best_fit = -1; + int bit_width = 0; + + w = ox03c10->cur_mode->width; + h = ox03c10->cur_mode->height; + hdr_mode = ox03c10->cur_mode->hdr_mode; + exp_mode = ox03c10->cur_mode->exp_mode; + for (i = 0; i < ARRAY_SIZE(supported_modes); i++) { + if (w == supported_modes[i].width && + h == supported_modes[i].height && + supported_modes[i].hdr_mode == hdr_mode && + supported_modes[i].exp_mode == exp_mode) { + if (cmps_mode == CMPS_LOW_BIT_WIDTH_MODE) { + if (bit_width == 0) { + bit_width = supported_modes[i].bpp; + best_fit = i; + } else if (supported_modes[i].bpp < bit_width) { + bit_width = supported_modes[i].bpp; + best_fit = i; + } + } else { + if (bit_width == 0) { + bit_width = supported_modes[i].bpp; + best_fit = i; + } else if (supported_modes[i].bpp > bit_width) { + bit_width = supported_modes[i].bpp; + best_fit = i; + } + } + } + } + if (best_fit >= 0) { + ox03c10->cur_mode = &supported_modes[i]; + w = ox03c10->cur_mode->hts_def - ox03c10->cur_mode->width; + h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height; + __v4l2_ctrl_modify_range(ox03c10->hblank, w, w, 1, w); + __v4l2_ctrl_modify_range(ox03c10->vblank, h, + OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, h); + ret = 0; + } + return ret; +} + static long ox03c10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct ox03c10 *ox03c10 = to_ox03c10(sd); @@ -4604,6 +5776,8 @@ static long ox03c10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) long ret = 0; u32 stream = 0; u32 *exp_mode; + struct rkmodule_wb_gain_info *wb_gain_info; + struct rkmodule_blc_info *blc_info; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -4637,7 +5811,7 @@ static long ox03c10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) ret = -EINVAL; } else { w = ox03c10->cur_mode->hts_def - ox03c10->cur_mode->width; - h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height / 2; + h = ox03c10->cur_mode->vts_def - ox03c10->cur_mode->height; __v4l2_ctrl_modify_range(ox03c10->hblank, w, w, 1, w); __v4l2_ctrl_modify_range(ox03c10->vblank, h, OX03C10_VTS_MAX - ox03c10->cur_mode->height, 1, h); @@ -4684,6 +5858,18 @@ static long ox03c10_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKMODULE_SET_EXP_MODE: ret = ox03c10_select_exp_mode(ox03c10, *(u32 *)arg); break; + case RKMODULE_GET_WB_GAIN_INFO: + wb_gain_info = (struct rkmodule_wb_gain_info *)arg; + wb_gain_info->coarse_bit = 5; + wb_gain_info->fine_bit = 10; + break; + case RKMODULE_GET_BLC_INFO: + blc_info = (struct rkmodule_blc_info *)arg; + blc_info->bit_width = 10; + break; + case RKMODULE_SET_CMPS_MODE: + ret = ox03c10_select_cmps_mode(ox03c10, *(u32 *)arg); + break; default: ret = -ENOIOCTLCMD; break; @@ -4708,6 +5894,9 @@ static long ox03c10_compat_ioctl32(struct v4l2_subdev *sd, long ret; u32 stream = 0; u32 exp_mode; + struct rkmodule_wb_gain_info *wb_gain_info; + struct rkmodule_blc_info *blc_info; + u32 cmps_mode; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -4877,6 +6066,43 @@ static long ox03c10_compat_ioctl32(struct v4l2_subdev *sd, return -EFAULT; ret = ox03c10_ioctl(sd, cmd, &exp_mode); break; + case RKMODULE_GET_WB_GAIN_INFO: + wb_gain_info = kzalloc(sizeof(*wb_gain_info), GFP_KERNEL); + if (!wb_gain_info) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, wb_gain_info); + if (!ret) { + if (copy_to_user(up, wb_gain_info, sizeof(*wb_gain_info))) { + kfree(wb_gain_info); + return -EFAULT; + } + } + kfree(wb_gain_info); + break; + case RKMODULE_GET_BLC_INFO: + blc_info = kzalloc(sizeof(*blc_info), GFP_KERNEL); + if (!blc_info) { + ret = -ENOMEM; + return ret; + } + + ret = ox03c10_ioctl(sd, cmd, blc_info); + if (!ret) { + if (copy_to_user(up, blc_info, sizeof(*blc_info))) { + kfree(blc_info); + return -EFAULT; + } + } + kfree(blc_info); + break; + case RKMODULE_SET_CMPS_MODE: + if (copy_from_user(&cmps_mode, up, sizeof(u32))) + return -EFAULT; + ret = ox03c10_ioctl(sd, cmd, &cmps_mode); + break; default: ret = -ENOIOCTLCMD; break; @@ -4908,6 +6134,16 @@ static int __ox03c10_start_stream(struct ox03c10 *ox03c10) return ret; } } + if (ox03c10->has_init_wbgain) { + ret = ox03c10_ioctl(&ox03c10->subdev, + RKMODULE_SET_WB_GAIN, + &ox03c10->init_wbgain); + if (ret) { + dev_err(&ox03c10->client->dev, + "init wbgain fail\n"); + return ret; + } + } return ox03c10_write_reg(ox03c10->client, OX03C10_REG_CTRL_MODE, OX03C10_REG_VALUE_08BIT, OX03C10_MODE_STREAMING); @@ -4916,6 +6152,7 @@ static int __ox03c10_start_stream(struct ox03c10 *ox03c10) static int __ox03c10_stop_stream(struct ox03c10 *ox03c10) { ox03c10->has_init_exp = false; + ox03c10->has_init_wbgain = false; return ox03c10_write_reg(ox03c10->client, OX03C10_REG_CTRL_MODE, OX03C10_REG_VALUE_08BIT, OX03C10_MODE_SW_STANDBY); } @@ -5169,7 +6406,7 @@ static int ox03c10_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - exposure_max = ox03c10->cur_mode->height + ctrl->val - 12; + exposure_max = (ox03c10->cur_mode->height + ctrl->val) / 2 - 12; __v4l2_ctrl_modify_range(ox03c10->exposure, ox03c10->exposure->minimum, exposure_max, ox03c10->exposure->step, @@ -5201,24 +6438,44 @@ static int ox03c10_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_ANALOGUE_GAIN: if (ox03c10->cur_mode->hdr_mode != NO_HDR) break; + /* + *[1, 1.9375, 16, 0, 1, 16, 31, + * 2, 3.875, 8, -16, 1, 32, 47, + * 4, 7.75, 4, -32, 1, 48, 63, + * 8, 15.5, 2,-48, 1, 64, 95, + * 15.5, 247.9375, 16, 0, 1, 248, 3967] + */ // hcg real gain - again = ctrl->val; - if (again > 248) { - dgain = again * 1024 / 248; + if (ctrl->val < 16) { + again = 16; + } else if (ctrl->val <= 31) { + again = ctrl->val; + } else if (ctrl->val <= 47) { + again = (ctrl->val - 16) << 1; + } else if (ctrl->val <= 63) { + again = (ctrl->val - 32) << 2; + } else if (ctrl->val <= 95) { + again = (ctrl->val - 48) << 3; + } else if (ctrl->val >= 248) { + dgain = div_u64(ctrl->val * 1024, 248); again = 248; + } else { + dev_err(&client->dev, "%s set gain val:0x%x not support", + __func__, ctrl->val); + break; } ret |= ox03c10_write_reg(ox03c10->client, OX03C10_GROUP_UPDATE_ADDRESS, OX03C10_REG_VALUE_08BIT, OX03C10_GROUP1_UPDATE_START_DATA); - // hcg real gain + // lcg real gain ret |= ox03c10_write_reg(ox03c10->client, - OX03C10_REG_AGAIN_HCG_H, + OX03C10_REG_AGAIN_LCG_H, OX03C10_REG_VALUE_16BIT, (again << 4) & 0xff0); - // hcg digital gain + // lcg digital gain ret |= ox03c10_write_reg(ox03c10->client, - OX03C10_REG_DGAIN_HCG_H, + OX03C10_REG_DGAIN_LCG_H, OX03C10_REG_VALUE_24BIT, (dgain << 6) & 0xfffc0); @@ -5323,7 +6580,7 @@ static int ox03c10_initialize_controls(struct ox03c10 *ox03c10) OX03C10_VTS_MAX, 1, vblank_def); - exposure_max = mode->vts_def - 12; + exposure_max = mode->vts_def / 2 - 12; ox03c10->exposure = v4l2_ctrl_new_std(handler, &ox03c10_ctrl_ops, V4L2_CID_EXPOSURE, OX03C10_EXPOSURE_HCG_MIN, exposure_max, OX03C10_EXPOSURE_HCG_STEP, @@ -5352,6 +6609,7 @@ static int ox03c10_initialize_controls(struct ox03c10 *ox03c10) ox03c10->subdev.ctrl_handler = handler; ox03c10->has_init_exp = false; + ox03c10->has_init_wbgain = false; return 0; diff --git a/drivers/media/i2c/ps5458.c b/drivers/media/i2c/ps5458.c index 58f240076bc1..a97bf2118089 100644 --- a/drivers/media/i2c/ps5458.c +++ b/drivers/media/i2c/ps5458.c @@ -2157,7 +2157,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&ps5458_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/rk628/rk628.c b/drivers/media/i2c/rk628/rk628.c index 51d6b4d3f2be..fe43f2ca3c11 100644 --- a/drivers/media/i2c/rk628/rk628.c +++ b/drivers/media/i2c/rk628/rk628.c @@ -739,13 +739,15 @@ void rk628_post_process_en(struct rk628 *rk628, u64 *dst_pclk) { u64 dst_rate, src_rate; - u64 dst_htotal, src_htotal; + u64 dst_htotal, dst_vtotal, src_htotal, src_vtotal; src_rate = src->pixelclock; dst_htotal = dst->hactive + dst->hfront_porch + dst->hsync_len + dst->hback_porch; - dst_rate = src_rate * dst->vactive * dst_htotal; + dst_vtotal = dst->vactive + dst->vfront_porch + dst->vsync_len + dst->vback_porch; + dst_rate = src_rate * dst_vtotal * dst_htotal; src_htotal = src->hactive + src->hfront_porch + src->hsync_len + src->hback_porch; - do_div(dst_rate, (src->vactive * src_htotal)); + src_vtotal = src->vactive + src->vfront_porch + src->vsync_len + src->vback_porch; + do_div(dst_rate, (src_vtotal * src_htotal)); dst->pixelclock = dst_rate; *dst_pclk = dst->pixelclock; diff --git a/drivers/media/i2c/rk628/rk628_hdmirx.c b/drivers/media/i2c/rk628/rk628_hdmirx.c index e7ab841912be..ece94b9ea381 100644 --- a/drivers/media/i2c/rk628/rk628_hdmirx.c +++ b/drivers/media/i2c/rk628/rk628_hdmirx.c @@ -107,6 +107,25 @@ static int supported_fs[] = { -1 }; +static int rk628_hdmirx_write_nolock(struct rk628 *rk628, u32 reg, u32 val) +{ + int region = (reg >> 16) & 0xff; + int ret = 0; + + if (region >= RK628_DEV_MAX) { + dev_err(rk628->dev, + "%s: i2c err: invalid arguments, out of register range\n", __func__); + return -EINVAL; + } + + ret = regmap_write(rk628->regmap[region], reg, val); + if (ret < 0) + dev_err(rk628->dev, + "%s: i2c err reg=0x%x, val=0x%x, ret=%d\n", __func__, reg, val, ret); + + return ret; +} + static int hdcp_load_keys_cb(struct rk628 *rk628, struct rk628_hdcp *hdcp) { int size; @@ -1932,11 +1951,11 @@ void rk628_hdmirx_controller_reset(struct rk628 *rk628) rk628_control_deassert(rk628, RGU_HDMIRX); rk628_control_deassert(rk628, RGU_HDMIRX_PON); usleep_range(20 * 1000, 20 * 1100); + rk628_hdmirx_write_nolock(rk628, HDMI_RX_DMI_SW_RST, 0x000101ff); + rk628_hdmirx_write_nolock(rk628, HDMI_RX_DMI_DISABLE_IF, 0x00000000); + rk628_hdmirx_write_nolock(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0000017f); + rk628_hdmirx_write_nolock(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0001017f); mutex_unlock(&rk628->rst_lock); - rk628_i2c_write(rk628, HDMI_RX_DMI_SW_RST, 0x000101ff); - rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x00000000); - rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0000017f); - rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0001017f); } EXPORT_SYMBOL(rk628_hdmirx_controller_reset); diff --git a/drivers/media/i2c/sc132gs.c b/drivers/media/i2c/sc132gs.c index 9fb5745ccd5d..e2420f5c0eb1 100644 --- a/drivers/media/i2c/sc132gs.c +++ b/drivers/media/i2c/sc132gs.c @@ -50,24 +50,30 @@ #define SC132GS_MODE_SW_STANDBY 0x0 #define SC132GS_MODE_STREAMING BIT(0) -#define SC132GS_REG_EXPOSURE 0x3e01 -#define SC132GS_EXPOSURE_MIN 6 +#define SC132GS_REG_EXPOSURE 0x3e00 +#define SC132GS_EXPOSURE_MIN 1 #define SC132GS_EXPOSURE_STEP 1 #define SC132GS_VTS_MAX 0xffff #define SC132GS_REG_COARSE_AGAIN 0x3e08 #define SC132GS_REG_FINE_AGAIN 0x3e09 +#define SC132GS_REG_COARSE_DGAIN 0x3e06 +#define SC132GS_REG_FINE_DGAIN 0x3e07 + #define ANALOG_GAIN_MIN 0x20 -#define ANALOG_GAIN_MAX 0x391 +#define ANALOG_GAIN_MAX 0x6c80 #define ANALOG_GAIN_STEP 1 #define ANALOG_GAIN_DEFAULT 0x20 #define SC132GS_REG_TEST_PATTERN 0x4501 -#define SC132GS_TEST_PATTERN_ENABLE 0xcc -#define SC132GS_TEST_PATTERN_DISABLE 0xc4 +#define SC132GS_TEST_PATTERN_BIT_MASK BIT(3) #define SC132GS_REG_VTS 0x320e +#define SC132GS_FLIP_REG 0x3221 +#define SC132GS_HFLIP_MASK 0x06 +#define SC132GS_VFLIP_MASK 0x60 + #define REG_NULL 0xFFFF #define SC132GS_REG_VALUE_08BIT 1 @@ -131,6 +137,8 @@ struct sc132gs { struct v4l2_ctrl *test_pattern; struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *h_flip; + struct v4l2_ctrl *v_flip; struct mutex mutex; struct v4l2_fract cur_fps; u32 cur_vts; @@ -141,6 +149,7 @@ struct sc132gs { const char *module_facing; const char *module_name; const char *len_name; + u8 flip; }; #define to_sc132gs(sd) container_of(sd, struct sc132gs, subdev) @@ -285,18 +294,18 @@ static const struct regval sc132gs_2lane_10bit_regs[] = { {0x3018, 0x32}, {0x3019, 0x0c}, {0x301a, 0xb4}, - {0x3031, 0x0a}, + {0x301f, 0x51}, {0x3032, 0x60}, {0x3038, 0x44}, {0x3207, 0x17}, - {0x320c, 0x05}, - {0x320d, 0xdc}, - {0x320e, 0x09}, - {0x320f, 0x60}, + {0x320c, 0x02}, + {0x320d, 0xee}, + {0x320e, 0x05}, + {0x320f, 0x78}, {0x3250, 0xcc}, {0x3251, 0x02}, - {0x3252, 0x09}, - {0x3253, 0x5b}, + {0x3252, 0x05}, + {0x3253, 0x73}, {0x3254, 0x05}, {0x3255, 0x3b}, {0x3306, 0x78}, @@ -331,18 +340,22 @@ static const struct regval sc132gs_2lane_10bit_regs[] = { {0x363b, 0x48}, {0x363c, 0x83}, {0x363d, 0x10}, - {0x36ea, 0x38}, - {0x36fa, 0x25}, - {0x36fb, 0x05}, - {0x36fd, 0x04}, + {0x36ea, 0x36}, + {0x36eb, 0x04}, + {0x36ec, 0x13}, + {0x36ed, 0x24}, + {0x36fa, 0x2b}, + {0x36fb, 0x1b}, + {0x36fc, 0x11}, + {0x36fd, 0x34}, {0x3900, 0x11}, {0x3901, 0x05}, {0x3902, 0xc5}, {0x3904, 0x04}, {0x3908, 0x91}, {0x391e, 0x00}, - {0x3e01, 0x11}, - {0x3e02, 0x20}, + {0x3e01, 0x4e}, + {0x3e02, 0xc0}, {0x3e09, 0x20}, {0x3e0e, 0xd2}, {0x3e14, 0xb0}, @@ -350,7 +363,7 @@ static const struct regval sc132gs_2lane_10bit_regs[] = { {0x3e26, 0x20}, {0x4418, 0x38}, {0x4503, 0x10}, - {0x4837, 0x21}, + {0x4837, 0x35}, {0x5000, 0x0e}, {0x540c, 0x51}, {0x550f, 0x38}, @@ -374,15 +387,15 @@ static const struct regval sc132gs_2lane_10bit_regs[] = { //flip //{0x3221, (0x3 << 5)}, - //mirror - {0x3221, (0x3 << 1)}, - - //flip & mirror - //{0x3221, ((0x3 << 1)|(0x3 << 5))}, //PLL set - {0x36e9, 0x20}, - {0x36f9, 0x24}, + {0x36e9, 0x54}, + {0x36f9, 0x50}, + {0x0100, 0x01}, + + //gain >= 2 + {0x33fa, 0x02}, + {0x3317, 0x14}, {REG_NULL, 0x00}, }; @@ -395,14 +408,14 @@ static const struct sc132gs_mode supported_modes[] = { .numerator = 10000, .denominator = 300000, }, - .exp_def = 0x0148, - .hts_def = 0x06a0, - .vts_def = 0x084a, + .exp_def = 0x04ec, + .hts_def = 0x02ee*2, + .vts_def = 0x0578, .link_freq_index = LINK_FREQ_180M_INDEX, .pixel_rate = PIXEL_RATE_WITH_180M, .reg_list = sc132gs_2lane_10bit_regs, .lanes = 2, - .bus_fmt = MEDIA_BUS_FMT_Y10_1X10, + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, }, { @@ -644,15 +657,19 @@ static int sc132gs_enum_frame_sizes(struct v4l2_subdev *sd, static int sc132gs_enable_test_pattern(struct sc132gs *sc132gs, u32 pattern) { - u32 val; + u32 val = 0; + int ret = 0; + ret = sc132gs_read_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN, + SC132GS_REG_VALUE_08BIT, &val); if (pattern) - val = (pattern - 1) | SC132GS_TEST_PATTERN_ENABLE; + val |= SC132GS_TEST_PATTERN_BIT_MASK; else - val = SC132GS_TEST_PATTERN_DISABLE; + val &= ~SC132GS_TEST_PATTERN_BIT_MASK; - return sc132gs_write_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN, - SC132GS_REG_VALUE_08BIT, val); + ret |= sc132gs_write_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN, + SC132GS_REG_VALUE_08BIT, val); + return ret; } static void sc132gs_get_module_inf(struct sc132gs *sc132gs, @@ -737,50 +754,75 @@ static long sc132gs_compat_ioctl32(struct v4l2_subdev *sd, static int sc132gs_set_ctrl_gain(struct sc132gs *sc132gs, u32 a_gain) { int ret = 0; - u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg; + u32 fine_again_reg, coarse_again_reg, fine_dgain_reg, coarse_dgain_reg; if (a_gain < 0x20) a_gain = 0x20; - if (a_gain > 0x391) - a_gain = 0x391; + if (a_gain > 0x6c80) + a_gain = 0x6c80; if (a_gain < 0x3a) {/*1x~1.813*/ - fine_again = a_gain; - coarse_again = 0x03; - fine_again_reg = fine_again & 0x3f; - coarse_again_reg = coarse_again & 0x3F; - if (fine_again_reg >= 0x39) - fine_again_reg = 0x39; - } else if (a_gain < 0x72) {/*1.813~3.568x*/ - fine_again = (a_gain - 0x3a) * 1000 / 1755 + 0x20; - coarse_again = 0x23; - if (fine_again > 0x3f) - fine_again = 0x3f; - fine_again_reg = fine_again & 0x3f; - coarse_again_reg = coarse_again & 0x3F; + fine_again_reg = a_gain; + coarse_again_reg = 0x03; + fine_dgain_reg = 0x80; + coarse_dgain_reg = 0x00; + } else if (a_gain < 0x74) {/*1.813~3.568x*/ + fine_again_reg = a_gain * 0x20 / 0x3a; + coarse_again_reg = 0x23; + fine_dgain_reg = 0x80; + coarse_dgain_reg = 0x00; } else if (a_gain < 0xe8) { /*3.568x~7.250x*/ - fine_again = (a_gain - 0x72) * 1000 / 3682 + 0x20; - coarse_again = 0x27; - if (fine_again > 0x3f) - fine_again = 0x3f; - fine_again_reg = fine_again & 0x3f; - coarse_again_reg = coarse_again & 0x3F; + fine_again_reg = a_gain * 0x20 / 0x74; + coarse_again_reg = 0x27; + fine_dgain_reg = 0x80; + coarse_dgain_reg = 0x00; } else if (a_gain < 0x1d0) { /*7.250x~14.5x*/ - fine_again = (a_gain - 0xe8) * 100 / 725 + 0x20; - coarse_again = 0x2f; - if (fine_again > 0x3f) - fine_again = 0x3f; - fine_again_reg = fine_again & 0x3f; - coarse_again_reg = coarse_again & 0x3F; - } else { /*14.5x~28.547*/ - fine_again = (a_gain - 0x1d0) * 1000 / 14047 + 0x20; - coarse_again = 0x3f; - if (fine_again > 0x3f) - fine_again = 0x3f; - fine_again_reg = fine_again & 0x3f; - coarse_again_reg = coarse_again & 0x3F; + fine_again_reg = a_gain * 0x20 / 0xe8; + coarse_again_reg = 0x2f; + fine_dgain_reg = 0x80; + coarse_dgain_reg = 0x00; + } else if (a_gain < 0x3a0) { /*14.5x~28.547x*/ + fine_again_reg = a_gain * 0x20 / 0x1d0; + coarse_again_reg = 0x3f; + fine_dgain_reg = 0x80; + coarse_dgain_reg = 0x00; + } else if (a_gain < 0x740) { /*again:28.547x, dgain: 1x~2x*/ + fine_again_reg = 0x3f ; + coarse_again_reg = 0x3f; + fine_dgain_reg = a_gain * 0x8 / 0x3a; + if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80; + else fine_dgain_reg = fine_dgain_reg & 0xfc; + coarse_dgain_reg = 0x00; + } else if (a_gain < 0xe80) { /*again:28.547x, dgain: 2x~4x*/ + fine_again_reg = 0x3f ; + coarse_again_reg = 0x3f; + fine_dgain_reg = a_gain * 0x8 / 0x74; + if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80; + else fine_dgain_reg = fine_dgain_reg & 0xfc; + coarse_dgain_reg = 0x01; + } else if (a_gain < 0x1d00) { /*again:28.547x, dgain: 4x~8x*/ + fine_again_reg = 0x3f ; + coarse_again_reg = 0x3f; + fine_dgain_reg = a_gain * 0x8 / 0xe8; + if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80; + else fine_dgain_reg = fine_dgain_reg & 0xfc; + coarse_dgain_reg = 0x03; + } else if (a_gain < 0x3a00) { /*again:28.547x, dgain: 8x~16x*/ + fine_again_reg = 0x3f ; + coarse_again_reg = 0x3f; + fine_dgain_reg = a_gain * 0x8 / 0x1d0; + if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80; + else fine_dgain_reg = fine_dgain_reg & 0xfc; + coarse_dgain_reg = 0x07; + } else { /*again:28.547x, dgain: 16x~31.5x*/ + fine_again_reg = 0x3f ; + coarse_again_reg = 0x3f; + fine_dgain_reg = a_gain * 0x8 / 0x3a0; + if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80; + else fine_dgain_reg = fine_dgain_reg & 0xfc; + coarse_dgain_reg = 0x0f; } - ret |= sc132gs_write_reg(sc132gs->client, + ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_COARSE_AGAIN, SC132GS_REG_VALUE_08BIT, coarse_again_reg); @@ -788,6 +830,34 @@ static int sc132gs_set_ctrl_gain(struct sc132gs *sc132gs, u32 a_gain) SC132GS_REG_FINE_AGAIN, SC132GS_REG_VALUE_08BIT, fine_again_reg); + ret |= sc132gs_write_reg(sc132gs->client, + SC132GS_REG_COARSE_DGAIN, + SC132GS_REG_VALUE_08BIT, + coarse_dgain_reg); + ret |= sc132gs_write_reg(sc132gs->client, + SC132GS_REG_FINE_DGAIN, + SC132GS_REG_VALUE_08BIT, + fine_dgain_reg); + if (a_gain < 0x40) { + ret |= sc132gs_write_reg(sc132gs->client, + 0x33fa, + SC132GS_REG_VALUE_08BIT, + 0x01); + ret |= sc132gs_write_reg(sc132gs->client, + 0x3317, + SC132GS_REG_VALUE_08BIT, + 0xf0); + } else { + ret |= sc132gs_write_reg(sc132gs->client, + 0x33fa, + SC132GS_REG_VALUE_08BIT, + 0x02); + ret |= sc132gs_write_reg(sc132gs->client, + 0x3317, + SC132GS_REG_VALUE_08BIT, + 0x0a); + } + return ret; } @@ -1110,7 +1180,7 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - max = sc132gs->cur_mode->height + ctrl->val - 6; + max = sc132gs->cur_mode->height + ctrl->val - 8; __v4l2_ctrl_modify_range(sc132gs->exposure, sc132gs->exposure->minimum, max, sc132gs->exposure->step, @@ -1125,10 +1195,13 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_EXPOSURE: /* 4 least significant bits of expsoure are fractional part */ ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_EXPOSURE, - SC132GS_REG_VALUE_16BIT, ctrl->val << 4); + SC132GS_REG_VALUE_24BIT, ctrl->val << 4); + + dev_dbg(&client->dev, "set exposure 0x%x \n",ctrl->val); break; case V4L2_CID_ANALOGUE_GAIN: ret = sc132gs_set_ctrl_gain(sc132gs, ctrl->val); + dev_dbg(&client->dev, "set gain 0x%x \n",ctrl->val); break; case V4L2_CID_VBLANK: ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_VTS, @@ -1136,12 +1209,29 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl) ctrl->val + sc132gs->cur_mode->height); if (!ret) sc132gs->cur_vts = ctrl->val + sc132gs->cur_mode->height; - sc132gs_modify_fps_info(sc132gs); - break; + if (sc132gs->cur_vts != sc132gs->cur_mode->vts_def) + sc132gs_modify_fps_info(sc132gs); break; case V4L2_CID_TEST_PATTERN: ret = sc132gs_enable_test_pattern(sc132gs, ctrl->val); break; + case V4L2_CID_HFLIP: + if (ctrl->val) + sc132gs->flip |= SC132GS_HFLIP_MASK; + else + sc132gs->flip &= ~SC132GS_HFLIP_MASK; + ret = sc132gs_write_reg(sc132gs->client, SC132GS_FLIP_REG, + SC132GS_REG_VALUE_08BIT, sc132gs->flip); + break; + case V4L2_CID_VFLIP: + if (ctrl->val) + sc132gs->flip |= SC132GS_VFLIP_MASK; + else + sc132gs->flip &= ~SC132GS_VFLIP_MASK; + + ret = sc132gs_write_reg(sc132gs->client, SC132GS_FLIP_REG, + SC132GS_REG_VALUE_08BIT, sc132gs->flip); + break; default: dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", __func__, ctrl->id, ctrl->val); @@ -1195,7 +1285,7 @@ static int sc132gs_initialize_controls(struct sc132gs *sc132gs) SC132GS_VTS_MAX - mode->height, 1, vblank_def); - exposure_max = mode->vts_def - 6; + exposure_max = mode->vts_def - 8; sc132gs->exposure = v4l2_ctrl_new_std(handler, &sc132gs_ctrl_ops, V4L2_CID_EXPOSURE, SC132GS_EXPOSURE_MIN, exposure_max, SC132GS_EXPOSURE_STEP, @@ -1210,7 +1300,12 @@ static int sc132gs_initialize_controls(struct sc132gs *sc132gs) &sc132gs_ctrl_ops, V4L2_CID_TEST_PATTERN, ARRAY_SIZE(sc132gs_test_pattern_menu) - 1, 0, 0, sc132gs_test_pattern_menu); + sc132gs->flip = 0; + sc132gs->h_flip = v4l2_ctrl_new_std(handler, &sc132gs_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + sc132gs->v_flip = v4l2_ctrl_new_std(handler, &sc132gs_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); if (handler->error) { ret = handler->error; dev_err(&sc132gs->client->dev, diff --git a/drivers/media/i2c/sc1346.c b/drivers/media/i2c/sc1346.c index f54dec8b9f20..b61f7d32ed09 100644 --- a/drivers/media/i2c/sc1346.c +++ b/drivers/media/i2c/sc1346.c @@ -1493,7 +1493,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc1346_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc200ai.c b/drivers/media/i2c/sc200ai.c index 0070cf53ff27..b5f62a50cfc8 100644 --- a/drivers/media/i2c/sc200ai.c +++ b/drivers/media/i2c/sc200ai.c @@ -2184,7 +2184,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc200ai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc223a.c b/drivers/media/i2c/sc223a.c index ed2c57f68459..1aebd80cd5c1 100644 --- a/drivers/media/i2c/sc223a.c +++ b/drivers/media/i2c/sc223a.c @@ -1868,7 +1868,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc223a_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc230ai.c b/drivers/media/i2c/sc230ai.c index 54692123f8af..6d454fdd5544 100644 --- a/drivers/media/i2c/sc230ai.c +++ b/drivers/media/i2c/sc230ai.c @@ -1887,7 +1887,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc230ai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc2336.c b/drivers/media/i2c/sc2336.c index 5490a60d3f2f..62ec88891df1 100644 --- a/drivers/media/i2c/sc2336.c +++ b/drivers/media/i2c/sc2336.c @@ -1546,7 +1546,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc2336_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc301iot.c b/drivers/media/i2c/sc301iot.c index 8ef10e616da9..f07204e6d904 100644 --- a/drivers/media/i2c/sc301iot.c +++ b/drivers/media/i2c/sc301iot.c @@ -2320,7 +2320,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc301iot_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc3336.c b/drivers/media/i2c/sc3336.c index 39769a9ddd43..aae6bcaf5a6a 100644 --- a/drivers/media/i2c/sc3336.c +++ b/drivers/media/i2c/sc3336.c @@ -1722,7 +1722,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc3336_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc3336p.c b/drivers/media/i2c/sc3336p.c index d57e2fa58ed5..785ece097402 100644 --- a/drivers/media/i2c/sc3336p.c +++ b/drivers/media/i2c/sc3336p.c @@ -1909,7 +1909,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc3336p_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc3338.c b/drivers/media/i2c/sc3338.c index d9af0ee83fa7..90751e004e79 100644 --- a/drivers/media/i2c/sc3338.c +++ b/drivers/media/i2c/sc3338.c @@ -716,7 +716,7 @@ static long sc3338_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) memcpy(&sc3338->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg), sizeof(struct preisp_hdrae_exp_s)); break; - case RKMODULE_SET_QUICK_STREAM: + case RKMODULE_SET_QUICK_STREAM:; stream = *((u32 *)arg); @@ -1590,7 +1590,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc3338_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc401ai.c b/drivers/media/i2c/sc401ai.c index ea367df2a6fc..0fedc077b5c2 100644 --- a/drivers/media/i2c/sc401ai.c +++ b/drivers/media/i2c/sc401ai.c @@ -1760,7 +1760,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc401ai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc4336.c b/drivers/media/i2c/sc4336.c index 681aca811645..747a2580d7f1 100644 --- a/drivers/media/i2c/sc4336.c +++ b/drivers/media/i2c/sc4336.c @@ -1581,7 +1581,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc4336_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc4336p.c b/drivers/media/i2c/sc4336p.c index b584b4a9ad89..82da26c3af2f 100644 --- a/drivers/media/i2c/sc4336p.c +++ b/drivers/media/i2c/sc4336p.c @@ -1574,7 +1574,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc4336p_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc450ai.c b/drivers/media/i2c/sc450ai.c index 568e3e7b2964..df0f0d36ed49 100644 --- a/drivers/media/i2c/sc450ai.c +++ b/drivers/media/i2c/sc450ai.c @@ -7,6 +7,7 @@ * V0.0X01.0X01 first version * V0.0X01.0X02 Increase vblank in 2688x1520@30fps linear 4lane configuration * V0.0X01.0X03 Add sc450ai 2lane hdr/linear configuration and 4 lane linear configuration + * V0.0X01.0X04 Add sc450ai thunder boot support */ //#define DEBUG @@ -34,28 +35,35 @@ #include "cam-tb-setup.h" #include "cam-sleep-wakeup.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x04) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN #endif -#define SC450AI_LANES_2LANE 2 -#define SC450AI_LANES_4LANE 4 #define SC450AI_BITS_PER_SAMPLE 10 #define SC450AI_LINK_FREQ_180 180000000 #define SC450AI_LINK_FREQ_360 360000000 #define SC450AI_LINK_FREQ_540 540000000 #define SC450AI_MAX_LINK_FREQ SC450AI_LINK_FREQ_540 -#define PIXEL_RATE_WITH_360M_10BIT (SC450AI_LINK_FREQ_360 / SC450AI_BITS_PER_SAMPLE * 2 * \ - SC450AI_LANES_2LANE) +/* 2 lane */ +#define PIXEL_RATE_WITH_360M_10BIT_2L (SC450AI_LINK_FREQ_360 * 2 * \ + 2 / SC450AI_BITS_PER_SAMPLE) +/* 4 lane */ +#define PIXEL_RATE_WITH_180M_10BIT_4L (SC450AI_LINK_FREQ_180 * 2 / \ + SC450AI_BITS_PER_SAMPLE * 4) +#define PIXEL_RATE_WITH_360M_10BIT_4L (SC450AI_LINK_FREQ_360 * 2 / \ + SC450AI_BITS_PER_SAMPLE * 4) #define SC450AI_XVCLK_FREQ 27000000 #define CHIP_ID 0xbd2f #define SC450AI_REG_CHIP_ID 0x3107 +#define SC450AI_REG_MIPI_CTRL 0x3019 +#define SC450AI_MIPI_CTRL_ON 0x00 +#define SC450AI_MIPI_CTRL_OFF 0xff #define SC450AI_REG_CTRL_MODE 0x0100 #define SC450AI_MODE_SW_STANDBY 0x0 #define SC450AI_MODE_STREAMING BIT(0) @@ -63,9 +71,9 @@ #define SC450AI_REG_EXPOSURE_H 0x3e00 #define SC450AI_REG_EXPOSURE_M 0x3e01 #define SC450AI_REG_EXPOSURE_L 0x3e02 -#define SC450AI_REG_EXPOSURE_SHORT_H 0x3e22 -#define SC450AI_REG_EXPOSURE_SHORT_M 0x3e04 -#define SC450AI_REG_EXPOSURE_SHORT_L 0x3e05 +#define SC450AI_REG_SEXPOSURE_H 0x3e22 +#define SC450AI_REG_SEXPOSURE_M 0x3e04 +#define SC450AI_REG_SEXPOSURE_L 0x3e05 #define SC450AI_EXPOSURE_MIN 1 #define SC450AI_EXPOSURE_STEP 1 #define SC450AI_VTS_MAX 0x7fff @@ -74,20 +82,22 @@ #define SC450AI_REG_DIG_FINE_GAIN 0x3e07 #define SC450AI_REG_ANA_GAIN 0x3e08 #define SC450AI_REG_ANA_FINE_GAIN 0x3e09 -#define SC450AI_REG_DIG_GAIN_SHORT 0x3e10 -#define SC450AI_REG_DIG_FINE_GAIN_SHORT 0x3e11 -#define SC450AI_REG_ANA_GAIN_SHORT 0x3e12 -#define SC450AI_REG_ANA_FINE_GAIN_SHORT 0x3e13 +#define SC450AI_REG_SDIG_GAIN 0x3e10 +#define SC450AI_REG_SDIG_FINE_GAIN 0x3e11 +#define SC450AI_REG_SANA_GAIN 0x3e12 +#define SC450AI_REG_SANA_FINE_GAIN 0x3e13 #define SC450AI_GAIN_MIN 0x40 //0x0080 #define SC450AI_GAIN_MAX 61975 //60.523*16*64 (99614) //48.64*16*128 #define SC450AI_GAIN_STEP 1 #define SC450AI_GAIN_DEFAULT 0x40 //0x80 // Note that the benchmark is 0x40 +#define SC450AI_LGAIN 0 +#define SC450AI_SGAIN 1 #define SC450AI_REG_GROUP_HOLD 0x3800//0x3812 #define SC450AI_GROUP_HOLD_START 0x00 #define SC450AI_GROUP_HOLD_END 0x30 // Not used -#define SC450AI_REG_TEST_PATTERN 0x4501 +#define SC450AI_REG_TEST_PATTERN 0x4501 #define SC450AI_TEST_PATTERN_BIT_MASK BIT(3) #define SC450AI_REG_VTS_H 0x320e @@ -95,9 +105,9 @@ #define SC450AI_FLIP_MIRROR_REG 0x3221 -#define SC450AI_FETCH_EXP_H(VAL) (((VAL) >> 12) & 0xF) -#define SC450AI_FETCH_EXP_M(VAL) (((VAL) >> 4) & 0xFF) -#define SC450AI_FETCH_EXP_L(VAL) (((VAL) & 0xF) << 4) +#define SC450AI_FETCH_EXP_H(VAL) (((VAL) >> 12) & 0xF) +#define SC450AI_FETCH_EXP_M(VAL) (((VAL) >> 4) & 0xFF) +#define SC450AI_FETCH_EXP_L(VAL) (((VAL) & 0xF) << 4) #define SC450AI_FETCH_MIRROR(VAL, ENABLE) (ENABLE ? VAL | 0x06 : VAL & 0xf9) #define SC450AI_FETCH_FLIP(VAL, ENABLE) (ENABLE ? VAL | 0x60 : VAL & 0x9f) @@ -135,11 +145,13 @@ struct sc450ai_mode { u32 hts_def; u32 vts_def; u32 exp_def; + const struct regval *global_reg_list; const struct regval *reg_list; u32 hdr_mode; - u32 xvclk_freq; + u32 mclk; u32 link_freq_idx; u32 vc[PAD_MAX]; + u8 bpp; u32 lanes; }; @@ -169,20 +181,23 @@ struct sc450ai { struct v4l2_fract cur_fps; bool streaming; bool power_on; + const struct sc450ai_mode *supported_modes; const struct sc450ai_mode *cur_mode; + u32 cfg_num; u32 module_index; const char *module_facing; const char *module_name; const char *len_name; + u32 standby_hw; u32 cur_vts; bool has_init_exp; bool is_thunderboot; bool is_first_streamoff; + bool is_standby; struct preisp_hdrae_exp_s init_hdrae_exp; struct cam_sw_info *cam_sw_inf; struct v4l2_fwnode_endpoint bus_cfg; - const struct sc450ai_mode *supported_modes; - u32 cfg_num; + enum rkmodule_sync_mode sync_mode; }; #define to_sc450ai(sd) container_of(sd, struct sc450ai, subdev) @@ -190,10 +205,9 @@ struct sc450ai { /* * Xclk 24Mhz */ -static const struct regval sc450ai_global_regs[] = { +static const struct regval sc450ai_global_regs_2lane[] = { {REG_NULL, 0x00}, }; - /* * Xclk 27Mhz * max_framerate 120fps @@ -790,6 +804,10 @@ static const struct regval sc450ai_hdr2_10_2688x1520_25fps_2lane_regs[] = { {REG_NULL, 0x00}, }; +static const struct regval sc450ai_global_4lane_regs[] = { + {REG_NULL, 0x00}, +}; + /* * Xclk 27Mhz * max_framerate 30fps @@ -1188,6 +1206,23 @@ static const struct regval sc450ai_hdr2_10_2688x1520_30fps_4lane_regs[] = { {REG_NULL, 0x00}, }; +static __maybe_unused const struct regval sc450ai_interal_sync_master_start_regs[] = { + {0x300a, 0x24}, //bit[2]=1 fsync_oen + {0x3032, 0xa0},////bit[7]=1 vsync_tc_en + {REG_NULL, 0x00}, +}; + +static __maybe_unused const struct regval sc450ai_interal_sync_slaver_start_regs[] = { + {0x300a, 0x22}, + {0x3222, 0x01}, //Bit[0]: Slave mode en + {0x3224, 0x92}, //fsync trigger + {0x3230, 0x00}, + {0x3231, 0x04}, + {0x322e, 0x00}, + {0x322f, 0x02}, + {REG_NULL, 0x00}, +}; + static const struct sc450ai_mode supported_modes_2lane[] = { { .width = 2688, @@ -1200,10 +1235,12 @@ static const struct sc450ai_mode supported_modes_2lane[] = { .hts_def = 0x2ee * 4, .vts_def = 0x0638, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .global_reg_list = sc450ai_global_regs_2lane, .reg_list = sc450ai_linear_10_2688x1520_30fps_2lane_regs, .hdr_mode = NO_HDR, - .xvclk_freq = 27000000, + .mclk = 27000000, .link_freq_idx = 1, + .bpp = 10, .vc[PAD0] = 0, .lanes = 2, }, @@ -1218,10 +1255,12 @@ static const struct sc450ai_mode supported_modes_2lane[] = { .hts_def = 0x39e * 4, .vts_def = 0x0c26, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .global_reg_list = sc450ai_global_regs_2lane, .reg_list = sc450ai_hdr2_10_2688x1520_25fps_2lane_regs, .hdr_mode = HDR_X2, - .xvclk_freq = 27000000, + .mclk = 27000000, .link_freq_idx = 2, + .bpp = 10, .vc[PAD0] = 1, .vc[PAD1] = 0,//L->CSI_WR0 .vc[PAD2] = 1, @@ -1239,10 +1278,12 @@ static const struct sc450ai_mode supported_modes_2lane[] = { .hts_def = 0x03a8, .vts_def = 0x030c, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .global_reg_list = sc450ai_global_regs_2lane, .reg_list = sc450ai_linear_10_1344x760_120fps_2lane_regs, .hdr_mode = NO_HDR, - .xvclk_freq = 27000000, + .mclk = 27000000, .link_freq_idx = 1, + .bpp = 10, .vc[PAD0] = 0, .lanes = 2, }, @@ -1260,10 +1301,12 @@ static const struct sc450ai_mode supported_modes_4lane[] = { .hts_def = 0x2ee * 4, .vts_def = 0x0c30, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .global_reg_list = sc450ai_global_4lane_regs, .reg_list = sc450ai_linear_10_2688x1520_30fps_4lane_regs, .hdr_mode = NO_HDR, - .xvclk_freq = 27000000, + .mclk = 27000000, .link_freq_idx = 0, + .bpp = 10, .vc[PAD0] = 0, .lanes = 4, }, @@ -1278,10 +1321,12 @@ static const struct sc450ai_mode supported_modes_4lane[] = { .hts_def = 0x3a8 * 4, .vts_def = 0x0c30, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .global_reg_list = sc450ai_global_4lane_regs, .reg_list = sc450ai_hdr2_10_2688x1520_30fps_4lane_regs, .hdr_mode = HDR_X2, - .xvclk_freq = 27000000, + .mclk = 27000000, .link_freq_idx = 1, + .bpp = 10, .vc[PAD0] = 1, .vc[PAD1] = 0,//L->CSI_WR0 .vc[PAD2] = 1, @@ -1290,6 +1335,10 @@ static const struct sc450ai_mode supported_modes_4lane[] = { }, }; +static const u32 bus_code[] = { + MEDIA_BUS_FMT_SBGGR10_1X10, +}; + static const s64 link_freq_menu_items[] = { SC450AI_LINK_FREQ_180, SC450AI_LINK_FREQ_360, @@ -1380,7 +1429,7 @@ static int sc450ai_read_reg(struct i2c_client *client, u16 reg, unsigned int len return 0; } -static int sc450ai_set_gain_reg(struct sc450ai *sc450ai, u32 gain) +static int sc450ai_set_gain_reg(struct sc450ai *sc450ai, u32 gain, int mode) { struct i2c_client *client = sc450ai->client; u32 coarse_again = 0, coarse_dgain = 0, fine_again = 0, fine_dgain = 0; @@ -1447,38 +1496,38 @@ static int sc450ai_set_gain_reg(struct sc450ai *sc450ai, u32 gain) dev_dbg(&client->dev, "c_again: 0x%x, c_dgain: 0x%x, f_again: 0x%x, f_dgain: 0x%0x\n", coarse_again, coarse_dgain, fine_again, fine_dgain); - ret = sc450ai_write_reg(sc450ai->client, - SC450AI_REG_DIG_GAIN, - SC450AI_REG_VALUE_08BIT, - coarse_dgain); - ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_DIG_FINE_GAIN, - SC450AI_REG_VALUE_08BIT, - fine_dgain); - ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_ANA_GAIN, - SC450AI_REG_VALUE_08BIT, - coarse_again); - ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_ANA_FINE_GAIN, - SC450AI_REG_VALUE_08BIT, - fine_again); - - if (sc450ai->cur_mode->hdr_mode == HDR_X2) { - ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_DIG_GAIN_SHORT, + if (mode == SC450AI_LGAIN) { + ret = sc450ai_write_reg(sc450ai->client, + SC450AI_REG_DIG_GAIN, SC450AI_REG_VALUE_08BIT, coarse_dgain); ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_DIG_FINE_GAIN_SHORT, + SC450AI_REG_DIG_FINE_GAIN, + SC450AI_REG_VALUE_08BIT, + fine_dgain); + ret |= sc450ai_write_reg(sc450ai->client, + SC450AI_REG_ANA_GAIN, + SC450AI_REG_VALUE_08BIT, + coarse_again); + ret |= sc450ai_write_reg(sc450ai->client, + SC450AI_REG_ANA_FINE_GAIN, + SC450AI_REG_VALUE_08BIT, + fine_again); + } else { + ret |= sc450ai_write_reg(sc450ai->client, + SC450AI_REG_SDIG_GAIN, + SC450AI_REG_VALUE_08BIT, + coarse_dgain); + ret |= sc450ai_write_reg(sc450ai->client, + SC450AI_REG_SDIG_FINE_GAIN, SC450AI_REG_VALUE_08BIT, fine_dgain); ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_ANA_GAIN_SHORT, + SC450AI_REG_SANA_GAIN, SC450AI_REG_VALUE_08BIT, coarse_again); ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_ANA_FINE_GAIN_SHORT, + SC450AI_REG_SANA_FINE_GAIN, SC450AI_REG_VALUE_08BIT, fine_again); } @@ -1486,199 +1535,8 @@ static int sc450ai_set_gain_reg(struct sc450ai *sc450ai, u32 gain) return ret; } -static int sc450ai_get_reso_dist(const struct sc450ai_mode *mode, - struct v4l2_mbus_framefmt *framefmt) -{ - return abs(mode->width - framefmt->width) + - abs(mode->height - framefmt->height); -} - -static const struct sc450ai_mode * -sc450ai_find_best_fit(struct sc450ai *sc450ai, struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *framefmt = &fmt->format; - int dist; - int cur_best_fit = 0; - int cur_best_fit_dist = -1; - unsigned int i; - - for (i = 0; i < sc450ai->cfg_num; i++) { - dist = sc450ai_get_reso_dist(&sc450ai->supported_modes[i], framefmt); - if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { - cur_best_fit_dist = dist; - cur_best_fit = i; - } - } - - return &sc450ai->supported_modes[cur_best_fit]; -} - -static int sc450ai_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - const struct sc450ai_mode *mode; - s64 h_blank, vblank_def; - u64 dst_link_freq = 0; - u64 dst_pixel_rate = 0; - - mutex_lock(&sc450ai->mutex); - - mode = sc450ai_find_best_fit(sc450ai, fmt); - fmt->format.code = mode->bus_fmt; - fmt->format.width = mode->width; - fmt->format.height = mode->height; - fmt->format.field = V4L2_FIELD_NONE; - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { -#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API - *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; -#else - mutex_unlock(&sc450ai->mutex); - return -ENOTTY; -#endif - } else { - sc450ai->cur_mode = mode; - h_blank = mode->hts_def - mode->width; - __v4l2_ctrl_modify_range(sc450ai->hblank, h_blank, - h_blank, 1, h_blank); - vblank_def = mode->vts_def - mode->height; - __v4l2_ctrl_modify_range(sc450ai->vblank, vblank_def, - SC450AI_VTS_MAX - mode->height, - 1, vblank_def); - dst_link_freq = mode->link_freq_idx; - dst_pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / - SC450AI_BITS_PER_SAMPLE * 2 * mode->lanes; - __v4l2_ctrl_s_ctrl_int64(sc450ai->pixel_rate, - dst_pixel_rate); - __v4l2_ctrl_s_ctrl(sc450ai->link_freq, - dst_link_freq); - sc450ai->cur_fps = mode->max_fps; - } - - mutex_unlock(&sc450ai->mutex); - - return 0; -} - -static int sc450ai_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - const struct sc450ai_mode *mode = sc450ai->cur_mode; - - mutex_lock(&sc450ai->mutex); - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { -#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API - fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); -#else - mutex_unlock(&sc450ai->mutex); - return -ENOTTY; -#endif - } else { - fmt->format.width = mode->width; - fmt->format.height = mode->height; - fmt->format.code = mode->bus_fmt; - fmt->format.field = V4L2_FIELD_NONE; - /* format info: width/height/data type/virctual channel */ - if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) - fmt->reserved[0] = mode->vc[fmt->pad]; - else - fmt->reserved[0] = mode->vc[PAD0]; - } - mutex_unlock(&sc450ai->mutex); - - return 0; -} - -static int sc450ai_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - - if (code->index != 0) - return -EINVAL; - code->code = sc450ai->cur_mode->bus_fmt; - - return 0; -} - -static int sc450ai_enum_frame_sizes(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - - if (fse->index >= sc450ai->cfg_num) - return -EINVAL; - - if (fse->code != sc450ai->supported_modes[0].bus_fmt) - return -EINVAL; - - fse->min_width = sc450ai->supported_modes[fse->index].width; - fse->max_width = sc450ai->supported_modes[fse->index].width; - fse->max_height = sc450ai->supported_modes[fse->index].height; - fse->min_height = sc450ai->supported_modes[fse->index].height; - - return 0; -} - -static int sc450ai_enable_test_pattern(struct sc450ai *sc450ai, u32 pattern) -{ - u32 val = 0; - int ret = 0; - - ret = sc450ai_read_reg(sc450ai->client, SC450AI_REG_TEST_PATTERN, - SC450AI_REG_VALUE_08BIT, &val); - if (pattern) - val |= SC450AI_TEST_PATTERN_BIT_MASK; - else - val &= ~SC450AI_TEST_PATTERN_BIT_MASK; - - ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_TEST_PATTERN, - SC450AI_REG_VALUE_08BIT, val); - return ret; -} - -static int sc450ai_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *fi) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - const struct sc450ai_mode *mode = sc450ai->cur_mode; - - if (sc450ai->streaming) - fi->interval = sc450ai->cur_fps; - else - fi->interval = mode->max_fps; - return 0; -} - -static int sc450ai_g_mbus_config(struct v4l2_subdev *sd, - unsigned int pad_id, - struct v4l2_mbus_config *config) -{ - struct sc450ai *sc450ai = to_sc450ai(sd); - - config->type = V4L2_MBUS_CSI2_DPHY; - config->bus.mipi_csi2.num_data_lanes = sc450ai->cur_mode->lanes; - - return 0; -} - -static void sc450ai_get_module_inf(struct sc450ai *sc450ai, - struct rkmodule_inf *inf) -{ - memset(inf, 0, sizeof(*inf)); - strscpy(inf->base.sensor, SC450AI_NAME, sizeof(inf->base.sensor)); - strscpy(inf->base.module, sc450ai->module_name, - sizeof(inf->base.module)); - strscpy(inf->base.lens, sc450ai->len_name, sizeof(inf->base.lens)); -} - static int sc450ai_set_hdrae(struct sc450ai *sc450ai, - struct preisp_hdrae_exp_s *ae) + struct preisp_hdrae_exp_s *ae) { int ret = 0; u32 l_exp_time, m_exp_time, s_exp_time; @@ -1728,31 +1586,365 @@ static int sc450ai_set_hdrae(struct sc450ai *sc450ai, SC450AI_REG_EXPOSURE_L, SC450AI_REG_VALUE_08BIT, SC450AI_FETCH_EXP_L(l_exp_time)); - ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_EXPOSURE_SHORT_M, + SC450AI_REG_SEXPOSURE_M, SC450AI_REG_VALUE_08BIT, SC450AI_FETCH_EXP_M(s_exp_time)); ret |= sc450ai_write_reg(sc450ai->client, - SC450AI_REG_EXPOSURE_SHORT_L, + SC450AI_REG_SEXPOSURE_L, SC450AI_REG_VALUE_08BIT, SC450AI_FETCH_EXP_L(s_exp_time)); - ret |= sc450ai_set_gain_reg(sc450ai, l_a_gain); + ret |= sc450ai_set_gain_reg(sc450ai, l_a_gain, SC450AI_LGAIN); + ret |= sc450ai_set_gain_reg(sc450ai, s_a_gain, SC450AI_SGAIN); return ret; } +static int sc450ai_get_reso_dist(const struct sc450ai_mode *mode, + struct v4l2_mbus_framefmt *framefmt) +{ + return abs(mode->width - framefmt->width) + + abs(mode->height - framefmt->height); +} + +static const struct sc450ai_mode * +sc450ai_find_best_fit(struct sc450ai *sc450ai, struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt = &fmt->format; + int dist; + int cur_best_fit = 0; + int cur_best_fit_dist = -1; + unsigned int i; + + for (i = 0; i < sc450ai->cfg_num; i++) { + dist = sc450ai_get_reso_dist(&sc450ai->supported_modes[i], framefmt); + if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { + cur_best_fit_dist = dist; + cur_best_fit = i; + } else if (dist == cur_best_fit_dist && + framefmt->code == sc450ai->supported_modes[i].bus_fmt) { + cur_best_fit = i; + break; + } + } + + return &sc450ai->supported_modes[cur_best_fit]; +} + +static int sc450ai_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + const struct sc450ai_mode *mode; + s64 h_blank, vblank_def; + u64 dst_link_freq = 0; + u64 dst_pixel_rate = 0; + u8 lanes = sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes; + + mutex_lock(&sc450ai->mutex); + + mode = sc450ai_find_best_fit(sc450ai, fmt); + fmt->format.code = mode->bus_fmt; + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; +#else + mutex_unlock(&sc450ai->mutex); + return -ENOTTY; +#endif + } else { + sc450ai->cur_mode = mode; + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(sc450ai->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(sc450ai->vblank, vblank_def, + SC450AI_VTS_MAX - mode->height, + 1, vblank_def); + dst_link_freq = mode->link_freq_idx; + dst_pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / + mode->bpp * 2 * lanes; + __v4l2_ctrl_s_ctrl_int64(sc450ai->pixel_rate, + dst_pixel_rate); + __v4l2_ctrl_s_ctrl(sc450ai->link_freq, + dst_link_freq); + sc450ai->cur_fps = mode->max_fps; + } + + mutex_unlock(&sc450ai->mutex); + + return 0; +} + +static int sc450ai_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + const struct sc450ai_mode *mode = sc450ai->cur_mode; + + mutex_lock(&sc450ai->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API + fmt->format = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); +#else + mutex_unlock(&sc450ai->mutex); + return -ENOTTY; +#endif + } else { + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = mode->bus_fmt; + fmt->format.field = V4L2_FIELD_NONE; + /* format info: width/height/data type/virctual channel */ + if (fmt->pad < PAD_MAX && mode->hdr_mode != NO_HDR) + fmt->reserved[0] = mode->vc[fmt->pad]; + else + fmt->reserved[0] = mode->vc[PAD0]; + } + mutex_unlock(&sc450ai->mutex); + + return 0; +} + +static int sc450ai_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index >= ARRAY_SIZE(bus_code)) + return -EINVAL; + code->code = bus_code[code->index]; + + return 0; +} + +static int sc450ai_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + + if (fse->index >= sc450ai->cfg_num) + return -EINVAL; + + if (fse->code != sc450ai->supported_modes[fse->index].bus_fmt) + return -EINVAL; + + fse->min_width = sc450ai->supported_modes[fse->index].width; + fse->max_width = sc450ai->supported_modes[fse->index].width; + fse->max_height = sc450ai->supported_modes[fse->index].height; + fse->min_height = sc450ai->supported_modes[fse->index].height; + + return 0; +} + +static int sc450ai_enable_test_pattern(struct sc450ai *sc450ai, u32 pattern) +{ + u32 val = 0; + int ret = 0; + + ret = sc450ai_read_reg(sc450ai->client, SC450AI_REG_TEST_PATTERN, + SC450AI_REG_VALUE_08BIT, &val); + if (pattern) + val |= SC450AI_TEST_PATTERN_BIT_MASK; + else + val &= ~SC450AI_TEST_PATTERN_BIT_MASK; + + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_TEST_PATTERN, + SC450AI_REG_VALUE_08BIT, val); + return ret; +} + +static int sc450ai_g_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + const struct sc450ai_mode *mode = sc450ai->cur_mode; + + if (sc450ai->streaming) + fi->interval = sc450ai->cur_fps; + else + fi->interval = mode->max_fps; + return 0; +} + +static const struct sc450ai_mode *sc450ai_find_mode(struct sc450ai *sc450ai, int fps) +{ + const struct sc450ai_mode *mode = NULL; + const struct sc450ai_mode *match = NULL; + int cur_fps = 0; + int i = 0; + + for (i = 0; i < sc450ai->cfg_num; i++) { + mode = &sc450ai->supported_modes[i]; + if (mode->width == sc450ai->cur_mode->width && + mode->height == sc450ai->cur_mode->height && + mode->hdr_mode == sc450ai->cur_mode->hdr_mode && + mode->bus_fmt == sc450ai->cur_mode->bus_fmt) { + cur_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, mode->max_fps.numerator); + if (cur_fps == fps) { + match = mode; + break; + } + } + } + return match; +} + +static int sc450ai_s_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *fi) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + const struct sc450ai_mode *mode = NULL; + struct v4l2_fract *fract = &fi->interval; + s64 h_blank, vblank_def; + u64 pixel_rate = 0; + int fps; + + if (sc450ai->streaming) + return -EBUSY; + + if (fi->pad != 0) + return -EINVAL; + + if (fract->numerator == 0) { + v4l2_err(sd, "error param, check interval param\n"); + return -EINVAL; + } + fps = DIV_ROUND_CLOSEST(fract->denominator, fract->numerator); + mode = sc450ai_find_mode(sc450ai, fps); + if (mode == NULL) { + v4l2_err(sd, "couldn't match fi\n"); + return -EINVAL; + } + + sc450ai->cur_mode = mode; + + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(sc450ai->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(sc450ai->vblank, vblank_def, + SC450AI_VTS_MAX - mode->height, + 1, vblank_def); + pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / + mode->bpp * 2 * mode->lanes; + + __v4l2_ctrl_s_ctrl_int64(sc450ai->pixel_rate, + pixel_rate); + __v4l2_ctrl_s_ctrl(sc450ai->link_freq, + mode->link_freq_idx); + sc450ai->cur_fps = mode->max_fps; + + return 0; +} + +static int sc450ai_g_mbus_config(struct v4l2_subdev *sd, + unsigned int pad_id, + struct v4l2_mbus_config *config) +{ + struct sc450ai *sc450ai = to_sc450ai(sd); + + config->type = V4L2_MBUS_CSI2_DPHY; + config->bus.mipi_csi2.num_data_lanes = sc450ai->cur_mode->lanes; + + return 0; +} + +static void sc450ai_get_module_inf(struct sc450ai *sc450ai, + struct rkmodule_inf *inf) +{ + memset(inf, 0, sizeof(*inf)); + strscpy(inf->base.sensor, SC450AI_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, sc450ai->module_name, + sizeof(inf->base.module)); + strscpy(inf->base.lens, sc450ai->len_name, sizeof(inf->base.lens)); +} + +static int sc450ai_set_setting(struct sc450ai *sc450ai, struct rk_sensor_setting *setting) +{ + int i = 0; + int cur_fps = 0; + s64 h_blank, vblank_def; + u64 pixel_rate = 0; + const struct sc450ai_mode *mode = NULL; + const struct sc450ai_mode *match = NULL; + u8 lane = sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes; + + dev_info(&sc450ai->client->dev, + "sensor setting: %d x %d, fps:%d fmt:%d, mode:%d\n", + setting->width, setting->height, + setting->fps, setting->fmt, setting->mode); + + for (i = 0; i < sc450ai->cfg_num; i++) { + mode = &sc450ai->supported_modes[i]; + if (mode->width == setting->width && + mode->height == setting->height && + mode->hdr_mode == setting->mode && + mode->bus_fmt == setting->fmt) { + cur_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, mode->max_fps.numerator); + if (cur_fps == setting->fps) { + match = mode; + break; + } + } + } + + if (match) { + dev_info(&sc450ai->client->dev, "-----%s: match the support mode, mode idx:%d-----\n", + __func__, i); + sc450ai->cur_mode = mode; + + h_blank = mode->hts_def - mode->width; + __v4l2_ctrl_modify_range(sc450ai->hblank, h_blank, + h_blank, 1, h_blank); + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(sc450ai->vblank, vblank_def, + SC450AI_VTS_MAX - mode->height, + 1, vblank_def); + + + __v4l2_ctrl_s_ctrl(sc450ai->link_freq, mode->link_freq_idx); + pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / + mode->bpp * 2 * lane; + __v4l2_ctrl_s_ctrl_int64(sc450ai->pixel_rate, pixel_rate); + dev_info(&sc450ai->client->dev, "freq_idx:%d pixel_rate:%lld\n", + mode->link_freq_idx, pixel_rate); + + sc450ai->cur_vts = mode->vts_def; + sc450ai->cur_fps = mode->max_fps; + + dev_info(&sc450ai->client->dev, "hts_def:%d cur_vts:%d cur_fps:%d\n", + mode->hts_def, mode->vts_def, + sc450ai->cur_fps.denominator / sc450ai->cur_fps.numerator); + } else { + dev_err(&sc450ai->client->dev, "couldn't match the support modes\n"); + return -EINVAL; + } + + return 0; +} + static long sc450ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct sc450ai *sc450ai = to_sc450ai(sd); struct rkmodule_hdr_cfg *hdr; + struct rk_sensor_setting *setting; u32 i, h, w; long ret = 0; u32 stream = 0; - const struct sc450ai_mode *mode; u64 dst_link_freq = 0; u64 dst_pixel_rate = 0; - + u8 lanes = sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes; + const struct sc450ai_mode *mode; + int cur_best_fit = -1; + int cur_best_fit_dist = -1; + int cur_dist, cur_fps, dst_fps; + u32 *sync_mode = NULL; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1765,51 +1957,178 @@ static long sc450ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) break; case RKMODULE_SET_HDR_CFG: hdr = (struct rkmodule_hdr_cfg *)arg; + if (hdr->hdr_mode == sc450ai->cur_mode->hdr_mode) + return 0; w = sc450ai->cur_mode->width; h = sc450ai->cur_mode->height; + dst_fps = DIV_ROUND_CLOSEST(sc450ai->cur_mode->max_fps.denominator, + sc450ai->cur_mode->max_fps.numerator); for (i = 0; i < sc450ai->cfg_num; i++) { if (w == sc450ai->supported_modes[i].width && h == sc450ai->supported_modes[i].height && - sc450ai->supported_modes[i].hdr_mode == hdr->hdr_mode) { - sc450ai->cur_mode = &sc450ai->supported_modes[i]; - break; + sc450ai->supported_modes[i].hdr_mode == hdr->hdr_mode && + sc450ai->supported_modes[i].bus_fmt == sc450ai->cur_mode->bus_fmt) { + cur_fps = DIV_ROUND_CLOSEST(sc450ai->supported_modes[i].max_fps.denominator, + sc450ai->supported_modes[i].max_fps.numerator); + cur_dist = abs(cur_fps - dst_fps); + if (cur_best_fit_dist == -1 || cur_dist < cur_best_fit_dist) { + cur_best_fit_dist = cur_dist; + cur_best_fit = i; + } else if (cur_dist == cur_best_fit_dist) { + cur_best_fit = i; + break; + } } } - if (i == sc450ai->cfg_num) { + if (cur_best_fit == -1) { dev_err(&sc450ai->client->dev, "not find hdr mode:%d %dx%d config\n", hdr->hdr_mode, w, h); ret = -EINVAL; } else { + sc450ai->cur_mode = &sc450ai->supported_modes[cur_best_fit]; mode = sc450ai->cur_mode; w = mode->hts_def - mode->width; h = mode->vts_def - mode->height; __v4l2_ctrl_modify_range(sc450ai->hblank, w, w, 1, w); __v4l2_ctrl_modify_range(sc450ai->vblank, h, - SC450AI_VTS_MAX - mode->height, 1, h); + SC450AI_VTS_MAX - sc450ai->cur_mode->height, 1, h); + sc450ai->cur_fps = sc450ai->cur_mode->max_fps; + dst_link_freq = mode->link_freq_idx; dst_pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / - SC450AI_BITS_PER_SAMPLE * 2 * mode->lanes; + mode->bpp * 2 * lanes; __v4l2_ctrl_s_ctrl_int64(sc450ai->pixel_rate, dst_pixel_rate); __v4l2_ctrl_s_ctrl(sc450ai->link_freq, dst_link_freq); - sc450ai->cur_fps = mode->max_fps; } break; case PREISP_CMD_SET_HDRAE_EXP: - ret = sc450ai_set_hdrae(sc450ai, arg); + sc450ai_set_hdrae(sc450ai, arg); + if (sc450ai->cam_sw_inf) + memcpy(&sc450ai->cam_sw_inf->hdr_ae, (struct preisp_hdrae_exp_s *)(arg), + sizeof(struct preisp_hdrae_exp_s)); break; case RKMODULE_SET_QUICK_STREAM: stream = *((u32 *)arg); - if (stream) - ret = sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, - SC450AI_REG_VALUE_08BIT, SC450AI_MODE_STREAMING); - else - ret = sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, - SC450AI_REG_VALUE_08BIT, SC450AI_MODE_SW_STANDBY); + + if (sc450ai->standby_hw) { /* hardware standby */ + if (stream) { + u32 val; + + /* pwdn gpio pull up */ + if (!IS_ERR(sc450ai->pwdn_gpio)) + gpiod_set_value_cansleep(sc450ai->pwdn_gpio, 1); + // Make sure __v4l2_ctrl_handler_setup can be called correctly + sc450ai->is_standby = false; + /* mipi clk on */ + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_MIPI_CTRL, + SC450AI_REG_VALUE_08BIT, + SC450AI_MIPI_CTRL_ON); + /* adjust timing */ + ret |= sc450ai_read_reg(sc450ai->client, 0x36e9, + SC450AI_REG_VALUE_08BIT, &val); + val &= 0x7f; + ret |= sc450ai_write_reg(sc450ai->client, 0x36e9, + SC450AI_REG_VALUE_08BIT, + val); + ret |= sc450ai_read_reg(sc450ai->client, 0x36f9, + SC450AI_REG_VALUE_08BIT, &val); + val &= 0x7f; + ret |= sc450ai_write_reg(sc450ai->client, 0x36f9, + SC450AI_REG_VALUE_08BIT, + val); + + #if IS_REACHABLE(CONFIG_VIDEO_CAM_SLEEP_WAKEUP) + if (__v4l2_ctrl_handler_setup(&sc450ai->ctrl_handler)) + dev_err(&sc450ai->client->dev, "__v4l2_ctrl_handler_setup fail!"); + if (sc450ai->cur_mode->hdr_mode != NO_HDR) { // hdr mode + if (sc450ai->cam_sw_inf) { + ret = sc450ai_ioctl(&sc450ai->subdev, + PREISP_CMD_SET_HDRAE_EXP, + &sc450ai->cam_sw_inf->hdr_ae); + if (ret) { + dev_err(&sc450ai->client->dev, + "init exp fail in hdr mode\n"); + return ret; + } + } + } + #endif + + /* stream on */ + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, + SC450AI_REG_VALUE_08BIT, + SC450AI_MODE_STREAMING); + dev_info(&sc450ai->client->dev, + "quickstream, streaming on: exit hw standby mode\n"); + } else { + u32 val; + + /* adjust timing */ + ret |= sc450ai_read_reg(sc450ai->client, 0x36e9, + SC450AI_REG_VALUE_08BIT, &val); + val |= 0x80; + ret |= sc450ai_write_reg(sc450ai->client, 0x36e9, + SC450AI_REG_VALUE_08BIT, + val); + ret |= sc450ai_read_reg(sc450ai->client, 0x36f9, + SC450AI_REG_VALUE_08BIT, &val); + val |= 0x80; + ret |= sc450ai_write_reg(sc450ai->client, 0x36f9, + SC450AI_REG_VALUE_08BIT, + val); + /* stream off */ + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, + SC450AI_REG_VALUE_08BIT, + SC450AI_MODE_SW_STANDBY); + /* mipi clk off */ + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_MIPI_CTRL, + SC450AI_REG_VALUE_08BIT, + SC450AI_MIPI_CTRL_OFF); + /* pwnd gpio pull down */ + if (!IS_ERR(sc450ai->pwdn_gpio)) + gpiod_set_value_cansleep(sc450ai->pwdn_gpio, 0); + dev_info(&sc450ai->client->dev, + "quickstream, streaming off: enter hw standby mode\n"); + sc450ai->is_standby = true; + } + } else { /* software standby */ + if (stream) { + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_MIPI_CTRL, + SC450AI_REG_VALUE_08BIT, + SC450AI_MIPI_CTRL_ON); + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, + SC450AI_REG_VALUE_08BIT, + SC450AI_MODE_STREAMING); + dev_info(&sc450ai->client->dev, + "quickstream, streaming on: exit soft standby mode\n"); + } else { + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, + SC450AI_REG_VALUE_08BIT, + SC450AI_MODE_SW_STANDBY); + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_MIPI_CTRL, + SC450AI_REG_VALUE_08BIT, + SC450AI_MIPI_CTRL_OFF); + dev_info(&sc450ai->client->dev, + "quickstream, streaming off: enter soft standby mode\n"); + } + } + break; + case RKCIS_CMD_SELECT_SETTING: + setting = (struct rk_sensor_setting *)arg; + ret = sc450ai_set_setting(sc450ai, setting); + break; + case RKMODULE_GET_SYNC_MODE: + sync_mode = (u32 *)arg; + *sync_mode = sc450ai->sync_mode; + break; + case RKMODULE_SET_SYNC_MODE: + sync_mode = (u32 *)arg; + sc450ai->sync_mode = *sync_mode; break; default: ret = -ENOIOCTLCMD; @@ -1827,8 +2146,10 @@ static long sc450ai_compat_ioctl32(struct v4l2_subdev *sd, struct rkmodule_inf *inf; struct rkmodule_hdr_cfg *hdr; struct preisp_hdrae_exp_s *hdrae; + struct rk_sensor_setting *setting; long ret; u32 stream = 0; + u32 *sync_mode = NULL; switch (cmd) { case RKMODULE_GET_MODULE_INFO: @@ -1894,6 +2215,35 @@ static long sc450ai_compat_ioctl32(struct v4l2_subdev *sd, else ret = -EFAULT; break; + case RKCIS_CMD_SELECT_SETTING: + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (!setting) { + ret = -ENOMEM; + return ret; + } + + ret = copy_from_user(setting, up, sizeof(*setting)); + if (!ret) + ret = sc450ai_ioctl(sd, cmd, setting); + else + ret = -EFAULT; + kfree(setting); + break; + case RKMODULE_GET_SYNC_MODE: + ret = sc450ai_ioctl(sd, cmd, &sync_mode); + if (!ret) { + ret = copy_to_user(up, &sync_mode, sizeof(u32)); + if (ret) + ret = -EFAULT; + } + break; + case RKMODULE_SET_SYNC_MODE: + ret = copy_from_user(&sync_mode, up, sizeof(u32)); + if (!ret) + ret = sc450ai_ioctl(sd, cmd, &sync_mode); + else + ret = -EFAULT; + break; default: ret = -ENOIOCTLCMD; break; @@ -1905,7 +2255,7 @@ static long sc450ai_compat_ioctl32(struct v4l2_subdev *sd, static int __sc450ai_start_stream(struct sc450ai *sc450ai) { - int ret; + int ret = 0; if (!sc450ai->is_thunderboot) { ret = sc450ai_write_array(sc450ai->client, sc450ai->cur_mode->reg_list); @@ -1925,8 +2275,15 @@ static int __sc450ai_start_stream(struct sc450ai *sc450ai) } } } - ret = sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, - SC450AI_REG_VALUE_08BIT, SC450AI_MODE_STREAMING); + if (sc450ai->sync_mode == INTERNAL_MASTER_MODE) + ret |= sc450ai_write_array(sc450ai->client, + sc450ai_interal_sync_master_start_regs); + else if (sc450ai->sync_mode == EXTERNAL_MASTER_MODE) + ret |= sc450ai_write_array(sc450ai->client, + sc450ai_interal_sync_slaver_start_regs); + else if (sc450ai->sync_mode == NO_SYNC_MODE) + ret |= sc450ai_write_reg(sc450ai->client, SC450AI_REG_CTRL_MODE, + SC450AI_REG_VALUE_08BIT, SC450AI_MODE_STREAMING); return ret; } @@ -1997,7 +2354,8 @@ static int sc450ai_s_power(struct v4l2_subdev *sd, int on) } if (!sc450ai->is_thunderboot) { - ret = sc450ai_write_array(sc450ai->client, sc450ai_global_regs); + ret = sc450ai_write_array(sc450ai->client, + sc450ai->cur_mode->global_reg_list); if (ret) { v4l2_err(sd, "could not set init registers\n"); pm_runtime_put_noidle(&client->dev); @@ -2020,7 +2378,7 @@ unlock_and_return: /* Calculate the delay in us by clock rate and clock cycles */ static inline u32 sc450ai_cal_delay(u32 cycles, struct sc450ai *sc450ai) { - return DIV_ROUND_UP(cycles, sc450ai->cur_mode->xvclk_freq / 1000 / 1000); + return DIV_ROUND_UP(cycles, sc450ai->cur_mode->mclk / 1000 / 1000); } static int __sc450ai_power_on(struct sc450ai *sc450ai) @@ -2035,12 +2393,12 @@ static int __sc450ai_power_on(struct sc450ai *sc450ai) if (ret < 0) dev_err(dev, "could not set pins\n"); } - ret = clk_set_rate(sc450ai->xvclk, sc450ai->cur_mode->xvclk_freq); + ret = clk_set_rate(sc450ai->xvclk, sc450ai->cur_mode->mclk); if (ret < 0) - dev_warn(dev, "Failed to set xvclk rate (%dHz)\n", sc450ai->cur_mode->xvclk_freq); - if (clk_get_rate(sc450ai->xvclk) != sc450ai->cur_mode->xvclk_freq) + dev_warn(dev, "Failed to set xvclk rate (%dHz)\n", sc450ai->cur_mode->mclk); + if (clk_get_rate(sc450ai->xvclk) != sc450ai->cur_mode->mclk) dev_warn(dev, "xvclk mismatched, modes are based on %dHz\n", - sc450ai->cur_mode->xvclk_freq); + sc450ai->cur_mode->mclk); ret = clk_prepare_enable(sc450ai->xvclk); if (ret < 0) { dev_err(dev, "Failed to enable xvclk\n"); @@ -2122,6 +2480,11 @@ static int __maybe_unused sc450ai_resume(struct device *dev) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct sc450ai *sc450ai = to_sc450ai(sd); + if (sc450ai->standby_hw) { + dev_info(dev, "resume standby!"); + return 0; + } + cam_sw_prepare_wakeup(sc450ai->cam_sw_inf, dev); usleep_range(4000, 5000); @@ -2132,7 +2495,7 @@ static int __maybe_unused sc450ai_resume(struct device *dev) if (sc450ai->has_init_exp && sc450ai->cur_mode != NO_HDR) { // hdr mode ret = sc450ai_ioctl(&sc450ai->subdev, PREISP_CMD_SET_HDRAE_EXP, - &sc450ai->cam_sw_inf->hdr_ae); + &sc450ai->cam_sw_inf->hdr_ae); if (ret) { dev_err(&sc450ai->client->dev, "set exp fail in hdr mode\n"); return ret; @@ -2148,6 +2511,11 @@ static int __maybe_unused sc450ai_suspend(struct device *dev) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct sc450ai *sc450ai = to_sc450ai(sd); + if (sc450ai->standby_hw) { + dev_info(dev, "suspend standby!"); + return 0; + } + cam_sw_write_array_cb_init(sc450ai->cam_sw_inf, client, (void *)sc450ai->cur_mode->reg_list, (sensor_write_array)sc450ai_write_array); @@ -2223,7 +2591,9 @@ static int sc450ai_enum_frame_interval(struct v4l2_subdev *sd, static const struct dev_pm_ops sc450ai_pm_ops = { SET_RUNTIME_PM_OPS(sc450ai_runtime_suspend, sc450ai_runtime_resume, NULL) +#ifdef CONFIG_VIDEO_CAM_SLEEP_WAKEUP SET_LATE_SYSTEM_SLEEP_PM_OPS(sc450ai_suspend, sc450ai_resume) +#endif }; #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API @@ -2243,6 +2613,7 @@ static const struct v4l2_subdev_core_ops sc450ai_core_ops = { static const struct v4l2_subdev_video_ops sc450ai_video_ops = { .s_stream = sc450ai_s_stream, .g_frame_interval = sc450ai_g_frame_interval, + .s_frame_interval = sc450ai_s_frame_interval, }; static const struct v4l2_subdev_pad_ops sc450ai_pad_ops = { @@ -2281,7 +2652,7 @@ static int sc450ai_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - max = sc450ai->cur_mode->height + ctrl->val - 5; + max = sc450ai->cur_mode->height + ctrl->val - 4; __v4l2_ctrl_modify_range(sc450ai->exposure, sc450ai->exposure->minimum, max, sc450ai->exposure->step, @@ -2289,6 +2660,11 @@ static int sc450ai_set_ctrl(struct v4l2_ctrl *ctrl) break; } + if (sc450ai->standby_hw && sc450ai->is_standby) { + dev_dbg(&client->dev, "%s: is_standby = true, will return\n", __func__); + return 0; + } + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; @@ -2296,7 +2672,7 @@ static int sc450ai_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_EXPOSURE: dev_dbg(&client->dev, "set exposure 0x%x\n", ctrl->val); if (sc450ai->cur_mode->hdr_mode == NO_HDR) { - val = ctrl->val<<1; + val = ctrl->val << 1; /* 4 least significant bits of expsoure are fractional part */ ret = sc450ai_write_reg(sc450ai->client, SC450AI_REG_EXPOSURE_H, @@ -2315,7 +2691,7 @@ static int sc450ai_set_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_ANALOGUE_GAIN: dev_dbg(&client->dev, "set gain 0x%x\n", ctrl->val); if (sc450ai->cur_mode->hdr_mode == NO_HDR) - ret = sc450ai_set_gain_reg(sc450ai, ctrl->val); + ret = sc450ai_set_gain_reg(sc450ai, ctrl->val, SC450AI_LGAIN); break; case V4L2_CID_VBLANK: dev_dbg(&client->dev, "set vblank 0x%x\n", ctrl->val); @@ -2374,6 +2750,7 @@ static int sc450ai_initialize_controls(struct sc450ai *sc450ai) int ret; u64 dst_link_freq = 0; u64 dst_pixel_rate = 0, max_dst_pixel_rate = 0; + u8 lanes = sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes; handler = &sc450ai->ctrl_handler; mode = sc450ai->cur_mode; @@ -2389,9 +2766,9 @@ static int sc450ai_initialize_controls(struct sc450ai *sc450ai) sc450ai->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; dst_link_freq = mode->link_freq_idx; - max_dst_pixel_rate = SC450AI_MAX_LINK_FREQ / SC450AI_BITS_PER_SAMPLE * 2 * SC450AI_LANES_4LANE; + max_dst_pixel_rate = SC450AI_MAX_LINK_FREQ / mode->bpp * 2 * lanes; dst_pixel_rate = (u32)link_freq_menu_items[mode->link_freq_idx] / - SC450AI_BITS_PER_SAMPLE * 2 * mode->lanes; + mode->bpp * 2 * lanes; sc450ai->pixel_rate = v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 0, max_dst_pixel_rate, 1, dst_pixel_rate); @@ -2408,7 +2785,7 @@ static int sc450ai_initialize_controls(struct sc450ai *sc450ai) V4L2_CID_VBLANK, vblank_def, SC450AI_VTS_MAX - mode->height, 1, vblank_def); - exposure_max = mode->vts_def - 8; + exposure_max = mode->vts_def - 4; sc450ai->exposure = v4l2_ctrl_new_std(handler, &sc450ai_ctrl_ops, V4L2_CID_EXPOSURE, SC450AI_EXPOSURE_MIN, exposure_max, SC450AI_EXPOSURE_STEP, @@ -2436,6 +2813,7 @@ static int sc450ai_initialize_controls(struct sc450ai *sc450ai) sc450ai->subdev.ctrl_handler = handler; sc450ai->has_init_exp = false; sc450ai->cur_fps = mode->max_fps; + sc450ai->is_standby = false; return 0; @@ -2464,7 +2842,7 @@ static int sc450ai_check_sensor_id(struct sc450ai *sc450ai, return -ENODEV; } - dev_info(dev, "Detected %s sensor chip_id %x\n", SC450AI_NAME, CHIP_ID); + dev_info(dev, "Detected SC450AI (0x%04x) sensor\n", CHIP_ID); return 0; } @@ -2491,6 +2869,7 @@ static int sc450ai_probe(struct i2c_client *client) int ret; int i, hdr_mode = 0; struct device_node *endpoint; + const char *sync_mode_name = NULL; dev_info(dev, "driver version: %02x.%02x.%02x", DRIVER_VERSION >> 16, @@ -2514,10 +2893,32 @@ static int sc450ai_probe(struct i2c_client *client) return -EINVAL; } - sc450ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); + /* Compatible with non-standby mode if this attribute is not configured in dts*/ + of_property_read_u32(node, RKMODULE_CAMERA_STANDBY_HW, + &sc450ai->standby_hw); + dev_info(dev, "sc450ai->standby_hw = %d\n", sc450ai->standby_hw); + ret = of_property_read_string(node, RKMODULE_CAMERA_SYNC_MODE, + &sync_mode_name); + if (ret) { + sc450ai->sync_mode = NO_SYNC_MODE; + dev_err(dev, "could not get sync mode!\n"); + } else { + if (strcmp(sync_mode_name, RKMODULE_EXTERNAL_MASTER_MODE) == 0) { + sc450ai->sync_mode = EXTERNAL_MASTER_MODE; + dev_info(dev, "external master mode\n"); + } else if (strcmp(sync_mode_name, RKMODULE_INTERNAL_MASTER_MODE) == 0) { + sc450ai->sync_mode = INTERNAL_MASTER_MODE; + dev_info(dev, "internal master mode\n"); + } else if (strcmp(sync_mode_name, RKMODULE_SOFT_SYNC_MODE) == 0) { + sc450ai->sync_mode = SOFT_SYNC_MODE; + dev_info(dev, "soft sync mode\n"); + } + } - ret = of_property_read_u32(node, OF_CAMERA_HDR_MODE, - &hdr_mode); + sc450ai->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP); + dev_err(dev, "========= is_thunderboot %d\n", sc450ai->is_thunderboot); + + ret = of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode); if (ret) { hdr_mode = NO_HDR; dev_warn(dev, " Get hdr mode failed! no hdr default\n"); @@ -2537,12 +2938,16 @@ static int sc450ai_probe(struct i2c_client *client) return -EINVAL; } - if (sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes == SC450AI_LANES_4LANE) { + if (sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes == 4) { sc450ai->supported_modes = supported_modes_4lane; sc450ai->cfg_num = ARRAY_SIZE(supported_modes_4lane); + dev_info(dev, "detect sc450ai lane: %d\n", + sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes); } else { sc450ai->supported_modes = supported_modes_2lane; sc450ai->cfg_num = ARRAY_SIZE(supported_modes_2lane); + dev_info(dev, "detect sc450ai lane: %d\n", + sc450ai->bus_cfg.bus.mipi_csi2.num_data_lanes); } sc450ai->client = client; @@ -2635,7 +3040,7 @@ static int sc450ai_probe(struct i2c_client *client) if (!sc450ai->cam_sw_inf) { sc450ai->cam_sw_inf = cam_sw_init(); cam_sw_clk_init(sc450ai->cam_sw_inf, sc450ai->xvclk, - sc450ai->cur_mode->xvclk_freq); + sc450ai->cur_mode->mclk); cam_sw_reset_pin_init(sc450ai->cam_sw_inf, sc450ai->reset_gpio, 0); cam_sw_pwdn_pin_init(sc450ai->cam_sw_inf, sc450ai->pwdn_gpio, 1); } @@ -2733,7 +3138,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc450ai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc501ai.c b/drivers/media/i2c/sc501ai.c index 4ddd3b4cbc3d..888d47cb8aec 100644 --- a/drivers/media/i2c/sc501ai.c +++ b/drivers/media/i2c/sc501ai.c @@ -1421,7 +1421,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc501ai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc5336.c b/drivers/media/i2c/sc5336.c index 5cebafa69eee..bb281f2e7a85 100644 --- a/drivers/media/i2c/sc5336.c +++ b/drivers/media/i2c/sc5336.c @@ -1594,7 +1594,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc5336_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc635hai.c b/drivers/media/i2c/sc635hai.c index b48a7502a908..0d9dd2f13ce9 100644 --- a/drivers/media/i2c/sc635hai.c +++ b/drivers/media/i2c/sc635hai.c @@ -2963,7 +2963,7 @@ static void __exit sensor_mod_exit(void) i2c_del_driver(&sc635hai_i2c_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(sensor_mod_init); #else device_initcall_sync(sensor_mod_init); diff --git a/drivers/media/i2c/sc850sl.c b/drivers/media/i2c/sc850sl.c index e9e49d12807c..bd99f7dcac23 100644 --- a/drivers/media/i2c/sc850sl.c +++ b/drivers/media/i2c/sc850sl.c @@ -41,8 +41,10 @@ #endif #define MIPI_FREQ_540M 540000000 +#define MIPI_FREQ_972M 486000000 +#define SC850AI_MAX_LINK_FREQ MIPI_FREQ_540M -#define SC850SL_MAX_PIXEL_RATE (MIPI_FREQ_540M / 10 * 2 * SC850SL_4LANES) +#define SC850SL_MAX_PIXEL_RATE (SC850AI_MAX_LINK_FREQ / 10 * 2 * SC850SL_4LANES) #define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode" #define SC850SL_XVCLK_FREQ_24M 24000000 @@ -144,6 +146,7 @@ struct sc850sl_mode { u32 vts_def; u32 exp_def; u32 mipi_freq_idx; + u32 xvclk_freq; u32 bpp; const struct regval *reg_list; u32 hdr_mode; @@ -195,7 +198,7 @@ struct sc850sl { #define to_sc850sl(sd) container_of(sd, struct sc850sl, subdev) //cleaned_0x20_SC850SL_MIPI_24Minput_1C4D_1080Mbps_10bit_3840x2160_30fps_one_expo.ini -static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] = { +static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_30fps_regs[] = { {0x0103, 0x01}, {0x0100, 0x00}, {0x36e9, 0x80}, @@ -394,6 +397,208 @@ static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] = {REG_NULL, 0x00}, }; +static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_40fps_regs[] = { + {0x0103, 0x01}, + {0x0100, 0x00}, + {0x36e9, 0x80}, + {0x36f9, 0x80}, + {0x36ea, 0x09}, + {0x36eb, 0x0c}, + {0x36ec, 0x4b}, + {0x36ed, 0x34}, + {0x36fa, 0xcb}, + {0x36fb, 0x13}, + {0x36fc, 0x00}, + {0x36fd, 0x07}, + {0x36e9, 0x53}, + {0x36f9, 0x53}, + {0x3000, 0x01}, + {0x3018, 0x7a}, + {0x3019, 0xf0}, + {0x301a, 0x30}, + {0x301e, 0x3c}, + {0x301f, 0x0d}, + {0x302a, 0x00}, + {0x3031, 0x0a}, + {0x3032, 0x20}, + {0x3033, 0x22}, + {0x3037, 0x60}, + {0x303e, 0xb4}, + {0x3201, 0x98}, + {0x3203, 0x0c}, + {0x3205, 0xa7}, + {0x3207, 0x83}, + {0x320c, 0x03}, + {0x320d, 0x39}, + {0x3211, 0x08}, + {0x3213, 0x2c}, + {0x3223, 0xc0}, + {0x3226, 0x00}, + {0x3227, 0x03}, + {0x3230, 0x11}, + {0x3231, 0x93}, + {0x3250, 0x40}, + {0x3253, 0x08}, + {0x327e, 0x00}, + {0x3280, 0x00}, + {0x3281, 0x00}, + {0x3301, 0x24}, + {0x3304, 0x30}, + {0x3306, 0x54}, + {0x3308, 0x10}, + {0x3309, 0x60}, + {0x330a, 0x00}, + {0x330b, 0xa0}, + {0x330d, 0x10}, + {0x3314, 0x92}, + {0x331e, 0x29}, + {0x331f, 0x59}, + {0x3333, 0x10}, + {0x3347, 0x05}, + {0x3348, 0xd0}, + {0x3352, 0x01}, + {0x3356, 0x38}, + {0x335d, 0x60}, + {0x3362, 0x70}, + {0x338f, 0x80}, + {0x33af, 0x48}, + {0x33fe, 0x00}, + {0x3400, 0x12}, + {0x3406, 0x04}, + {0x3410, 0x12}, + {0x3416, 0x06}, + {0x3433, 0x01}, + {0x3440, 0x12}, + {0x3446, 0x08}, + {0x3478, 0x01}, + {0x3479, 0x01}, + {0x347a, 0x02}, + {0x347b, 0x01}, + {0x347c, 0x04}, + {0x347d, 0x01}, + {0x3616, 0x0c}, + {0x3620, 0x94}, + {0x3622, 0x74}, + {0x3629, 0x74}, + {0x362a, 0xf0}, + {0x362b, 0x0f}, + {0x362d, 0x00}, + {0x3630, 0x68}, + {0x3633, 0x24}, + {0x3634, 0x22}, + {0x3635, 0x20}, + {0x3637, 0x18}, + {0x3638, 0x26}, + {0x363b, 0x06}, + {0x363c, 0x07}, + {0x363d, 0x05}, + {0x363e, 0x8f}, + {0x3648, 0xe0}, + {0x3649, 0x0a}, + {0x364a, 0x06}, + {0x364c, 0x6a}, + {0x3650, 0x3d}, + {0x3654, 0x70}, + {0x3656, 0x68}, + {0x3657, 0x0f}, + {0x3658, 0x3d}, + {0x365c, 0x40}, + {0x365e, 0x68}, + {0x3901, 0x04}, + {0x3902, 0xf1}, + {0x3904, 0x20}, + {0x3905, 0x91}, + {0x391e, 0x03}, + {0x3928, 0x04}, + {0x3933, 0xa0}, + {0x3934, 0x0a}, + {0x3935, 0x68}, + {0x3936, 0x00}, + {0x3937, 0x20}, + {0x3938, 0x0a}, + {0x3946, 0x20}, + {0x3961, 0x40}, + {0x3962, 0x40}, + {0x3963, 0xc8}, + {0x3964, 0xc8}, + {0x3965, 0x40}, + {0x3966, 0x40}, + {0x3967, 0x00}, + {0x39cd, 0xc8}, + {0x39ce, 0xc8}, + {0x3e01, 0x82}, + {0x3e02, 0x00}, + {0x3e0e, 0x02}, + {0x3e0f, 0x00}, + {0x3e1c, 0x0f}, + {0x3e23, 0x00}, + {0x3e24, 0x00}, + {0x3e53, 0x00}, + {0x3e54, 0x00}, + {0x3e68, 0x00}, + {0x3e69, 0x80}, + {0x3e73, 0x00}, + {0x3e74, 0x00}, + {0x3e86, 0x03}, + {0x3e87, 0x40}, + {0x3f02, 0x24}, + {0x4424, 0x02}, + {0x4501, 0xb4}, + {0x4503, 0x20}, + {0x4509, 0x20}, + {0x4561, 0x12}, + {0x4800, 0x24}, + {0x4837, 0x20}, + {0x4900, 0x24}, + {0x4937, 0x16}, + {0x5000, 0x0e}, + {0x500f, 0x35}, + {0x5020, 0x00}, + {0x5787, 0x10}, + {0x5788, 0x06}, + {0x5789, 0x00}, + {0x578a, 0x18}, + {0x578b, 0x0c}, + {0x578c, 0x00}, + {0x5790, 0x10}, + {0x5791, 0x06}, + {0x5792, 0x01}, + {0x5793, 0x18}, + {0x5794, 0x0c}, + {0x5795, 0x01}, + {0x5799, 0x06}, + {0x57a2, 0x60}, + {0x59e0, 0xfe}, + {0x59e1, 0x40}, + {0x59e2, 0x38}, + {0x59e3, 0x30}, + {0x59e4, 0x20}, + {0x59e5, 0x38}, + {0x59e6, 0x30}, + {0x59e7, 0x20}, + {0x59e8, 0x3f}, + {0x59e9, 0x38}, + {0x59ea, 0x30}, + {0x59eb, 0x3f}, + {0x59ec, 0x38}, + {0x59ed, 0x30}, + {0x59ee, 0xfe}, + {0x59ef, 0x40}, + {0x59f4, 0x38}, + {0x59f5, 0x30}, + {0x59f6, 0x20}, + {0x59f7, 0x38}, + {0x59f8, 0x30}, + {0x59f9, 0x20}, + {0x59fa, 0x3f}, + {0x59fb, 0x38}, + {0x59fc, 0x30}, + {0x59fd, 0x3f}, + {0x59fe, 0x38}, + {0x59ff, 0x30}, + {REG_NULL, 0x00}, +}; + /* * The width and height must be configured to be * the same as the current output resolution of the sensor. @@ -407,6 +612,26 @@ static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] = * } */ static const struct sc850sl_mode supported_modes[] = { +#if defined CONFIG_VIDEO_CAM_SLEEP_WAKEUP + { + .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 3840, + .height = 2160, + .max_fps = { + .numerator = 10000, + .denominator = 400000, + }, + .exp_def = 0x08c0, + .hts_def = 0x10e0, + .vts_def = 0x08ca, + .reg_list = sc850sl_linear10bit_3840x2160_40fps_regs, + .hdr_mode = NO_HDR, + .xvclk_freq = 24000000, + .mipi_freq_idx = 1, + .bpp = 10, + .vc[PAD0] = 0, + }, +#endif { .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, .width = 3840, @@ -419,8 +644,9 @@ static const struct sc850sl_mode supported_modes[] = { .hts_def = 0x0226 * 5 - 0x180, .vts_def = 0x08ca, .bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10, - .reg_list = sc850sl_linear10bit_3840x2160_regs, + .reg_list = sc850sl_linear10bit_3840x2160_30fps_regs, .hdr_mode = NO_HDR, + .xvclk_freq = 24000000, .mipi_freq_idx = 0, .bpp = 10, .vc[PAD0] = 0, @@ -441,6 +667,7 @@ static const char *const sc850sl_test_pattern_menu[] = { static const s64 link_freq_items[] = { MIPI_FREQ_540M, + MIPI_FREQ_972M, }; /* Write registers up to 4 at a time */ @@ -1025,6 +1252,7 @@ static long sc850sl_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKMODULE_SET_QUICK_STREAM: stream = *((u32 *)arg); + dev_info(&sc850sl->client->dev, "stream: %d\n", stream); if (stream) { ret |= sc850sl_write_reg(sc850sl->client, 0x3019, @@ -1354,10 +1582,10 @@ static int __sc850sl_power_on(struct sc850sl *sc850sl) if (ret < 0) dev_err(dev, "could not set pins\n"); } - ret = clk_set_rate(sc850sl->xvclk, SC850SL_XVCLK_FREQ_24M); + ret = clk_set_rate(sc850sl->xvclk, sc850sl->cur_mode->xvclk_freq); if (ret < 0) dev_warn(dev, "Failed to set xvclk rate 24MHz\n"); - if (clk_get_rate(sc850sl->xvclk) != SC850SL_XVCLK_FREQ_24M) + if (clk_get_rate(sc850sl->xvclk) != sc850sl->cur_mode->xvclk_freq) dev_warn(dev, "xvclk mismatched\n"); ret = clk_prepare_enable(sc850sl->xvclk); if (ret < 0) { @@ -1972,7 +2200,7 @@ static int sc850sl_probe(struct i2c_client *client) #endif if (!sc850sl->cam_sw_info) { sc850sl->cam_sw_info = cam_sw_init(); - cam_sw_clk_init(sc850sl->cam_sw_info, sc850sl->xvclk, SC850SL_XVCLK_FREQ_24M); + cam_sw_clk_init(sc850sl->cam_sw_info, sc850sl->xvclk, sc850sl->cur_mode->xvclk_freq); cam_sw_reset_pin_init(sc850sl->cam_sw_info, sc850sl->reset_gpio, 0); cam_sw_pwdn_pin_init(sc850sl->cam_sw_info, sc850sl->pwdn_gpio, 1); } diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.c b/drivers/media/platform/rockchip/aiisp/aiisp.c index 8ae4ffbe429a..6c37a3069835 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.c +++ b/drivers/media/platform/rockchip/aiisp/aiisp.c @@ -123,7 +123,7 @@ static void rkaiisp_update_regs(struct rkaiisp_device *aidev, u32 start, u32 end } } -void rkaiisp_update_list_reg(struct rkaiisp_device *aidev) +static void rkaiisp_update_list_reg(struct rkaiisp_device *aidev) { rkaiisp_update_regs(aidev, AIISP_MI_CTRL, AIISP_MI_CTRL); rkaiisp_update_regs(aidev, AIISP_MI_SLICE_CTRL, AIISP_MI_MANUAL_CTRL); @@ -355,8 +355,8 @@ static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev, { if (buffer->dma_fd >= 0) { v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "%s buf:%pad size:%d\n", __func__, - &buffer->dma_addr, buffer->size); + "%s dma_fd:%d, buf:%pad size:%d\n", __func__, + buffer->dma_fd, &buffer->dma_addr, buffer->size); dma_buf_unmap_attachment(buffer->dba, buffer->sgt, DMA_BIDIRECTIONAL); dma_buf_detach(buffer->dmabuf, buffer->dba); dma_buf_put(buffer->dmabuf); @@ -365,10 +365,39 @@ static void rkaiisp_detach_dmabuf(struct rkaiisp_device *aidev, } } +static void rkaiisp_free_aiynr_ybuf(struct rkaiisp_device *aidev) +{ + struct aiisp_aiynr_ybuf_cfg *buf_cfg = &aidev->ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + int i; + + for (i = 0; i < buf_cfg->buf_cnt; i++) { + if (buf_cfg->buf[i]) { + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, + "%s buf:%pad size:%zu dmabuf:%p\n", __func__, + &ynroutbuf[i].dma_addr, ynroutbuf[i].dmabuf->size, + buf_cfg->buf[i]); + if (ynroutbuf[i].dba) { + if (ynroutbuf[i].sgt) { + dma_buf_unmap_attachment(ynroutbuf[i].dba, + ynroutbuf[i].sgt, + DMA_BIDIRECTIONAL); + ynroutbuf[i].sgt = NULL; + } + dma_buf_detach(ynroutbuf[i].dmabuf, ynroutbuf[i].dba); + dma_buf_put(ynroutbuf[i].dmabuf); + ynroutbuf[i].dba = NULL; + } + buf_cfg->buf[i] = NULL; + } + } + + buf_cfg->buf_cnt = 0; +} + static void rkaiisp_free_tempbuf(struct rkaiisp_device *aidev) { - rkaiisp_free_buffer(aidev, &aidev->temp_buf[0]); - rkaiisp_free_buffer(aidev, &aidev->temp_buf[1]); + rkaiisp_free_buffer(aidev, &aidev->temp_buf); } static int rkaiisp_free_pool(struct rkaiisp_device *aidev) @@ -394,7 +423,13 @@ static int rkaiisp_free_pool(struct rkaiisp_device *aidev) for (i = 0; i < ispbuf->bnr_buf.u.v35.aiisp.buf_cnt; i++) rkaiisp_detach_dmabuf(aidev, &aidev->aiispbuf[i]); + for (i = 0; i < ispbuf->bnr_buf.u.v35.y_src.buf_cnt; i++) + rkaiisp_detach_dmabuf(aidev, &aidev->ynrinbuf[i]); + rkaiisp_free_tempbuf(aidev); + if (aidev->exealgo == AIYNR) + rkaiisp_free_aiynr_ybuf(aidev); + aidev->init_buf = false; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "free buf poll\n"); @@ -432,9 +467,10 @@ static int rkaiisp_attach_dmabuf(struct rkaiisp_device *aidev, buffer->sgt = sgt; buffer->dma_addr = sg_dma_address(sgt->sgl); buffer->size = sg_dma_len(sgt->sgl); + buffer->vaddr = NULL; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "%s buf:%pad size:%d\n", __func__, - &buffer->dma_addr, buffer->size); + "%s dma_fd:%d, buf:%pad size:%d\n", __func__, + buffer->dma_fd, &buffer->dma_addr, buffer->size); return ret; } @@ -446,6 +482,26 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, if (aidev->model_mode == REMOSAIC_MODE) return; + if (aidev->model_mode == AIYNR_MODE) { + for (i = 0; i < RKAIISP_AIYNR_LAYER_NUM; i++) { + if (i == 0) { + aidev->outbuf_size[i].height = raw_hgt; + aidev->outbuf_size[i].width = raw_wid; + aidev->outbuf_size[i].channel = 1; + aidev->outbuf_size[i].stride = raw_wid; + } else { + aidev->outbuf_size[i].height = raw_hgt / 2; + aidev->outbuf_size[i].width = raw_wid / 2; + aidev->outbuf_size[i].channel = 8; + aidev->outbuf_size[i].stride = raw_wid * 8; + } + + raw_hgt = CEIL_BY(CEIL_DOWN(raw_hgt, 2), 2); + raw_wid = CEIL_BY(CEIL_DOWN(raw_wid, 2), 2); + } + return; + } + if (aidev->model_mode == SINGLEX2_MODE) { for (i = 0; i < RKAIISP_PYRAMID_LAYER_NUM; i++) { if (i == 0) { @@ -491,10 +547,41 @@ static void rkaiisp_calc_outbuf_size(struct rkaiisp_device *aidev, u32 raw_hgt, } } +static void rkaiisp_set_lastout_buf(struct rkaiisp_device *aidev) +{ + int buffer_index; + + if (aidev->model_mode == REMOSAIC_MODE) { + aidev->lastout_buf[0] = &aidev->temp_buf; + aidev->lastout_buf[1] = &aidev->temp_buf; + return; + } + + if (aidev->model_runcnt % 2 == 0) { + aidev->lastout_buf[0] = &aidev->temp_buf; + if (aidev->model_mode == AIYNR_MODE) { + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + aidev->lastout_buf[1] = &aidev->ynroutbuf[buffer_index]; + } else { + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + aidev->lastout_buf[1] = &aidev->aiispbuf[buffer_index]; + } + } else { + aidev->lastout_buf[1] = &aidev->temp_buf; + if (aidev->model_mode == AIYNR_MODE) { + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + aidev->lastout_buf[0] = &aidev->ynroutbuf[buffer_index]; + } else { + buffer_index = aidev->curr_idxbuf.aibnr_st.aiisp_index; + aidev->lastout_buf[0] = &aidev->aiispbuf[buffer_index]; + } + } +} + static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf_info *ispbuf) { int i, ret = 0; - u32 stride; + u32 stride, size; for (i = 0; i < ispbuf->bnr_buf.iir.buf_cnt; i++) { aidev->iirbuf[i].dma_fd = ispbuf->bnr_buf.iir.buf_fd[i]; @@ -536,18 +623,29 @@ static int rkaiisp_init_pool(struct rkaiisp_device *aidev, struct rkaiisp_ispbuf return -EINVAL; } } + for (i = 0; i < ispbuf->bnr_buf.u.v35.y_src.buf_cnt; i++) { + aidev->ynrinbuf[i].dma_fd = ispbuf->bnr_buf.u.v35.y_src.buf_fd[i]; + ret = rkaiisp_attach_dmabuf(aidev, &aidev->ynrinbuf[i]); - stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; - aidev->temp_buf[0].size = stride * (ispbuf->iir_height + 1) / 2; - aidev->temp_buf[1].size = aidev->temp_buf[0].size; - aidev->temp_buf[0].is_need_vaddr = false; - aidev->temp_buf[0].is_need_dbuf = false; - aidev->temp_buf[0].is_need_dmafd = false; - aidev->temp_buf[1].is_need_vaddr = false; - aidev->temp_buf[1].is_need_dbuf = false; - aidev->temp_buf[1].is_need_dmafd = false; - ret = rkaiisp_allow_buffer(aidev, &aidev->temp_buf[0]); - ret |= rkaiisp_allow_buffer(aidev, &aidev->temp_buf[1]); + if (ret) { + rkaiisp_free_pool(aidev); + v4l2_err(&aidev->v4l2_dev, "attach dmabuf failed: %d\n", ret); + return -EINVAL; + } + } + + if (aidev->exealgo == AIYNR) { + stride = ((ispbuf->iir_width + 3) / 4 * 8 * 11 + 7) >> 3; + size = stride * (ispbuf->iir_height + 3) / 4; + } else { + stride = ((ispbuf->iir_width + 1) / 2 * 15 * 11 + 7) >> 3; + size = stride * (ispbuf->iir_height + 1) / 2; + } + aidev->temp_buf.size = size; + aidev->temp_buf.is_need_vaddr = false; + aidev->temp_buf.is_need_dbuf = false; + aidev->temp_buf.is_need_dmafd = false; + ret = rkaiisp_allow_buffer(aidev, &aidev->temp_buf); if (ret) rkaiisp_free_pool(aidev); @@ -635,7 +733,7 @@ static int rkaiisp_init_airms_pool(struct rkaiisp_device *aidev, struct rkaiisp_ return ret; } -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) +static int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf) { struct kfifo *fifo = &aidev->idxbuf_kfifo; struct rkaiisp_hw_dev *hw_dev = aidev->hw_dev; @@ -656,10 +754,10 @@ int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf * else v4l2_err(&aidev->v4l2_dev, "fifo is full\n"); - if (aidev->exealgo == AIBNR) - sequence = idxbuf->aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = idxbuf->airms_st.sequence; + else + sequence = idxbuf->aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "idxbuf fifo in: %d\n", sequence); @@ -676,6 +774,40 @@ int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf * return ret; } +static int rkaiisp_get_ynrbuf_info(struct rkaiisp_device *aidev, + struct rkaiisp_ynrbuf_info *ynrbuf_info) +{ + + struct aiisp_aiynr_ybuf_cfg *buf_cfg = &aidev->ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + u32 buf_cnt; + int i; + + buf_cnt = buf_cfg->buf_cnt; + if (buf_cnt > RKAIISP_AIYNR_YBUF_NUM_MAX) { + v4l2_err(&aidev->v4l2_dev, + "%s ynroutbuf cnt(%d) is too big\n", __func__, + buf_cnt); + buf_cnt = RKAIISP_AIYNR_YBUF_NUM_MAX; + } + ynrbuf_info->width = buf_cfg->width; + ynrbuf_info->height = buf_cfg->height; + ynrbuf_info->buf_cnt = 0; + for (i = 0; i < buf_cnt; i++) { + if (buf_cfg->buf[i]) { + ynroutbuf[i].dma_fd = dma_buf_fd(ynroutbuf[i].dmabuf, O_CLOEXEC); + if (ynroutbuf[i].dma_fd < 0) + return -EINVAL; + + get_dma_buf(ynroutbuf[i].dmabuf); + ynrbuf_info->dma_fd[i] = ynroutbuf[i].dma_fd; + ynrbuf_info->buf_cnt++; + } + } + + return 0; +} + static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev, struct rkaiisp_model_cfg *model_cfg, int width) { @@ -759,7 +891,7 @@ static void rkaiisp_gen_slice_param(struct rkaiisp_device *aidev, slice_mode[6] << 12 | slice_mode[7] << 14 | slice_num << 24 | - AIISP_MODE_MODE1 << 30; + model_cfg->sw_aiisp_mode << 30; rkaiisp_write(aidev, AIISP_MI_SLICE_CTRL, value, false); lext_num_sel = ext_tab[model_cfg->sw_aiisp_op_mode][slice_mode[slice_num]]; @@ -1000,7 +1132,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, struct rkaiisp_rmsbuf_info *rmsbuf = &aidev->rmsbuf; struct rkaiisp_dummy_buffer *vpsl_buf; dma_addr_t dma_addr; - u32 width, height; + u32 width, height, stride; u32 sig_width = 0; int buffer_index; int i; @@ -1010,6 +1142,7 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, if (model_cfg->sw_mi_chn_en[i] == 0) continue; + stride = 0; switch (model_cfg->mi_chn_src[i]) { case ISP_IIR: width = CEIL_BY(ispbuf->iir_width, 16); @@ -1022,60 +1155,71 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, width = ispbuf->raw_width[0]; height = ispbuf->raw_height[0]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[0]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[0]; break; case VPSL_YRAW_CHN1: width = ispbuf->raw_width[1]; height = ispbuf->raw_height[1]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[1]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[1]; break; case VPSL_YRAW_CHN2: width = ispbuf->raw_width[2]; height = ispbuf->raw_height[2]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[2]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[2]; break; case VPSL_YRAW_CHN3: width = ispbuf->raw_width[3]; height = ispbuf->raw_height[3]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[3]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[3]; break; case VPSL_YRAW_CHN4: width = ispbuf->raw_width[4]; height = ispbuf->raw_height[4]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[4]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[4]; break; case VPSL_YRAW_CHN5: width = ispbuf->raw_width[5]; height = ispbuf->raw_height[5]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_yraw_offs[5]; + stride = ispbuf->bnr_buf.u.v35.vpsl_yraw_stride[5]; break; case VPSL_SIG_CHN0: width = ispbuf->sig_width[0]; height = ispbuf->sig_height[0]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[0]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[0]; sig_width = width; break; case VPSL_SIG_CHN1: width = ispbuf->sig_width[1]; height = ispbuf->sig_height[1]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[1]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[1]; sig_width = width; break; case VPSL_SIG_CHN2: width = ispbuf->sig_width[2]; height = ispbuf->sig_height[2]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[2]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[2]; sig_width = width; break; case VPSL_SIG_CHN3: width = ispbuf->sig_width[3]; height = ispbuf->sig_height[3]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[3]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[3]; sig_width = width; break; case VPSL_SIG_CHN4: width = ispbuf->sig_width[4]; height = ispbuf->sig_height[4]; dma_addr = vpsl_buf->dma_addr + ispbuf->bnr_buf.u.v35.vpsl_sig_offs[4]; + stride = ispbuf->bnr_buf.u.v35.vpsl_sig_stride[4]; sig_width = width; break; case ISP_AIPRE_NARMAP: @@ -1092,12 +1236,13 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, width = aidev->outbuf_size[aidev->model_runcnt-run_idx].width; height = aidev->outbuf_size[aidev->model_runcnt-run_idx].height; } - dma_addr = aidev->temp_buf[aidev->outbuf_idx].dma_addr; + dma_addr = aidev->lastout_buf[aidev->outbuf_idx]->dma_addr; break; case VICAP_BAYER_RAW: width = rmsbuf->image_width; height = rmsbuf->image_height; - dma_addr = aidev->rms_inbuf[aidev->curr_idxbuf.airms_st.inbuf_idx].dma_addr; + buffer_index = aidev->curr_idxbuf.airms_st.inbuf_idx; + dma_addr = aidev->rms_inbuf[buffer_index].dma_addr; break; case ALLZERO_SIGMA: width = rmsbuf->sigma_width; @@ -1110,6 +1255,12 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, height = rmsbuf->narmap_height; dma_addr = aidev->narmap_buf.dma_addr; break; + case ISP_FINAL_Y: + width = ispbuf->iir_width; + height = ispbuf->iir_height; + buffer_index = aidev->curr_idxbuf.aibnr_st.y_src_index; + dma_addr = aidev->ynrinbuf[buffer_index].dma_addr; + break; default: width = 0; height = 0; @@ -1120,12 +1271,15 @@ static u32 rkaiisp_config_rdchannel(struct rkaiisp_device *aidev, if (width > 0) { aidev->chn_size[i].width = width; aidev->chn_size[i].height = height; + aidev->chn_size[i].stride = stride; rkaiisp_write(aidev, AIISP_MI_RD_CH0_BASE + 0x100 * i, dma_addr, false); rkaiisp_write(aidev, AIISP_MI_RD_CH0_HEIGHT + 0x100 * i, height, false); v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "configure channel %d, width %d, height %d, dma_addr %pad\n", - i, aidev->chn_size[i].width, aidev->chn_size[i].height, &dma_addr); + "configure channel %d, width %d, height %d, stride %d, dma_addr %pad, mi_chn_src %d\n", + i, aidev->chn_size[i].width, aidev->chn_size[i].height, + aidev->chn_size[i].stride, &dma_addr, + model_cfg->mi_chn_src[i]); } } @@ -1147,14 +1301,14 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) int buffer_index; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, - "run frame id: %d, run_idx: %d\n", - sequence, run_idx); + "run frame id: %d, run_idx: %d, model_mode %d\n", + sequence, run_idx, aidev->model_mode); cur_params = (struct rkaiisp_params *)aidev->cur_params->vaddr[0]; model_cfg = &cur_params->model_cfg[run_idx]; @@ -1162,7 +1316,38 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) lastlv = model_cfg->sw_aiisp_level_num - 1; lv_mode = model_cfg->sw_aiisp_lv_mode[lastlv]; out_chns = channels_lut[model_cfg->sw_aiisp_mode][lv_mode]; - if (aidev->model_mode == REMOSAIC_MODE) { + if (aidev->model_mode == AIYNR_MODE) { + if (run_idx == 0) { + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + + outbuf_idx = 0; + aidev->outbuf_idx = outbuf_idx; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, + aidev->lastout_buf[outbuf_idx]->dma_addr, false); + + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + } else if (run_idx < aidev->model_runcnt-1) { + outbuf_idx = aidev->outbuf_idx; + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + + outbuf_idx = (outbuf_idx + 1) % 2; + aidev->outbuf_idx = outbuf_idx; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, + aidev->lastout_buf[outbuf_idx]->dma_addr, false); + } else { + sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); + + buffer_index = aidev->curr_idxbuf.aibnr_st.y_dest_index; + dma_addr = aidev->ynroutbuf[buffer_index].dma_addr; + rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, dma_addr, false); + + rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); + rkaiisp_determine_size(aidev, model_cfg); + } + } else if (aidev->model_mode == REMOSAIC_MODE) { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); dma_addr = aidev->rms_outbuf[aidev->curr_idxbuf.airms_st.outbuf_idx].dma_addr; @@ -1177,7 +1362,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = 0; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, sig_width); rkaiisp_determine_size(aidev, model_cfg); @@ -1190,7 +1375,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = (outbuf_idx + 1) % 2; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); } else { sig_width = rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1213,7 +1398,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = 0; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); rkaiisp_gen_slice_param(aidev, model_cfg, ispbuf->sig_width[3]); rkaiisp_determine_size(aidev, model_cfg); @@ -1229,7 +1414,7 @@ static void rkaiisp_run_cfg(struct rkaiisp_device *aidev, u32 run_idx) outbuf_idx = (outbuf_idx + 1) % 2; aidev->outbuf_idx = outbuf_idx; rkaiisp_write(aidev, AIISP_MI_CHN0_WR_BASE, - aidev->temp_buf[outbuf_idx].dma_addr, false); + aidev->lastout_buf[outbuf_idx]->dma_addr, false); } else { rkaiisp_config_rdchannel(aidev, model_cfg, run_idx); @@ -1307,10 +1492,10 @@ static int rkaiisp_update_buf(struct rkaiisp_device *aidev) } else { ret = 0; aidev->curr_idxbuf = idxbuf; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, "idxbuf fifo out: %d\n", sequence); @@ -1401,10 +1586,10 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) struct rkaiisp_ispbuf_info *ispbuf = &aidev->ispbuf; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = aidev->curr_idxbuf.aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = aidev->curr_idxbuf.airms_st.sequence; + else + sequence = aidev->curr_idxbuf.aibnr_st.sequence; if (!rkaiisp_update_buf(aidev)) { aidev->run_idx = 0; @@ -1413,6 +1598,7 @@ void rkaiisp_trigger(struct rkaiisp_device *aidev) aidev->frm_st = ktime_get_ns(); rkaiisp_get_new_iqparam(aidev); rkaiisp_calc_outbuf_size(aidev, ispbuf->iir_height, ispbuf->iir_width); + rkaiisp_set_lastout_buf(aidev); rkaiisp_run_cfg(aidev, aidev->run_idx); aidev->hwstate = HW_RUNNING; rkaiisp_run_start(aidev); @@ -1425,10 +1611,10 @@ static void rkaiisp_event_queue(struct rkaiisp_device *aidev, union rkaiisp_queu struct v4l2_event event = {0}; int sequence = 0; - if (aidev->exealgo == AIBNR) - sequence = idxbuf->aibnr_st.sequence; - else if (aidev->exealgo == AIRMS) + if (aidev->exealgo == AIRMS) sequence = idxbuf->airms_st.sequence; + else + sequence = idxbuf->aibnr_st.sequence; if (aidev->subdev.is_subs_evt && aidev->exemode != BOTHEVENT_IN_KERNEL) { event.type = RKAIISP_V4L2_EVENT_AIISP_DONE; @@ -1649,6 +1835,9 @@ static long rkaiisp_ioctl_default(struct file *file, void *fh, case RKAIISP_CMD_INIT_AIRMS_BUFPOOL: ret = rkaiisp_init_airms_pool(aidev, arg); break; + case RKAIISP_CMD_GET_YNRBUF_INFO: + ret = rkaiisp_get_ynrbuf_info(aidev, arg); + break; default: ret = -EINVAL; } @@ -1953,3 +2142,54 @@ void rkaiisp_unregister_vdev(struct rkaiisp_device *aidev) vb2_queue_release(vdev->queue); } +int rkaiisp_set_aiynr_ybuf(struct rkaiisp_device *aidev, struct aiisp_aiynr_ybuf_cfg *buf_cfg) +{ + struct rkaiisp_dummy_buffer *ynroutbuf = &aidev->ynroutbuf[0]; + u32 buf_cnt; + int i; + + mutex_lock(&aidev->apilock); + if (aidev->ynr_ybuf_cfg.buf_cnt > 0) + rkaiisp_free_aiynr_ybuf(aidev); + + buf_cnt = buf_cfg->buf_cnt; + if (buf_cnt > RKAIISP_AIYNR_YBUF_NUM_MAX) { + v4l2_err(&aidev->v4l2_dev, + "%s input ynroutbuf cnt(%d) is too big\n", __func__, + buf_cnt); + buf_cnt = RKAIISP_AIYNR_YBUF_NUM_MAX; + } + for (i = 0; i < buf_cnt; i++) { + struct dma_buf_attachment *dba; + struct sg_table *sgt; + + dba = dma_buf_attach(buf_cfg->buf[i], aidev->hw_dev->dev); + if (IS_ERR(dba)) { + mutex_unlock(&aidev->apilock); + return PTR_ERR(dba); + } + + sgt = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + dma_buf_detach(buf_cfg->buf[i], dba); + mutex_unlock(&aidev->apilock); + return PTR_ERR(sgt); + } + ynroutbuf[i].vaddr = NULL; + ynroutbuf[i].dma_addr = sg_dma_address(sgt->sgl); + get_dma_buf(buf_cfg->buf[i]); + ynroutbuf[i].dmabuf = buf_cfg->buf[i]; + ynroutbuf[i].dba = dba; + ynroutbuf[i].sgt = sgt; + v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev, + "%s buf:%pad size:%zu dmabuf:%p\n", __func__, + &ynroutbuf[i].dma_addr, ynroutbuf[i].dmabuf->size, + buf_cfg->buf[i]); + } + + aidev->ynr_ybuf_cfg = *buf_cfg; + mutex_unlock(&aidev->apilock); + + return 0; +} + diff --git a/drivers/media/platform/rockchip/aiisp/aiisp.h b/drivers/media/platform/rockchip/aiisp/aiisp.h index 8c3749b9916f..b45ea78bf38f 100644 --- a/drivers/media/platform/rockchip/aiisp/aiisp.h +++ b/drivers/media/platform/rockchip/aiisp/aiisp.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "hw.h" #define DRIVER_NAME "rkaiisp" @@ -30,7 +31,7 @@ #define RKAIISP_V4L2_EVENT_ELEMS 4 #define RKAIISP_MAX_CHANNEL 7 -#define RKAIISP_TMP_BUF_CNT 2 +#define RKAIISP_LASTOUT_BUF_CNT 2 #define RKAIISP_DEFAULT_MAXRUNCNT 8 #define RKAIISP_DEFAULT_PARASIZE (16 * 1024) #define RKAIISP_SW_REG_SIZE 0x3000 @@ -115,7 +116,9 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer aiprebuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer vpslbuf[RKISP_BUFFER_MAX]; struct rkaiisp_dummy_buffer aiispbuf[RKISP_BUFFER_MAX]; - struct rkaiisp_dummy_buffer temp_buf[RKAIISP_TMP_BUF_CNT]; + struct rkaiisp_dummy_buffer ynrinbuf[RKISP_BUFFER_MAX]; + struct rkaiisp_dummy_buffer temp_buf; + struct rkaiisp_dummy_buffer *lastout_buf[RKAIISP_LASTOUT_BUF_CNT]; u32 outbuf_idx; struct rkaiisp_rmsbuf_info rmsbuf; @@ -124,6 +127,9 @@ struct rkaiisp_device { struct rkaiisp_dummy_buffer sigma_buf; struct rkaiisp_dummy_buffer narmap_buf; + struct aiisp_aiynr_ybuf_cfg ynr_ybuf_cfg; + struct rkaiisp_dummy_buffer ynroutbuf[RKAIISP_AIYNR_YBUF_NUM_MAX]; + struct kfifo idxbuf_kfifo; union rkaiisp_queue_buf curr_idxbuf; @@ -192,8 +198,7 @@ static inline u32 rkaiisp_read(struct rkaiisp_device *aidev, u32 reg, bool is_di } extern struct platform_driver rkaiisp_plat_drv; -int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, union rkaiisp_queue_buf *idxbuf); -void rkaiisp_update_list_reg(struct rkaiisp_device *aidev); +int rkaiisp_set_aiynr_ybuf(struct rkaiisp_device *aidev, struct aiisp_aiynr_ybuf_cfg *buf_cfg); void rkaiisp_trigger(struct rkaiisp_device *aidev); int rkaiisp_get_idxbuf_len(struct rkaiisp_device *aidev); enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis); diff --git a/drivers/media/platform/rockchip/aiisp/hw.c b/drivers/media/platform/rockchip/aiisp/hw.c index dfe1675ac805..02d577adae99 100644 --- a/drivers/media/platform/rockchip/aiisp/hw.c +++ b/drivers/media/platform/rockchip/aiisp/hw.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "regs.h" #include "hw.h" @@ -116,11 +117,11 @@ static int rkaiisp_register_irq(struct rkaiisp_hw_dev *hw_dev) return 0; } -int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) +int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg) { struct rkaiisp_hw_dev *hw_dev = rkaiisp_hwdev; struct rkaiisp_device *aidev = NULL; - union rkaiisp_queue_buf queue_buf; + int dev_id; int i; if (!hw_dev) { @@ -128,9 +129,16 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) return -EINVAL; } + if (!buf_cfg) { + pr_err("Input buf_cfg is NULL!"); + return -EINVAL; + } + + dev_id = buf_cfg->dev_id; for (i = 0; i < hw_dev->dev_num; i++) { if (hw_dev->aidev[i]) { - if ((hw_dev->aidev[i]->is_hw_link) && hw_dev->aidev[i]->dev_id == dev_id) { + if ((hw_dev->aidev[i]->is_hw_link) && + hw_dev->aidev[i]->dev_id == dev_id) { aidev = hw_dev->aidev[i]; break; } @@ -142,15 +150,9 @@ int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf) return -EINVAL; } - if (aidev->exemode != BOTHEVENT_TO_AIQ) { - pr_err("aidev %d exemode(%d) is not right!", dev_id, aidev->exemode); - return -EINVAL; - } - - queue_buf.aibnr_st = *idxbuf; - return rkaiisp_queue_ispbuf(aidev, &queue_buf); + return rkaiisp_set_aiynr_ybuf(aidev, buf_cfg); } -EXPORT_SYMBOL(rkaiisp_ispidx_queue); +EXPORT_SYMBOL(rkaiisp_cfg_aiynr_yuvbuf); static const char * const rv1126b_clks[] = { "clk_aiisp_core", diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index e9275ade2949..8366c88ba176 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -3953,9 +3953,10 @@ static unsigned char get_csi_fmt_val(struct rkcif_stream *stream, csi_fmt_val = CSI_WRDDR_TYPE_RAW12; break; } - } else if (cif_fmt_in->csi_fmt_val == CSI_WRDDR_TYPE_RGB565 || - (stream->cifdev->chip_id < CHIP_RK3576_CIF && - cif_fmt_in->csi_fmt_val == CSI_WRDDR_TYPE_RGB888)) { + } else if (stream->cifdev->chip_id < CHIP_RK3576_CIF && + cif_fmt_in->csi_fmt_val == CSI_WRDDR_TYPE_RGB888) { + csi_fmt_val = CSI_WRDDR_TYPE_YUV422; + } else if (cif_fmt_in->csi_fmt_val == CSI_WRDDR_TYPE_RGB565) { csi_fmt_val = CSI_WRDDR_TYPE_RAW8; } else { csi_fmt_val = cif_fmt_in->csi_fmt_val; @@ -3985,7 +3986,7 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, channel->crop_en = 1; if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888 && dev->chip_id < CHIP_RK3576_CIF) - channel->crop_st_x = 3 * stream->crop[CROP_SRC_ACT].left; + channel->crop_st_x = 3 * stream->crop[CROP_SRC_ACT].left / 2; else if (channel->fmt_val == CSI_WRDDR_TYPE_RGB565) channel->crop_st_x = 2 * stream->crop[CROP_SRC_ACT].left; else @@ -4023,9 +4024,9 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, (dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) || (dev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) { channel->crop_st_x += channel->width / 2; - channel->crop_st_x -= RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->crop_st_x -= dev->unite_extend_pixel; channel->width /= 2; - channel->width += RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->width += dev->unite_extend_pixel; } /* * for mipi or lvds, when enable compact, the virtual width of raw10/raw12 @@ -4056,6 +4057,9 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream, if ((channel->fmt_val == CSI_WRDDR_TYPE_RGB888 && dev->chip_id < CHIP_RK3576_CIF) || channel->fmt_val == CSI_WRDDR_TYPE_RGB565) channel->width = channel->width * fmt->bpp[0] / 8; + + if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888) + channel->width /= 2; /* * rk cif don't support output yuyv fmt data * if user request yuyv fmt, the input mode must be RAW8 @@ -4372,6 +4376,8 @@ static int rkcif_csi_get_output_type_mask(struct rkcif_stream *stream) break; case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: + mask = CSI_WRDDR_TYPE_YUV_PACKET | CSI_YUV_OUTPUT_ORDER_UYVY; + break; case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_BGR666: mask = CSI_WRDDR_TYPE_RAW_COMPACT; @@ -4974,7 +4980,7 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream, channel->vc << 8 | channel->data_type << 10; if (dev->chip_id >= CHIP_RK3588_CIF) { if (channel->csi_fmt_val == CSI_WRDDR_TYPE_RGB888) - val |= CSI_WRDDR_TYPE_RAW8; + val |= CSI_WRDDR_TYPE_YUV422; else if (channel->csi_fmt_val == CSI_WRDDR_TYPE_RAW14_RK3588) val |= channel->csi_fmt_val << 1; else @@ -5269,9 +5275,9 @@ void rkcif_reinit_right_half_config(struct rkcif_stream *stream) return; } channel->crop_st_x += channel->width / 2; - channel->crop_st_x -= RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->crop_st_x -= cif_dev->unite_extend_pixel; channel->width /= 2; - channel->width += RKMOUDLE_UNITE_EXTEND_PIXEL; + channel->width += cif_dev->unite_extend_pixel; channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256); if (cif_dev->chip_id < CHIP_RK3576_CIF) rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl1(channel->id), @@ -6171,6 +6177,7 @@ void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num) if (buf->dbufs.is_init) v4l2_subdev_call(sd, core, ioctl, RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); + rkcif_free_reserved_mem_buf(dev, buf); memset(buf, 0, sizeof(*buf)); buf->dummy.is_free = true; } @@ -6264,7 +6271,7 @@ static u32 rkcif_get_right_half_buf_size(struct rkcif_stream *stream) height = stream->pixm.height; } width /= 2; - width += RKMOUDLE_UNITE_EXTEND_PIXEL; + width += stream->cifdev->unite_extend_pixel; if (stream->is_compact) virtual_width = ALIGN(width * stream->cif_fmt_out->raw_bpp / 8, 256); else @@ -6915,6 +6922,8 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, break; } } + if (can_reset && hw_dev->dummy_buf.vaddr) + rkcif_destroy_dummy_buf(stream); mutex_unlock(&hw_dev->dev_lock); if (dev->can_be_reset && dev->chip_id >= CHIP_RK3588_CIF) { rkcif_do_soft_reset(dev); @@ -6937,8 +6946,6 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, } if (atomic_read(&dev->pipe.stream_cnt) == 0) atomic_set(&stream->sub_stream_buf_cnt, 0); - if (can_reset && hw_dev->dummy_buf.vaddr) - rkcif_destroy_dummy_buf(stream); stream->rounding_bit = 0; if (stream->id == RKCIF_STREAM_MIPI_ID0 && dev->is_support_get_exp) { kfifo_free(&stream->exp_kfifo); @@ -11212,7 +11219,7 @@ static void rkcif_dynamic_crop(struct rkcif_stream *stream) struct csi_channel_info *channel = &cif_dev->channels[stream->id]; if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888) - crop_x = 3 * stream->crop[CROP_SRC_ACT].left; + crop_x = 3 * stream->crop[CROP_SRC_ACT].left / 2; else if (channel->fmt_val == CSI_WRDDR_TYPE_RGB565) crop_x = 2 * stream->crop[CROP_SRC_ACT].left; else @@ -13945,7 +13952,8 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev) detect_stream->fs_cnt_in_single_frame++; if ((!cif_dev->sditf[0] || cif_dev->sditf[0]->mode.rdbk_mode >= RKISP_VICAP_RDBK_AIQ) && - detect_stream->fs_cnt_in_single_frame > 1) + detect_stream->fs_cnt_in_single_frame > 1 && + cif_dev->chip_id < CHIP_RK3588_CIF) return; spin_lock_irqsave(&detect_stream->fps_lock, flags); @@ -14926,6 +14934,17 @@ void rkcif_switch_change(struct rkcif_device *cif_dev, bool is_switch) } } +void rkcif_update_unite_extend_pixel(struct rkcif_device *cif_dev) +{ + struct v4l2_subdev *sd = get_rkisp_sd(cif_dev->sditf[0]); + + if (!sd) + return; + v4l2_subdev_call(sd, core, ioctl, + RKISP_VICAP_CMD_GET_UNITE_EXTEND_PIXEL, + &cif_dev->unite_extend_pixel); +} + /* pingpong irq for rk3588 and next */ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) { diff --git a/drivers/media/platform/rockchip/cif/common.c b/drivers/media/platform/rockchip/cif/common.c index 9f5cdb3e037d..61ec92440b8b 100644 --- a/drivers/media/platform/rockchip/cif/common.c +++ b/drivers/media/platform/rockchip/cif/common.c @@ -343,17 +343,42 @@ int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe { struct rkcif_dummy_buffer *dummy = &buf->dummy; u32 reserved_mem = 0; + struct dma_buf_attachment *dba; + struct sg_table *sgt; + dma_addr_t dma; + int ret = 0; + u32 dma_addr = 0; if (dev->pre_buf_num) reserved_mem = SHARED_MEM_RESERVED_HEAD_SIZE; - dummy->dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx; - if (dummy->dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size) + dma_addr = reserved_mem + dev->resmem_pa + dummy->size * buf->buf_idx; + if (dma_addr + dummy->size > dev->resmem_pa + dev->resmem_size) return -EINVAL; - buf->dbufs.dma = dummy->dma_addr; + buf->dbufs.dma = dma_addr; buf->dbufs.is_resmem = true; - buf->shmem.shm_start = dummy->dma_addr; + buf->shmem.shm_start = dma_addr; buf->shmem.shm_size = dummy->size; dummy->dbuf = rkcif_shm_alloc(&buf->shmem); + buf->dbufs.dbuf = dummy->dbuf; + if (dev->hw_dev->iommu_en) { + dba = dma_buf_attach(dummy->dbuf, dev->hw_dev->dev); + if (IS_ERR(dba)) { + ret = PTR_ERR(dba); + goto err_alloc; + } + dummy->dba = dba; + sgt = dma_buf_map_attachment(dba, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_alloc; + } + dummy->sgt = sgt; + dma = sg_dma_address(sgt->sgl); + get_dma_buf(dummy->dbuf); + dummy->dma_addr = dma; + } else { + dummy->dma_addr = dma_addr; + } if (dummy->is_need_vaddr) { struct iosys_map map; @@ -361,6 +386,11 @@ int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe dummy->vaddr = map.vaddr; } return 0; +err_alloc: + v4l2_info(&dev->v4l2_dev, + "can't match dma_buf 0x%x with iommu\n", + (u32)dummy->dma_addr); + return ret; } void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf) @@ -396,13 +426,30 @@ void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffe if (buf->dbufs.is_init) v4l2_subdev_call(sd, core, ioctl, RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs); + if (dev->hw_dev->iommu_en) { + if (dummy->dba) { + if (dummy->sgt) { + dma_buf_unmap_attachment(dummy->dba, dummy->sgt, + DMA_BIDIRECTIONAL); + dummy->sgt = NULL; + } + dma_buf_detach(dummy->dbuf, dummy->dba); + dma_buf_put(dummy->dbuf); + dummy->dba = NULL; + } + } if (dummy->is_need_vaddr) dummy->dbuf->ops->vunmap(dummy->dbuf, NULL); -#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP - free_reserved_area(phys_to_virt(buf->shmem.shm_start), - phys_to_virt(buf->shmem.shm_start + buf->shmem.shm_size), - -1, "rkisp_thunderboot"); -#endif + dma_buf_put(dummy->dbuf); buf->dummy.is_free = true; } +void rkcif_free_reserved_mem(u32 start, u32 size) +{ +#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP + free_reserved_area(phys_to_virt(start), + phys_to_virt(start + size), + -1, "rkisp_thunderboot"); +#endif +} + diff --git a/drivers/media/platform/rockchip/cif/common.h b/drivers/media/platform/rockchip/cif/common.h index 7bdfe4f40223..8745df4508f8 100644 --- a/drivers/media/platform/rockchip/cif/common.h +++ b/drivers/media/platform/rockchip/cif/common.h @@ -25,6 +25,7 @@ void rkcif_free_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_bu int rkcif_alloc_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf); void rkcif_free_reserved_mem_buf(struct rkcif_device *dev, struct rkcif_rx_buffer *buf); +void rkcif_free_reserved_mem(u32 start, u32 size); #endif /* _RKCIF_COMMON_H */ diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 9d185285814d..eb3dd568ccb8 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -3231,6 +3231,7 @@ static int rkcif_plat_probe(struct platform_device *pdev) dev_set_drvdata(dev, cif_dev); cif_dev->dev = dev; + cif_dev->unite_extend_pixel = 128; if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp)) return -ENODEV; diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 92cf438c9ce5..ad4b059e51dd 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -1073,6 +1073,7 @@ struct rkcif_device { u32 pre_buf_addr[MAX_PRE_BUF_NUM]; u64 pre_buf_timestamp[MAX_PRE_BUF_NUM]; u32 dvp_pin_group; + u32 unite_extend_pixel; struct rkcif_switch_info switch_info; }; @@ -1177,7 +1178,8 @@ void rkcif_free_buf_by_user_require(struct rkcif_device *dev); static inline u64 rkcif_time_get_ns(struct rkcif_device *dev) { if (dev->chip_id == CHIP_RV1106_CIF || - dev->chip_id == CHIP_RV1103B_CIF) + dev->chip_id == CHIP_RV1103B_CIF || + dev->chip_id == CHIP_RV1126B_CIF) return ktime_get_boottime_ns(); else return ktime_get_ns(); @@ -1201,4 +1203,5 @@ void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); int rkcif_sensor_set_power(struct rkcif_stream *stream, int on); void rkcif_switch_change(struct rkcif_device *cif_dev, bool is_switch); +void rkcif_update_unite_extend_pixel(struct rkcif_device *cif_dev); #endif diff --git a/drivers/media/platform/rockchip/cif/hw.c b/drivers/media/platform/rockchip/cif/hw.c index f4207b56b352..814c4555bc09 100644 --- a/drivers/media/platform/rockchip/cif/hw.c +++ b/drivers/media/platform/rockchip/cif/hw.c @@ -2076,8 +2076,8 @@ static void __exit rk_cif_plat_drv_exit(void) rkcif_csi2_hw_plat_drv_exit(); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) -subsys_initcall(rk_cif_plat_drv_init); +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) +subsys_initcall_sync(rk_cif_plat_drv_init); #else #if !defined(CONFIG_VIDEO_REVERSE_IMAGE) module_init(rk_cif_plat_drv_init); diff --git a/drivers/media/platform/rockchip/cif/hw.h b/drivers/media/platform/rockchip/cif/hw.h index 537dc154b329..c0ecbf2ab78c 100644 --- a/drivers/media/platform/rockchip/cif/hw.h +++ b/drivers/media/platform/rockchip/cif/hw.h @@ -81,6 +81,8 @@ struct rkcif_dummy_buffer { struct vb2_queue vb2_queue; struct list_head list; struct dma_buf *dbuf; + struct dma_buf_attachment *dba; + struct sg_table *sgt; dma_addr_t dma_addr; struct page **pages; void *mem_priv; diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index ea27600dfda6..a9241ff17163 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -98,6 +98,7 @@ static void sditf_buffree_work(struct work_struct *work) if (rx_buf) { list_del(&rx_buf->list_free); rkcif_free_reserved_mem_buf(priv->cif_dev, rx_buf); + rkcif_free_reserved_mem(rx_buf->shmem.shm_start, rx_buf->shmem.shm_size); memset(rx_buf, 0, sizeof(*rx_buf)); rx_buf->dummy.is_free = true; } @@ -215,7 +216,7 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd, out_fmt = rkcif_find_output_fmt(NULL, pixm.pixelformat); if (priv->toisp_inf.link_mode == TOISP_UNITE && - ((pixm.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL) * out_fmt->raw_bpp / 8) & 0xf) + ((pixm.width / 2 - cif_dev->unite_extend_pixel) * out_fmt->raw_bpp / 8) & 0xf) is_uncompact = true; v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, @@ -807,7 +808,7 @@ static int sditf_channel_enable_rv1103b(struct sditf_priv *priv, int user) if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && priv->toisp_inf.link_mode == TOISP_UNITE) { if (capture_info->multi_dev.dev_num != 2 || - capture_info->multi_dev.pixel_offset != RKMOUDLE_UNITE_EXTEND_PIXEL) { + capture_info->multi_dev.pixel_offset != cif_dev->unite_extend_pixel) { v4l2_err(&cif_dev->v4l2_dev, "param error of online mode, combine dev num %d, offset %d\n", capture_info->multi_dev.dev_num, @@ -878,9 +879,9 @@ static int sditf_channel_enable_rv1103b(struct sditf_priv *priv, int user) if (user == 0) { if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE_UNITE) { width /= 2; - width += RKMOUDLE_UNITE_EXTEND_PIXEL; + width += cif_dev->unite_extend_pixel; } else if (priv->toisp_inf.link_mode == TOISP_UNITE) { - width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = priv->cap_info.width / 2 + cif_dev->unite_extend_pixel; } rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_ch0); rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP, @@ -935,7 +936,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE && priv->toisp_inf.link_mode == TOISP_UNITE) { if (capture_info->multi_dev.dev_num != 2 || - capture_info->multi_dev.pixel_offset != RKMOUDLE_UNITE_EXTEND_PIXEL) { + capture_info->multi_dev.pixel_offset != cif_dev->unite_extend_pixel) { v4l2_err(&cif_dev->v4l2_dev, "param error of online mode, combine dev num %d, offset %d\n", capture_info->multi_dev.dev_num, @@ -1012,7 +1013,7 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) ctrl_val |= BIT(28); if (user == 0) { if (priv->toisp_inf.link_mode == TOISP_UNITE) - width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = priv->cap_info.width / 2 + cif_dev->unite_extend_pixel; rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val); if (width && height) { rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP, @@ -1027,8 +1028,8 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user) if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) offset_x = 0; else - offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; - width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + offset_x = priv->cap_info.width / 2 - cif_dev->unite_extend_pixel; + width = priv->cap_info.width / 2 + cif_dev->unite_extend_pixel; } rkcif_write_register(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val); if (width && height) { @@ -1321,6 +1322,8 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on) if (on && atomic_inc_return(&priv->power_cnt) > 1) return 0; + if (on) + rkcif_update_unite_extend_pixel(cif_dev); if (cif_dev->chip_id >= CHIP_RK3588_CIF) { v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "%s, toisp mode %d, hdr %d, set power %d\n", @@ -1444,7 +1447,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, if (cif_dev->is_thunderboot || cif_dev->is_rtt_suspend || cif_dev->is_aov_reserved) - dma_sync_single_for_device(cif_dev->dev, + dma_sync_single_for_device(cif_dev->hw_dev->dev, rx_buf->dummy.dma_addr + rx_buf->dummy.size - stream->pixm.plane_fmt[0].bytesperline * 3, stream->pixm.plane_fmt[0].bytesperline * 3, @@ -1453,6 +1456,7 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, cif_dev->hw_dev->mem_ops->prepare(rx_buf->dummy.mem_priv); } } + spin_unlock_irqrestore(&stream->vbq_lock, flags); if (dbufs->is_switch && dbufs->type == BUF_SHORT) { if (stream->is_in_vblank || !stream->dma_en) { @@ -1465,7 +1469,6 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "switch to online mode\n"); } - spin_unlock_irqrestore(&stream->vbq_lock, flags); spin_lock_irqsave(&stream->cifdev->stream_spinlock, flags); stream->is_finish_single_cap = true; diff --git a/drivers/media/platform/rockchip/isp/capture.c b/drivers/media/platform/rockchip/isp/capture.c index b62ec33a73df..64bb515f30c9 100644 --- a/drivers/media/platform/rockchip/isp/capture.c +++ b/drivers/media/platform/rockchip/isp/capture.c @@ -744,11 +744,12 @@ struct capture_fmt *find_fmt(struct rkisp_stream *stream, const u32 pixelfmt) } static void restrict_rsz_resolution(struct rkisp_stream *stream, - const struct stream_config *cfg, + u32 dest_w, u32 dest_h, struct v4l2_rect *max_rsz) { struct rkisp_device *dev = stream->ispdev; struct v4l2_rect *input_win = rkisp_get_isp_sd_win(&dev->isp_sdev); + const struct stream_config *cfg = stream->config; if (stream->id == RKISP_STREAM_VIR || stream->id == RKISP_STREAM_LDC || @@ -769,14 +770,24 @@ static void restrict_rsz_resolution(struct rkisp_stream *stream, max_rsz->width = ALIGN(DIV_ROUND_UP(input_win->width, div), 4); max_rsz->height = DIV_ROUND_UP(input_win->height, div); - } else if (dev->hw_dev->unite) { + } else if (dev->unite_div > ISP_UNITE_DIV1) { /* scale down only for unite mode */ - max_rsz->width = min_t(int, input_win->width, cfg->max_rsz_width); - max_rsz->height = min_t(int, input_win->height, cfg->max_rsz_height); + if (dest_w == input_win->width && dest_h == input_win->height) { + max_rsz->width = dest_w; + max_rsz->height = dest_h; + } else { + max_rsz->width = min_t(int, input_win->width, cfg->max_rsz_width); + max_rsz->height = min_t(int, input_win->height, cfg->max_rsz_height); + } } else { /* scale up/down */ - max_rsz->width = cfg->max_rsz_width; - max_rsz->height = cfg->max_rsz_height; + if (dest_w == input_win->width && dest_h == input_win->height) { + max_rsz->width = dest_w; + max_rsz->height = dest_h; + } else { + max_rsz->width = cfg->max_rsz_width; + max_rsz->height = cfg->max_rsz_height; + } } } @@ -817,7 +828,7 @@ static int rkisp_set_fmt(struct rkisp_stream *stream, } /* do checks on resolution */ - restrict_rsz_resolution(stream, config, &max_rsz); + restrict_rsz_resolution(stream, pixm->width, pixm->height, &max_rsz); if (stream->id == RKISP_STREAM_MP || stream->id == RKISP_STREAM_SP || (stream->id == RKISP_STREAM_BP && dev->isp_ver != ISP_V30)) { @@ -1087,7 +1098,6 @@ static int rkisp_enum_framesizes(struct file *file, void *prov, struct v4l2_frmsizeenum *fsize) { struct rkisp_stream *stream = video_drvdata(file); - const struct stream_config *config = stream->config; struct v4l2_frmsize_stepwise *s = &fsize->stepwise; struct v4l2_frmsize_discrete *d = &fsize->discrete; struct rkisp_device *dev = stream->ispdev; @@ -1100,7 +1110,7 @@ static int rkisp_enum_framesizes(struct file *file, void *prov, if (!find_fmt(stream, fsize->pixel_format)) return -EINVAL; - restrict_rsz_resolution(stream, config, &max_rsz); + restrict_rsz_resolution(stream, 0, 0, &max_rsz); if (stream->out_isp_fmt.fmt_type == FMT_BAYER || stream->id == RKISP_STREAM_FBC || diff --git a/drivers/media/platform/rockchip/isp/capture.h b/drivers/media/platform/rockchip/isp/capture.h index 264320b8e97f..6f908ca3e4b4 100644 --- a/drivers/media/platform/rockchip/isp/capture.h +++ b/drivers/media/platform/rockchip/isp/capture.h @@ -244,6 +244,7 @@ struct streams_ops { int (*set_wrap)(struct rkisp_stream *stream, int line); int (*isp_end)(struct rkisp_stream *stream, u32 irq); int (*switch_grey)(struct rkisp_stream *stream); + void (*push_buf)(struct rkisp_stream *stream); }; struct rockit_isp_ops { @@ -286,12 +287,15 @@ struct rkisp_stream { struct stream_config *config; spinlock_t vbq_lock; struct list_head buf_queue; + struct list_head buf_queue_tmp; struct rkisp_buffer *curr_buf; struct rkisp_buffer *next_buf; struct rkisp_dummy_buffer dummy_buf; struct mutex apilock; struct tasklet_struct buf_done_tasklet; struct list_head buf_done_list; + struct dma_buf *dbuf_pool[VIDEO_MAX_FRAME]; + bool is_rockit_buf; bool streaming; bool stopping; bool frame_end; diff --git a/drivers/media/platform/rockchip/isp/capture_v35.c b/drivers/media/platform/rockchip/isp/capture_v35.c index 232cc1b797dd..1c014e65b3cc 100644 --- a/drivers/media/platform/rockchip/isp/capture_v35.c +++ b/drivers/media/platform/rockchip/isp/capture_v35.c @@ -10,8 +10,10 @@ #include #include #include +#include #include "dev.h" #include "regs.h" +#include "isp_params_v35.h" /* ISP35 * |-->mainpath------------------->ddr @@ -726,12 +728,20 @@ static void update_mi(struct rkisp_stream *stream) struct rkisp_device *dev = stream->ispdev; struct rkisp_dummy_buffer *dummy_buf = &stream->dummy_buf; struct v4l2_pix_format_mplane *out_fmt = &stream->out_fmt; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; u32 div = stream->out_isp_fmt.fourcc == V4L2_PIX_FMT_UYVY ? 1 : 2; u32 val, reg; if (stream->next_buf) { reg = stream->config->mi.y_base_ad_init; - val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + if (dev->is_aiisp_yuv && stream->id == RKISP_STREAM_MP) { + val = priv->y_src_idx; + priv->pbuf_y_src = &priv->buf_y_src[val]; + priv->y_src_idx = (val + 1) % priv->y_src_cnt; + val = priv->pbuf_y_src->dma_addr; + } else { + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + } rkisp_write(dev, reg, val, false); reg = stream->config->mi.cb_base_ad_init; @@ -760,6 +770,32 @@ static void update_mi(struct rkisp_stream *stream) rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT, false); } + if (dev->unite_div == ISP_UNITE_DIV4) { + /* left bottom of image */ + reg = stream->config->mi.y_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + val += (out_fmt->plane_fmt[0].bytesperline * out_fmt->height / 2); + rkisp_idx_write(dev, reg, val, ISP_UNITE_LEFT_B, false); + + reg = stream->config->mi.cb_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CB]; + val += (out_fmt->plane_fmt[1].sizeimage / 2); + rkisp_idx_write(dev, reg, val, ISP_UNITE_LEFT_B, false); + + /* right bottom of image */ + reg = stream->config->mi.y_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_Y]; + val += (out_fmt->plane_fmt[0].bytesperline * out_fmt->height / 2) + + ((out_fmt->width / div) & ~0xf); + rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT_B, false); + + reg = stream->config->mi.cb_base_ad_init; + val = stream->next_buf->buff_addr[RKISP_PLANE_CB]; + val += (out_fmt->plane_fmt[1].sizeimage / 2) + + ((out_fmt->width / div) & ~0xf); + rkisp_idx_write(dev, reg, val, ISP_UNITE_RIGHT_B, false); + } + if (stream->is_pause) { /* single sensor mode with pingpong buffer: * if mi on, addr will auto update at frame end @@ -777,6 +813,10 @@ static void update_mi(struct rkisp_stream *stream) if (!stream->curr_buf) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } /* maybe no next buf to preclose mi */ stream->ops->disable_mi(stream); @@ -798,6 +838,10 @@ static void update_mi(struct rkisp_stream *stream) if (!dev->hw_dev->is_single) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } } else if (dummy_buf->mem_priv) { val = dummy_buf->dma_addr; @@ -896,6 +940,26 @@ static int sp_switch_grey(struct rkisp_stream *stream) return 0; } +static void mp_push_buf(struct rkisp_stream *stream) +{ + unsigned long lock_flags = 0; + struct rkisp_buffer *buf = NULL; + + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + if (!list_empty(&stream->buf_queue_tmp)) { + buf = list_first_entry(&stream->buf_queue_tmp, + struct rkisp_buffer, queue); + list_del(&buf->queue); + } + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + if (buf) { + if (buf->vb.vb2_buf.memory) + rkisp_stream_buf_done(stream, buf); + else + rkisp_rockit_buf_done(stream, ROCKIT_DVBM_END, buf); + } +} + static struct streams_ops rkisp_mp_streams_ops = { .config_mi = mp_config_mi, .enable_mi = mp_enable_mi, @@ -907,6 +971,7 @@ static struct streams_ops rkisp_mp_streams_ops = { .frame_start = mi_frame_start, .set_wrap = mp_set_wrap, .switch_grey = mp_switch_grey, + .push_buf = mp_push_buf, }; static struct streams_ops rkisp_sp_streams_ops = { @@ -924,6 +989,7 @@ static struct streams_ops rkisp_sp_streams_ops = { static int mi_frame_start(struct rkisp_stream *stream, u32 irq) { struct rkisp_device *dev = stream->ispdev; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; unsigned long lock_flags = 0; /* readback start to update stream buf if null */ @@ -951,6 +1017,10 @@ static int mi_frame_start(struct rkisp_stream *stream, u32 irq) if (!stream->ops->is_stream_stopped(stream)) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; if (!list_empty(&stream->buf_queue)) { stream->next_buf = list_first_entry(&stream->buf_queue, struct rkisp_buffer, queue); @@ -977,6 +1047,7 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state) { struct rkisp_device *dev = stream->ispdev; struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + struct rkisp_isp_params_val_v35 *priv = dev->params_vdev.priv_val; unsigned long lock_flags = 0; struct rkisp_buffer *buf = NULL; u32 i, seq; @@ -1069,6 +1140,13 @@ static int mi_frame_end(struct rkisp_stream *stream, u32 state) stream->dbg.timestamp = ns; stream->dbg.id = seq; + if (stream->id == RKISP_STREAM_MP && dev->is_aiisp_yuv) { + spin_lock_irqsave(&stream->vbq_lock, lock_flags); + list_add_tail(&buf->queue, &stream->buf_queue_tmp); + spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); + goto end; + } + if (vir->streaming && vir->conn_id == stream->id) { spin_lock_irqsave(&vir->vbq_lock, lock_flags); list_add_tail(&buf->queue, &dev->cap_dev.vir_cpy.queue); @@ -1090,6 +1168,10 @@ end: if (stream->next_buf) { stream->curr_buf = stream->next_buf; stream->next_buf = NULL; + if (dev->is_aiisp_yuv && + priv->pbuf_y_src && + stream->id == RKISP_STREAM_MP) + priv->y_src_cur_idx = priv->pbuf_y_src->index; } if (!list_empty(&stream->buf_queue)) { stream->next_buf = list_first_entry(&stream->buf_queue, @@ -1242,6 +1324,7 @@ static void rkisp_buf_queue(struct vb2_buffer *vb) struct rkisp_device *dev = stream->ispdev; struct v4l2_pix_format_mplane *pixm = &stream->out_fmt; struct capture_fmt *isp_fmt = &stream->out_isp_fmt; + const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops; unsigned long lock_flags = 0; struct sg_table *sgt; u32 height, offset; @@ -1282,6 +1365,9 @@ static void rkisp_buf_queue(struct vb2_buffer *vb) v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, "stream:%d queue buf:0x%x\n", stream->id, ispbuf->buff_addr[0]); + ispbuf->index = vb->index; + if (dev->is_aiisp_yuv && stream->dbuf_pool[vb->index]) + stream->dbuf_pool[vb->index] = g_ops->get_dmabuf(vb, vb->planes[0].mem_priv, O_RDWR); spin_lock_irqsave(&stream->vbq_lock, lock_flags); list_add_tail(&ispbuf->queue, &stream->buf_queue); @@ -1330,7 +1416,14 @@ static void destroy_buf_queue(struct rkisp_stream *stream, { unsigned long lock_flags = 0; struct rkisp_buffer *buf; + int i; + for (i = 0; i < VIDEO_MAX_FRAME && !stream->is_rockit_buf; i++) { + if (stream->dbuf_pool[i]) { + dma_buf_put(stream->dbuf_pool[i]); + stream->dbuf_pool[i] = NULL; + } + } spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->curr_buf) { list_add_tail(&stream->curr_buf->queue, &stream->buf_queue); @@ -1349,6 +1442,13 @@ static void destroy_buf_queue(struct rkisp_stream *stream, if (buf->vb.vb2_buf.memory) vb2_buffer_done(&buf->vb.vb2_buf, state); } + while (!list_empty(&stream->buf_queue_tmp)) { + buf = list_first_entry(&stream->buf_queue_tmp, + struct rkisp_buffer, queue); + list_del(&buf->queue); + if (buf->vb.vb2_buf.memory) + vb2_buffer_done(&buf->vb.vb2_buf, state); + } while (!list_empty(&stream->buf_done_list)) { buf = list_first_entry(&stream->buf_done_list, struct rkisp_buffer, queue); @@ -1445,6 +1545,57 @@ static int rkisp_stream_start(struct rkisp_stream *stream) return rkisp_start(stream); } +static int +rkisp_mainpath_buf_to_aiisp(struct rkisp_stream *stream) +{ +#if !IS_REACHABLE(CONFIG_VIDEO_ROCKCHIP_AIISP) + struct rkisp_device *dev = stream->ispdev; + + if (stream->id != RKISP_STREAM_MP || !dev->is_aiisp_yuv) + return 0; + + v4l2_err(&dev->v4l2_dev, + "aiisp is compiled as module, cannot call rkaiisp_cfg_aiynr_yuvbuf\n"); + return -EINVAL; +#else + struct rkisp_device *dev = stream->ispdev; + struct v4l2_rect *isp_out = &dev->isp_sdev.out_crop; + struct v4l2_pix_format_mplane *mp_out = &stream->out_fmt; + struct aiisp_aiynr_ybuf_cfg cfg = { 0 }; + int cnt = 0, ret = -EINVAL; + + if (stream->id != RKISP_STREAM_MP || !dev->is_aiisp_yuv) + return 0; + if (dev->cap_dev.wrap_line) { + v4l2_err(&dev->v4l2_dev, "aiynr no support for wrap\n"); + goto err; + } + if (isp_out->width != mp_out->width || + isp_out->height != mp_out->height) { + v4l2_err(&dev->v4l2_dev, "aiynr no support for mainpath scale\n"); + goto err; + } + cfg.dev_id = dev->dev_id; + cfg.width = mp_out->width; + cfg.height = mp_out->height; + for (cnt = 0; cnt < VIDEO_MAX_FRAME; cnt++) { + if (!stream->dbuf_pool[cnt] || cnt >= RKAIISP_AIYNR_YBUF_NUM_MAX) + break; + cfg.buf[cnt] = stream->dbuf_pool[cnt]; + } + if (cnt) { + cfg.buf_cnt = cnt; + ret = rkaiisp_cfg_aiynr_yuvbuf(&cfg); + if (ret) + v4l2_err(&dev->v4l2_dev, "aiynr yuv buf config error:%d\n", ret); + } else { + v4l2_err(&dev->v4l2_dev, "mainpath no dma buf for aiisp\n"); + } +err: + return ret; +#endif +} + static int rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -1517,6 +1668,9 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count) goto buffer_done; } + if (rkisp_mainpath_buf_to_aiisp(stream)) + goto destroy_dummy_buf; + /* enable clocks/power-domains */ ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true); if (ret < 0) { @@ -1609,6 +1763,7 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id) vdev = &stream->vnode.vdev; INIT_LIST_HEAD(&stream->buf_queue); + INIT_LIST_HEAD(&stream->buf_queue_tmp); init_waitqueue_head(&stream->done); spin_lock_init(&stream->vbq_lock); stream->linked = true; @@ -1618,6 +1773,8 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id) strscpy(vdev->name, SP_VDEV_NAME, sizeof(vdev->name)); stream->ops = &rkisp_sp_streams_ops; stream->config = &rkisp_sp_stream_cfg; + if (dev->hw_dev->unite) + stream->config->max_rsz_width *= 2; break; case RKISP_STREAM_VIR: strscpy(vdev->name, VIR_VDEV_NAME, sizeof(vdev->name)); @@ -1629,6 +1786,10 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id) strscpy(vdev->name, MP_VDEV_NAME, sizeof(vdev->name)); stream->ops = &rkisp_mp_streams_ops; stream->config = &rkisp_mp_stream_cfg; + if (dev->hw_dev->unite) { + stream->config->max_rsz_width = CIF_ISP_INPUT_W_MAX_V35_UNITE; + stream->config->max_rsz_height = CIF_ISP_INPUT_H_MAX_V35_UNITE; + } } rockit_isp_ops.rkisp_stream_start = rkisp_stream_start; diff --git a/drivers/media/platform/rockchip/isp/common.c b/drivers/media/platform/rockchip/isp/common.c index 4ef7250dc48e..a4e1d5f22eae 100644 --- a/drivers/media/platform/rockchip/isp/common.c +++ b/drivers/media/platform/rockchip/isp/common.c @@ -535,7 +535,7 @@ u64 rkisp_time_get_ns(struct rkisp_device *dev) { u64 ns; - if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V33) + if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V33 || dev->isp_ver == ISP_V35) ns = ktime_get_boottime_ns(); else ns = ktime_get_ns(); diff --git a/drivers/media/platform/rockchip/isp/common.h b/drivers/media/platform/rockchip/isp/common.h index 73d7b7858f98..1ef1aaae8a5d 100644 --- a/drivers/media/platform/rockchip/isp/common.h +++ b/drivers/media/platform/rockchip/isp/common.h @@ -123,6 +123,7 @@ struct rkisp_buffer { void *vaddr[VIDEO_MAX_PLANES]; u32 buff_addr[VIDEO_MAX_PLANES]; int dev_id; + int index; void *other; }; diff --git a/drivers/media/platform/rockchip/isp/dev.c b/drivers/media/platform/rockchip/isp/dev.c index 2544cf318b0f..387b7116d2bf 100644 --- a/drivers/media/platform/rockchip/isp/dev.c +++ b/drivers/media/platform/rockchip/isp/dev.c @@ -351,8 +351,7 @@ static int rkisp_pipeline_open(struct rkisp_pipeline *p, rkisp_csi_config_patch(dev, false); dev->is_aiisp_sync = false; if (dev->is_aiisp_en && - ((dev->isp_ver == ISP_V35 && !hw->is_single) || - (dev->isp_ver == ISP_V39 && (dev->isp_inp & INP_RAWRD2 || dev->is_rdbk_auto)))) + (!hw->is_single || IS_HDR_RDBK(dev->rd_mode))) dev->is_aiisp_sync = true; return 0; err: diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 1dafd16c183d..c641eba2e9ac 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -311,7 +311,10 @@ struct rkisp_device { bool is_suspend_one_frame; bool is_aiisp_en; bool is_aiisp_upd; + bool is_aiisp_stopping; + bool is_aiisp_stop; bool is_aiisp_sync; + bool is_aiisp_yuv; bool is_frm_rd; bool is_multi_one_sync; bool is_wait_aiq; @@ -321,6 +324,8 @@ struct rkisp_device { struct rkisp_vicap_sof vicap_sof; u32 hdr_wrap_line; + u32 aiisp_stop_seq; + u8 multi_mode; u8 multi_index; u8 rawaf_irq_cnt; diff --git a/drivers/media/platform/rockchip/isp/dmarx.c b/drivers/media/platform/rockchip/isp/dmarx.c index 1282c7bf33b8..40df35dda320 100644 --- a/drivers/media/platform/rockchip/isp/dmarx.c +++ b/drivers/media/platform/rockchip/isp/dmarx.c @@ -396,7 +396,7 @@ static void update_rawrd(struct rkisp_stream *stream) struct rkisp_device *dev = stream->ispdev; void __iomem *base = dev->base_addr; struct capture_fmt *fmt = &stream->out_isp_fmt; - u32 offs, offs_h = stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 offs, offs_h = stream->out_fmt.width / 2 - dev->hw_dev->unite_extend_pixel; u32 val = 0; if (stream->curr_buf) { @@ -417,7 +417,7 @@ static void update_rawrd(struct rkisp_stream *stream) val + offs_h, ISP_UNITE_RIGHT, false); if (dev->unite_div == ISP_UNITE_DIV4) { offs = stream->out_fmt.plane_fmt[0].bytesperline * - (stream->out_fmt.height / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL); + (stream->out_fmt.height / 2 - dev->hw_dev->unite_extend_pixel); rkisp_idx_write(dev, stream->config->mi.y_base_ad_init, val + offs, ISP_UNITE_LEFT_B, false); offs += offs_h; @@ -1218,9 +1218,9 @@ void rkisp_rawrd_set_pic_size(struct rkisp_device *dev, w = width; h = height; if (dev->unite_div > ISP_UNITE_DIV1) - w = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = height / 2 + dev->hw_dev->unite_extend_pixel; /* isp20 extend line for normal read back mode to fix internal bug */ if (dev->isp_ver == ISP_V20 && diff --git a/drivers/media/platform/rockchip/isp/hw.c b/drivers/media/platform/rockchip/isp/hw.c index 091e905d4583..d1a8f6ffa8d2 100644 --- a/drivers/media/platform/rockchip/isp/hw.c +++ b/drivers/media/platform/rockchip/isp/hw.c @@ -1367,6 +1367,9 @@ static int rkisp_hw_probe(struct platform_device *pdev) } else { hw_dev->unite = ISP_UNITE_NONE; } + hw_dev->unite_extend_pixel = 128; + if (hw_dev->isp_ver == ISP_V33 || hw_dev->isp_ver == ISP_V35) + hw_dev->unite_extend_pixel = 512; hw_dev->vpsl_base_addr = NULL; if (hw_dev->isp_ver == ISP_V35) { @@ -1396,7 +1399,7 @@ static int rkisp_hw_probe(struct platform_device *pdev) hw_dev->max_in.is_fix = true; if (hw_dev->unite) { hw_dev->max_in.w /= 2; - hw_dev->max_in.w += RKMOUDLE_UNITE_EXTEND_PIXEL; + hw_dev->max_in.w += hw_dev->unite_extend_pixel; } } dev_info(dev, "max input:%dx%d@%dfps\n", @@ -1554,9 +1557,9 @@ void rkisp_hw_enum_isp_size(struct rkisp_hw_dev *hw_dev) w = isp->isp_sdev.in_crop.width; h = isp->isp_sdev.in_crop.height; if (isp->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + hw_dev->unite_extend_pixel; if (isp->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + hw_dev->unite_extend_pixel; hw_dev->isp_size[i].w = w; hw_dev->isp_size[i].h = h; hw_dev->isp_size[i].size = w * h; @@ -1679,8 +1682,8 @@ static void __exit rkisp_hw_drv_exit(void) platform_driver_unregister(&rkisp_hw_drv); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) -subsys_initcall(rkisp_hw_drv_init); +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) +subsys_initcall_sync(rkisp_hw_drv_init); #else module_init(rkisp_hw_drv_init); #endif diff --git a/drivers/media/platform/rockchip/isp/hw.h b/drivers/media/platform/rockchip/isp/hw.h index 9314e72870da..d70f8a4d5286 100644 --- a/drivers/media/platform/rockchip/isp/hw.h +++ b/drivers/media/platform/rockchip/isp/hw.h @@ -93,6 +93,7 @@ struct rkisp_hw_dev { u64 iq_feature; int buf_init_cnt; u32 unite; + u32 unite_extend_pixel; bool is_feature_on; bool is_dma_contig; bool is_dma_sg_ops; diff --git a/drivers/media/platform/rockchip/isp/isp_external.h b/drivers/media/platform/rockchip/isp/isp_external.h index 73c5bd815987..8ca72c1d1805 100644 --- a/drivers/media/platform/rockchip/isp/isp_external.h +++ b/drivers/media/platform/rockchip/isp/isp_external.h @@ -33,6 +33,9 @@ #define RKISP_VICAP_CMD_MULTI_ONLINE \ _IOW('V', BASE_VIDIOC_PRIVATE + 8, int) +#define RKISP_VICAP_CMD_GET_UNITE_EXTEND_PIXEL \ + _IOR('V', BASE_VIDIOC_PRIVATE + 9, int) + #define RKISP_VICAP_BUF_CNT 3 #define RKISP_VICAP_BUF_CNT_MAX 8 #define RKISP_RX_BUF_POOL_MAX (RKISP_VICAP_BUF_CNT_MAX * 3) diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 5ed7da6e64c5..efbf9221835a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -304,13 +304,18 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) params_vdev->first_cfg_params = true; return; } - rkisp_params_disable_isp(params_vdev); /* clean module params */ params_vdev->ops->clear_first_param(params_vdev); params_vdev->rdbk_times = 0; - if (!(dev->isp_state & ISP_START)) + if (params_vdev->is_first_cfg) { rkisp_params_stream_stop(params_vdev); - + params_vdev->is_first_cfg = false; + } + dev->is_aiisp_yuv = false; + dev->is_aiisp_en = false; + dev->is_aiisp_stop = false; + dev->is_aiisp_stopping = false; + memset(&dev->aiisp_cfg, 0, sizeof(dev->aiisp_cfg)); dev->fpn_cfg.en = 0; if (dev->fpn_cfg.buf) { vfree(dev->fpn_cfg.buf); @@ -565,10 +570,12 @@ void rkisp_params_meshbuf_free(struct rkisp_isp_params_vdev *params_vdev, u64 id void rkisp_params_stream_stop(struct rkisp_isp_params_vdev *params_vdev) { + rkisp_params_disable_isp(params_vdev); /* isp stop to free buf */ if (params_vdev->ops->stream_stop) params_vdev->ops->stream_stop(params_vdev); - params_vdev->first_cfg_params = false; + if (!atomic_read(¶ms_vdev->open_cnt) && params_vdev->ops->fop_release) + params_vdev->ops->fop_release(params_vdev); } bool rkisp_params_check_bigmode(struct rkisp_isp_params_vdev *params_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_params.h b/drivers/media/platform/rockchip/isp/isp_params.h index cec291be2d3b..ffb76c28a824 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.h +++ b/drivers/media/platform/rockchip/isp/isp_params.h @@ -59,6 +59,7 @@ struct rkisp_isp_params_ops { int (*aiisp_start)(struct rkisp_isp_params_vdev *params_vdev, struct rkisp_aiisp_st *st); int (*get_aiawb_buffd)(struct rkisp_isp_params_vdev *params_vdev, void *arg); void (*vpsl_update_regs)(struct rkisp_isp_params_vdev *params_vdev); + void (*aiisp_switch)(struct rkisp_isp_params_vdev *params_vdev, bool on); }; /* diff --git a/drivers/media/platform/rockchip/isp/isp_params_v32.c b/drivers/media/platform/rockchip/isp/isp_params_v32.c index 2dff0a748a4a..50d7631c2f39 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v32.c @@ -1085,9 +1085,9 @@ isp_rawaf_config(struct rkisp_isp_params_vdev *params_vdev, struct isp2x_window win_ae; if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; for (i = 0; i < num_of_win; i++) { h_size = arg->win[i].h_size; @@ -1347,9 +1347,9 @@ isp_rawaelite_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWAE_LITE_OFFSET, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -1445,9 +1445,9 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWAE_BIG_OFFSET, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; if (!h_size || h_size + h_offs + 1 > width) @@ -1625,9 +1625,9 @@ isp_rawawb_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWAWB_WIN_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->h_size; v_size = arg->v_size; @@ -2310,9 +2310,9 @@ isp_rawhstlite_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWHIST_LITE_OFFS, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -2468,9 +2468,9 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWHIST_BIG_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -4413,9 +4413,9 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, bool is_alloc; if (dev->unite_div > ISP_UNITE_DIV1) - w = ALIGN(isp_sdev->in_crop.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + w = ALIGN(isp_sdev->in_crop.width / 2 + dev->hw_dev->unite_extend_pixel, 16); if (dev->unite_div == ISP_UNITE_DIV4) - h = ALIGN(isp_sdev->in_crop.height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + h = ALIGN(isp_sdev->in_crop.height / 2 + dev->hw_dev->unite_extend_pixel, 16); priv_val->is_lo8x8 = (!new_params->others.bay3d_cfg.lo4x8_en && !new_params->others.bay3d_cfg.lo4x4_en); @@ -5066,9 +5066,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, rkisp_free_buffer(params_vdev->dev, buf); } else { is_alloc = false; - buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); - if (buf->dma_fd < 0) + if (rkisp_buf_get_fd(ispdev, buf, false) < 0) goto err; + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; } } if (is_alloc) { @@ -5079,9 +5079,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, goto err; } mesh_head = (struct isp2x_mesh_head *)buf->vaddr; - mesh_head->stat = MESH_BUF_INIT; - mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); } + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); buf++; } diff --git a/drivers/media/platform/rockchip/isp/isp_params_v33.c b/drivers/media/platform/rockchip/isp/isp_params_v33.c index 22a8aa6a32c2..c8207681a8ce 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v33.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v33.c @@ -879,9 +879,9 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWAE_BIG_OFFSET, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -1032,9 +1032,9 @@ isp_rawawb_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWAWB_WIN_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->h_size; v_size = arg->v_size; @@ -1597,9 +1597,9 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWHIST_BIG_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -1967,9 +1967,9 @@ isp_enh_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, value, ctrl, het_aliquant; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; priv_val->enh_col = ALIGN((w + 127) / 128, 4); if (priv_val->enh_col > ISP33_ENH_IIR_COL_MAX) priv_val->enh_col = ISP33_ENH_IIR_COL_MAX; @@ -2094,9 +2094,9 @@ isp_hist_config(struct rkisp_isp_params_vdev *params_vdev, int i; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; ctrl = isp3_param_read(params_vdev, ISP33_HIST_CTRL, id); ctrl &= ISP33_MODULE_EN; @@ -3807,9 +3807,9 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, bool is_alloc; if (dev->unite_div > ISP_UNITE_DIV1) - w = ALIGN(isp_sdev->in_crop.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + w = ALIGN(isp_sdev->in_crop.width / 2 + dev->hw_dev->unite_extend_pixel, 16); if (dev->unite_div == ISP_UNITE_DIV4) - h = isp_sdev->in_crop.height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = isp_sdev->in_crop.height / 2 + dev->hw_dev->unite_extend_pixel; if (!iirsparse_en) { hsize = w * 3 / 2 + w / 4; @@ -4055,9 +4055,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, rkisp_free_buffer(params_vdev->dev, buf); } else { is_alloc = false; - buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); - if (buf->dma_fd < 0) + if (rkisp_buf_get_fd(ispdev, buf, false) < 0) goto err; + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; } } if (is_alloc) { @@ -4068,9 +4068,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, goto err; } mesh_head = (struct isp2x_mesh_head *)buf->vaddr; - mesh_head->stat = MESH_BUF_INIT; - mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); } + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); buf++; } diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index cd9632c08490..9b2a84b44c8e 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -929,9 +929,9 @@ isp_rawaf_config(struct rkisp_isp_params_vdev *params_vdev, size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->win), arg->num_afm_win); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; for (i = 0; i < num_of_win; i++) { h_size = arg->win[i].h_size; @@ -1131,9 +1131,9 @@ isp_rawae_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWAE_BIG_OFFSET, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win0_h_size; v_size = arg->win0_v_size; @@ -1289,9 +1289,9 @@ isp_rawawb_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWAWB_WIN_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->h_size; v_size = arg->v_size; @@ -2026,9 +2026,9 @@ isp_rawhist_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWHIST_BIG_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->h_size; v_size = arg->v_size; @@ -2535,7 +2535,7 @@ isp_gic_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) static void isp_enh_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, - const struct isp33_enh_cfg *arg, bool is_check, u32 id) + const struct isp35_enh_cfg *arg, bool is_check, u32 id) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; u32 i, j, val, ctrl = isp3_param_read(params_vdev, ISP33_ENH_CTRL, id); @@ -2559,10 +2559,10 @@ isp_enh_cfg_sram(struct rkisp_isp_params_vdev *params_vdev, static void isp_enh_config(struct rkisp_isp_params_vdev *params_vdev, - const struct isp33_enh_cfg *arg, u32 id) + const struct isp35_enh_cfg *arg, u32 id) { struct isp35_isp_params_cfg *params_rec = params_vdev->isp35_params + id; - struct isp33_enh_cfg *arg_rec = ¶ms_rec->others.enh_cfg; + struct isp35_enh_cfg *arg_rec = ¶ms_rec->others.enh_cfg; struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop; @@ -2570,9 +2570,9 @@ isp_enh_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, value, ctrl, het_aliquant; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; priv->enh_col = ALIGN((w + 127) / 128, 4); if (priv->enh_col > ISP35_ENH_IIR_COL_MAX) priv->enh_col = ISP33_ENH_IIR_COL_MAX; @@ -2640,7 +2640,7 @@ isp_enh_config(struct rkisp_isp_params_vdev *params_vdev, if (dev->hw_dev->is_single && arg->iir_wr) isp_enh_cfg_sram(params_vdev, arg, false, id); else if (arg->iir_wr) - memcpy(arg_rec, arg, sizeof(struct isp33_enh_cfg)); + memcpy(arg_rec, arg, sizeof(struct isp35_enh_cfg)); } static void @@ -2697,9 +2697,9 @@ isp_hist_config(struct rkisp_isp_params_vdev *params_vdev, int i; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; ctrl = isp3_param_read(params_vdev, ISP33_HIST_CTRL, id); ctrl &= ISP35_MODULE_EN; @@ -4366,18 +4366,19 @@ isp_rgbir_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) isp3_param_write(params_vdev, value, ISP39_RGBIR_CTRL, id); } -static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) +static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev, + struct rkisp_dummy_buffer *pbuf, bool is_force) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; u32 i, val, ds_cnt; - if (!priv->pbuf_vpsl) + if (!pbuf) return; - priv->vpsl_cur_idx = priv->pbuf_vpsl->index; + priv->vpsl_idx = pbuf->index; ds_cnt = priv->yraw_sel ? VPSL_YRAW_CHN_MAX / 2 : VPSL_YRAW_CHN_MAX; for (i = 0; i < ds_cnt; i++) { - val = priv->pbuf_vpsl->dma_addr + priv->vpsl_yraw_offs[i]; + val = pbuf->dma_addr + priv->vpsl_yraw_offs[i]; vpsl_write(dev, VPSL_MI_CHN0_WR_BASE + i * 0x100, val, false); val = priv->vpsl_yraw_stride[i]; vpsl_write(dev, VPSL_MI_CHN0_WR_STRIDE + i * 0x100, val, false); @@ -4385,7 +4386,7 @@ static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) } ds_cnt = priv->yraw_sel ? VPSL_SIG_CHN_MAX - 1 : VPSL_SIG_CHN_MAX; for (i = 0; i < ds_cnt; i++) { - val = priv->pbuf_vpsl->dma_addr + priv->vpsl_sig_offs[i]; + val = pbuf->dma_addr + priv->vpsl_sig_offs[i]; vpsl_write(dev, VPSL_MI_CHN6_WR_BASE + i * 0x100, val, false); val = priv->vpsl_sig_stride[i]; vpsl_write(dev, VPSL_MI_CHN6_WR_STRIDE + i * 0x100, val, false); @@ -4395,7 +4396,7 @@ static void vpsl_update_buf(struct rkisp_isp_params_vdev *params_vdev) vpsl_write(dev, VPSL_MI_IMSC, 0xffffffff, false); val = VPSL_MI_WR_ID_POLL_DIS | VPSL_MI_WR_INIT_OFFSET_EN | VPSL_MI_WR_INIT_BASE_EN; vpsl_write(dev, VPSL_MI_CTRL, val, false); - if (dev->hw_dev->is_single) + if (dev->hw_dev->is_single && is_force) vpsl_write(dev, VPSL_MI_WR_INIT, 0x7ff0, true); } @@ -4458,13 +4459,14 @@ isp_ai_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, val; val = isp3_param_read(params_vdev, ISP35_AI_CTRL, id); - val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); val |= //!!arg->aiisp_raw12_msb << 2 | (arg->aiisp_gain_mode & 0x3) << 4 | !!arg->aiisp_curve_en << 6 | - !!arg->aipre_iir_en << 8 | + //!!arg->aipre_iir_en << 8 | //!!arg->aipre_iir2ddr_en << 9 | - !!arg->aipre_gain_en << 10 | + //!!arg->aipre_gain_en << 10 | //!!arg->aipre_gain2ddr_en << 11 | !!arg->aipre_yraw_sel << 12 | !!arg->aipre_nl_ddr_mode << 13 | @@ -4474,7 +4476,7 @@ isp_ai_config(struct rkisp_isp_params_vdev *params_vdev, !!arg->aipre_luma2gain_dis << 17; if (params_vdev->is_hdr) val |= ISP35_AIISP_HDR_EN; - if (priv->bay3d_iir_rw_fmt == 2) + if (priv->bay3d_iir_rw_fmt == 2 && params_vdev->dev->is_aiisp_en) val |= ISP35_AIISP_RAW12_MSB; isp3_param_write(params_vdev, val, ISP35_AI_CTRL, id); for (i = 0; i < ISP35_AI_SIGMA_NUM / 2; i++) { @@ -4524,22 +4526,31 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) if (en == !!(ctrl & ISP35_MODULE_EN)) return; - ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); if (en) { if (priv->buf_aipre_gain[0].mem_priv) { + priv->aipre_gain_idx = 0; priv->aipre_gain_cur_idx = 0; val = priv->buf_aipre_gain[0].dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, id); val = priv->aipre_gain_stride; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_STRIDE, id); - ctrl |= ISP35_AIPRE_GIAN2DDR_EN; + ctrl |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN; } if (priv->buf_vpsl[0].mem_priv) { - vpsl_update_buf(params_vdev); - if (!priv->yraw_sel) + if (priv->yraw_sel) + ctrl |= ISP35_AIPRE_IIR_EN; + vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); + priv->vpsl_cur_idx = priv->vpsl_idx; + if (params_vdev->dev->is_aiisp_sync) params_vdev->dev->irq_ends_mask |= ISP_FRAME_VPSL; } - ctrl |= ISP35_AIISP_EN | ISP35_AIPRE_ITS_FORCE_UPD; + ctrl |= ISP35_AIPRE_ITS_FORCE_UPD; + if (params_vdev->dev->is_aiisp_en) + ctrl |= ISP35_AIISP_EN; + else if (params_vdev->dev->is_aiisp_stop) + ctrl &= ~(ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN | ISP35_AIPRE_IIR_EN); } else { ctrl &= ~ISP35_AIISP_EN; params_vdev->dev->irq_ends_mask &= ~ISP_FRAME_VPSL; @@ -4988,9 +4999,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, rkisp_free_buffer(params_vdev->dev, buf); } else { is_alloc = false; - buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); - if (buf->dma_fd < 0) + if (rkisp_buf_get_fd(ispdev, buf, false) < 0) goto err; + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; } } if (is_alloc) { @@ -5001,11 +5012,12 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, goto err; } mesh_head = (struct isp2x_mesh_head *)buf->vaddr; - mesh_head->stat = MESH_BUF_INIT; - mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); + } + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); + if (meshsize->module_id == ISP35_MODULE_BAY3D) mesh_head->data1_oft = mesh_head->data_oft + ALIGN(priv->b3dldc_hsize * 4 * priv->b3dldch_vsize, 16); - } buf++; } @@ -5304,12 +5316,13 @@ rkisp_params_init_bnr_buf_v35(struct rkisp_isp_params_vdev *params_vdev, INIT_LIST_HEAD(&priv->gain_list); INIT_LIST_HEAD(&priv->vpsl_list); INIT_LIST_HEAD(&priv->aipre_gain_list); + INIT_LIST_HEAD(&priv->y_src_list); iir_rw_fmt = bnrbuf->u.v35.iir_rw_fmt; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; w16 = ALIGN(w, 16); w32 = ALIGN(w, 32); w128 = ALIGN(w, 128); @@ -5501,7 +5514,53 @@ rkisp_params_init_bnr_buf_v35(struct rkisp_isp_params_vdev *params_vdev, ret = rkisp_alloc_vpsl_buf(params_vdev, bnrbuf); if (ret) goto err_vpsl; + + size = ALIGN(w, 16) * h; + if (dev->unite_div > ISP_UNITE_DIV1) + size *= dev->unite_div; + cnt = bnrbuf->u.v35.y_src.buf_cnt; + if (cnt >= RKISP_BUFFER_MAX) + cnt = RKISP_BUFFER_MAX - 1; + for (i = 0; i < cnt; i++) { + buf = &priv->buf_y_src[i]; + buf->size = size; + buf->is_need_dbuf = true; + buf->is_need_dmafd = true; + ret = rkisp_alloc_buffer(dev, buf); + if (ret) { + dev_err(dev->dev, "alloc y buf%d fail:%d\n", i, ret); + goto err_y_src; + } + if (!i) + priv->pbuf_y_src = buf; + else + list_add_tail(&buf->queue, &priv->y_src_list); + buf->index = i; + bnrbuf->u.v35.y_src.buf_fd[i] = buf->dma_fd; + } + if (cnt && !priv->yraw_sel) + dev->is_aiisp_yuv = true; + priv->y_src_cnt = cnt; + bnrbuf->u.v35.y_src.buf_cnt = cnt; + bnrbuf->u.v35.y_src.buf_size = size; return 0; +err_y_src: + for (i -= 1; i >= 0; i--) { + buf = &priv->buf_y_src[i]; + rkisp_free_buffer(dev, buf); + } + priv->y_src_cnt = 0; + bnrbuf->u.v35.y_src.buf_cnt = 0; + bnrbuf->u.v35.y_src.buf_size = 0; + + i = priv->vpsl_cnt; + for (i -= 1; i >= 0; i--) { + buf = &priv->buf_vpsl[i]; + rkisp_free_buffer(dev, buf); + } + priv->vpsl_cnt = 0; + bnrbuf->u.v35.vpsl.buf_cnt = 0; + bnrbuf->u.v35.vpsl.buf_size = 0; err_vpsl: i = priv->aipre_gain_cnt; err_aipre_gain: @@ -5634,6 +5693,9 @@ rkisp_params_stream_stop_v35(struct rkisp_isp_params_vdev *params_vdev) struct rkisp_device *dev = params_vdev->dev; int i; + for (i = 0; i < priv->y_src_cnt; i++) + rkisp_free_buffer(dev, &priv->buf_y_src[i]); + priv->y_src_cnt = 0; for (i = 0; i < priv->vpsl_cnt; i++) rkisp_free_buffer(dev, &priv->buf_vpsl[i]); priv->vpsl_cnt = 0; @@ -5937,6 +5999,7 @@ rkisp_params_aiisp_update_buf(struct rkisp_isp_params_vdev *params_vdev) val = priv->pbuf_aipre_gain->dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); + priv->aipre_gain_cur_idx = priv->pbuf_aipre_gain->index; if (params_vdev->dev->hw_dev->is_single) { val = isp3_param_read(params_vdev, ISP35_AI_CTRL, 0); @@ -5983,12 +6046,14 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) { struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; struct rkisp_device *dev = params_vdev->dev; + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; struct rkisp_dummy_buffer *buf = NULL; struct v4l2_event ev = { 0 }; struct rkisp_aiisp_ev_info *ev_info; unsigned long lock_flags = 0; u32 h = dev->isp_sdev.out_crop.height; u32 val, wr_line, rd_line; + bool is_event_queue = true; if (sizeof(*ev_info) > sizeof(ev.u)) { v4l2_err(&dev->v4l2_dev, "aiisp_ev_info too large\n"); @@ -6001,6 +6066,8 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) ev_info->aiisp_index = -1; ev_info->vpsl_index = -1; ev_info->aipre_gain_index = -1; + ev_info->y_src_index = -1; + ev_info->y_dest_index = -1; val = rkisp_read(dev, ISP39_AIISP_LINE_CNT, false); if (irq & ISP3X_OUT_FRM_QUARTER) { rd_line = ISP39_AIISP_RD_LINECNT(val); @@ -6016,25 +6083,34 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) list_add_tail(&priv->pbuf_gain_rd->queue, &priv->gain_list); priv->pbuf_gain_rd = NULL; } - if (!priv->yraw_sel) { - buf = priv->pbuf_vpsl; - if (buf) - ev_info->vpsl_index = buf->index; - buf = priv->pbuf_aipre_gain; - if (buf) - ev_info->aipre_gain_index = buf->index; - } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); - v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); } else { wr_line = ISP39_AIISP_WR_LINECNT(val); ev.id = RKISP_AIISP_WR_LINECNT_ID; ev_info->height = !wr_line ? h : wr_line; rkisp_dmarx_get_frame(dev, &ev_info->sequence, NULL, &ev_info->timestamp, true); + if (dev->aiisp_cfg.wr_mode) { + wr_line += dev->aiisp_cfg.wr_linecnt; + if (wr_line > h) + wr_line = h - 1; + rkisp_write(dev, ISP32_ISP_IRQ_CFG1, wr_line << 16, true); + } + + if (dev->is_aiisp_yuv) { + if (!stream->curr_buf) { + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s seq:%d stream output no buf, drop event\n", + __func__, ev_info->sequence); + return; + } + ev_info->y_dest_index = stream->curr_buf->index; + ev_info->y_src_index = priv->y_src_cur_idx; + } spin_lock_irqsave(&priv->buf_lock, lock_flags); - if (!priv->pbuf_bay3d_iir || !priv->pbuf_vpsl || - !priv->pbuf_gain_wr || !priv->pbuf_aipre_gain) { + if (dev->is_aiisp_en && + (!priv->pbuf_bay3d_iir || !priv->pbuf_vpsl || + !priv->pbuf_gain_wr || !priv->pbuf_aipre_gain)) { if (priv->pbuf_bay3d_iir) { list_add_tail(&priv->pbuf_bay3d_iir->queue, &priv->iir_list); priv->pbuf_bay3d_iir = NULL; @@ -6043,25 +6119,23 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) list_add_tail(&priv->pbuf_gain_wr->queue, &priv->gain_list); priv->pbuf_gain_wr = NULL; } - if (priv->pbuf_aipre_gain && priv->yraw_sel) { + if (priv->pbuf_aipre_gain) { list_add_tail(&priv->pbuf_aipre_gain->queue, &priv->aipre_gain_list); priv->pbuf_aipre_gain = NULL; } - if (priv->pbuf_vpsl && priv->yraw_sel) { + if (priv->pbuf_vpsl) { list_add_tail(&priv->pbuf_vpsl->queue, &priv->vpsl_list); priv->pbuf_vpsl = NULL; } + is_event_queue = false; } - if (priv->yraw_sel) { - buf = priv->pbuf_vpsl; - if (buf) - ev_info->vpsl_index = buf->index; - buf = priv->pbuf_aipre_gain; - if (buf) - ev_info->aipre_gain_index = buf->index; - } - + buf = priv->pbuf_vpsl; + if (buf) + ev_info->vpsl_index = buf->index; + buf = priv->pbuf_aipre_gain; + if (buf) + ev_info->aipre_gain_index = buf->index; buf = priv->pbuf_bay3d_iir; if (buf) ev_info->iir_index = buf->index; @@ -6069,14 +6143,15 @@ rkisp_params_aiisp_event_v35(struct rkisp_isp_params_vdev *params_vdev, u32 irq) if (buf) ev_info->gain_index = buf->index; spin_unlock_irqrestore(&priv->buf_lock, lock_flags); - if (buf) - v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); } + if (is_event_queue) + v4l2_event_queue(dev->isp_sdev.sd.devnode, &ev); v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, - "%s seq:%d height:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d)\n", + "%s seq:%d height:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d ysrc:%d ydst:%d)\n", ev.id ? "isp_be" : "isp_fe", ev_info->sequence, ev_info->height, ev_info->iir_index, ev_info->gain_index, - ev_info->vpsl_index, ev_info->aipre_gain_index, ev_info->aiisp_index); + ev_info->vpsl_index, ev_info->aipre_gain_index, ev_info->aiisp_index, + ev_info->y_src_index, ev_info->y_dest_index); } static int @@ -6089,7 +6164,7 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, unsigned long lock_flags = 0; u32 val, aiisp_rd, seq = st->sequence; - if (!dev->is_aiisp_en) + if (!dev->is_aiisp_en && !dev->is_aiisp_stop) return -EINVAL; v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "isp_be input seq:%d idx(iir:%d gain:%d vpsl:%d aipre:%d aiisp:%d)\n", @@ -6108,7 +6183,8 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, return -EINVAL; } - rkisp_params_cfg(params_vdev, seq, RKISP_PARAMS_LAT); + if (!dev->is_aiisp_stop) + rkisp_params_cfg(params_vdev, seq, RKISP_PARAMS_LAT); spin_lock_irqsave(&priv->buf_lock, lock_flags); buf = &priv->buf_bay3d_iir[st->iir_index]; @@ -6172,6 +6248,11 @@ rkisp_params_aiisp_start_v35(struct rkisp_isp_params_vdev *params_vdev, } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); + if (dev->is_aiisp_stop) { + dev->hw_dev->is_be_idle = true; + rkisp_params_aiisp_event_v35(params_vdev, ISP3X_OUT_FRM_QUARTER); + return -EINVAL; + } val = params_vdev->is_hdr ? ISP35_B3DLDCH_RD_BASE_SHD : ISP3X_MI_RAW0_RD_BASE_SHD; v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, "isp_be start seq:%d (%x %x | %x:%x %x:%x)\n", @@ -6210,6 +6291,107 @@ rkisp_vpsl_update_regs_v35(struct rkisp_isp_params_vdev *params_vdev) writel(VPSL_MI_FORCE_UPD, base + VPSL_MI_WR_INIT); } +static void +rkisp_params_aiisp_switch_v35(struct rkisp_isp_params_vdev *params_vdev, bool on) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_stats_vdev *stats_vdev = &dev->stats_vdev; + struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; + struct isp35_isp_params_cfg *params; + struct rkisp_buffer *params_buf; + unsigned long flags = 0; + u32 val; + + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s on:%d\n", __func__, on); + if (!on) { + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + while (!list_empty(¶ms_vdev->params_be)) { + params_buf = list_first_entry(¶ms_vdev->params_be, struct rkisp_buffer, queue); + list_del(¶ms_buf->queue); + params = params_buf->vaddr[0]; + __isp_isr_meas_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_meas_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + params->module_cfg_update = 0; + vb2_buffer_done(¶ms_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~(ISP35_AIISP_ST | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val |= ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + val = rkisp_read(dev, ISP3X_MI_BAY3D_IIR_RD_BASE_SHD, true); + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + + rkisp_stats_first_ddr_config(stats_vdev); + rkisp_stats_next_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val &= ~ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + val = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + rkisp_clear_bits(dev, CIF_ISP_IMSC, val, false); + + if (IS_HDR_RDBK(dev->rd_mode)) + dev->irq_ends_mask &= ~(ISP_FRAME_BNR | ISP_FRAME_VPSL); + } else { + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val |= ISP35_BAYER_PAT_FE(params_vdev->raw_type) | ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + if (priv->pbuf_bay3d_iir) { + val = priv->pbuf_bay3d_iir->dma_addr; + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + } + + spin_lock_irqsave(&stats_vdev->rd_lock, flags); + if (stats_vdev->cur_buf) { + list_add_tail(&stats_vdev->cur_buf->queue, &stats_vdev->stat); + stats_vdev->cur_buf = NULL; + } + if (stats_vdev->nxt_buf) { + list_add_tail(&stats_vdev->nxt_buf->queue, &stats_vdev->stat); + stats_vdev->nxt_buf = NULL; + } + spin_unlock_irqrestore(&stats_vdev->rd_lock, flags); + rkisp_stats_first_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~ISP35_AIISP_ST; + val |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIISP_RAW12_MSB | ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + params_vdev->cur_fe_frame_id = params_vdev->cur_frame_id; + if (IS_HDR_RDBK(dev->rd_mode)) { + dev->is_first_frame = true; + dev->irq_ends_mask = ISP_FRAME_BNR | ISP_FRAME_VPSL; + } + } +} + static void rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) { @@ -6223,7 +6405,8 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) params_vdev->rdbk_times--; if (!params_vdev->rdbk_times) { - if (!dev->is_aiisp_en && priv->bay3d_iir_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->bay3d_iir_cnt > 1) { + priv->pbuf_bay3d_iir = &priv->buf_bay3d_iir[priv->bay3d_iir_idx]; priv->bay3d_iir_cur_idx = priv->bay3d_iir_idx; i = (priv->bay3d_iir_idx + 1) % priv->bay3d_iir_cnt; priv->bay3d_iir_idx = i; @@ -6270,6 +6453,21 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_BASE, i); } } + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->aipre_gain_cnt > 1) { + priv->pbuf_aipre_gain = &priv->buf_aipre_gain[priv->aipre_gain_idx]; + priv->aipre_gain_cur_idx = priv->aipre_gain_idx; + i = (priv->aipre_gain_idx + 1) % priv->aipre_gain_cnt; + priv->aipre_gain_idx = i; + + val = priv->buf_aipre_gain[i].dma_addr; + isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); + } + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->vpsl_cnt > 1) { + priv->pbuf_vpsl = &priv->buf_vpsl[priv->vpsl_idx]; + priv->vpsl_cur_idx = priv->vpsl_idx; + i = (priv->vpsl_idx + 1) % priv->vpsl_cnt; + vpsl_update_buf(params_vdev, &priv->buf_vpsl[i], false); + } for (i = 0; i < dev->unite_div; i++) { if (params_rec->module_cfg_update & ISP35_MODULE_HDRMGE && (dev->is_aiisp_en || IS_HDR_RDBK(dev->rd_mode))) { @@ -6307,6 +6505,8 @@ void rkisp_params_vpsl_mi_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 struct rkisp_device *dev = params_vdev->dev; unsigned long lock_flags = 0; + if (!dev->is_aiisp_en) + return; spin_lock_irqsave(&priv->buf_lock, lock_flags); if (mis_val & VPSL_MI_YRAW_ALL_END) { priv->pbuf_vpsl = NULL; @@ -6314,9 +6514,10 @@ void rkisp_params_vpsl_mi_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 priv->pbuf_vpsl = list_first_entry(&priv->vpsl_list, struct rkisp_dummy_buffer, queue); list_del(&priv->pbuf_vpsl->queue); - vpsl_update_buf(params_vdev); + vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); + priv->vpsl_cur_idx = priv->vpsl_idx; } - if (dev->is_aiisp_sync || !priv->yraw_sel) + if (dev->is_aiisp_sync) rkisp_check_idle(dev, ISP_FRAME_VPSL); } spin_unlock_irqrestore(&priv->buf_lock, lock_flags); @@ -6343,6 +6544,7 @@ static struct rkisp_isp_params_ops rkisp_isp_params_ops_tbl = { .aiisp_event = rkisp_params_aiisp_event_v35, .aiisp_start = rkisp_params_aiisp_start_v35, .vpsl_update_regs = rkisp_vpsl_update_regs_v35, + .aiisp_switch = rkisp_params_aiisp_switch_v35, }; int rkisp_init_params_vdev_v35(struct rkisp_isp_params_vdev *params_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.h b/drivers/media/platform/rockchip/isp/isp_params_v35.h index 79d8feaf0b91..0d28402dc02f 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.h +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.h @@ -36,18 +36,21 @@ struct rkisp_isp_params_val_v35 { struct rkisp_dummy_buffer buf_aipre_gain[RKISP_BUFFER_MAX]; struct rkisp_dummy_buffer buf_aiisp[RKISP_BUFFER_MAX]; struct rkisp_dummy_buffer buf_vpsl[RKISP_BUFFER_MAX]; + struct rkisp_dummy_buffer buf_y_src[RKISP_BUFFER_MAX]; spinlock_t buf_lock; struct list_head iir_list; struct list_head gain_list; struct list_head aipre_gain_list; struct list_head vpsl_list; + struct list_head y_src_list; struct rkisp_dummy_buffer *pbuf_bay3d_iir; struct rkisp_dummy_buffer *pbuf_gain_wr; struct rkisp_dummy_buffer *pbuf_gain_rd; struct rkisp_dummy_buffer *pbuf_aipre_gain; struct rkisp_dummy_buffer *pbuf_vpsl; struct rkisp_dummy_buffer *pbuf_aiisp; + struct rkisp_dummy_buffer *pbuf_y_src; u32 bay3d_iir_rw_fmt; u32 bay3d_iir_offs; @@ -76,11 +79,17 @@ struct rkisp_isp_params_val_v35 { u32 aipre_gain_stride; int aipre_gain_cnt; + int aipre_gain_idx; int aipre_gain_cur_idx; int vpsl_cnt; + int vpsl_idx; int vpsl_cur_idx; + int y_src_cnt; + int y_src_idx; + int y_src_cur_idx; + u32 vpsl_yraw_offs[VPSL_YRAW_CHN_MAX]; u32 vpsl_yraw_stride[VPSL_YRAW_CHN_MAX]; u32 vpsl_sig_offs[VPSL_SIG_CHN_MAX]; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v39.c b/drivers/media/platform/rockchip/isp/isp_params_v39.c index df1451472d63..41fecc0794fc 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v39.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v39.c @@ -967,9 +967,9 @@ isp_rawaf_config(struct rkisp_isp_params_vdev *params_vdev, size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->win), arg->num_afm_win); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; for (i = 0; i < num_of_win; i++) { h_size = arg->win[i].h_size; @@ -1168,9 +1168,9 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWAE_BIG_OFFSET, id); if (ispdev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (ispdev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + ispdev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -1321,9 +1321,9 @@ isp_rawawb_config(struct rkisp_isp_params_vdev *params_vdev, ISP3X_RAWAWB_WIN_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->h_size; v_size = arg->v_size; @@ -2042,9 +2042,9 @@ isp_rawhstbig_config(struct rkisp_isp_params_vdev *params_vdev, addr + ISP3X_RAWHIST_BIG_OFFS, id); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; h_size = arg->win.h_size; v_size = arg->win.v_size; @@ -2378,9 +2378,9 @@ isp_dhaz_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, value, ctrl, thumb_row, thumb_col, blk_het, blk_wid; if (dev->unite_div > ISP_UNITE_DIV1) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - h = h / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h = h / 2 + dev->hw_dev->unite_extend_pixel; ctrl = isp3_param_read(params_vdev, ISP3X_DHAZ_CTRL, id); ctrl &= ISP3X_DHAZ_ENMUX; @@ -4430,9 +4430,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, rkisp_free_buffer(params_vdev->dev, buf); } else { is_alloc = false; - buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC); - if (buf->dma_fd < 0) + if (rkisp_buf_get_fd(ispdev, buf, false) < 0) goto err; + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; } } if (is_alloc) { @@ -4443,9 +4443,9 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, goto err; } mesh_head = (struct isp2x_mesh_head *)buf->vaddr; - mesh_head->stat = MESH_BUF_INIT; - mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); } + mesh_head->stat = MESH_BUF_INIT; + mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); buf++; } @@ -4659,9 +4659,9 @@ rkisp_params_init_bnr_buf_v39(struct rkisp_isp_params_vdev *params_vdev, INIT_LIST_HEAD(&priv_val->iir_list); INIT_LIST_HEAD(&priv_val->gain_list); if (dev->unite_div > ISP_UNITE_DIV1) - w = ALIGN(isp_sdev->in_crop.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + w = ALIGN(isp_sdev->in_crop.width / 2 + dev->hw_dev->unite_extend_pixel, 16); if (dev->unite_div == ISP_UNITE_DIV4) - h = ALIGN(isp_sdev->in_crop.height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + h = ALIGN(isp_sdev->in_crop.height / 2 + dev->hw_dev->unite_extend_pixel, 16); if (!iirsparse_en) { w = w * 3 / 2 + w / 4; h /= 2; diff --git a/drivers/media/platform/rockchip/isp/isp_params_v3x.c b/drivers/media/platform/rockchip/isp/isp_params_v3x.c index ba1a572cf873..310a4a6d1aaa 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v3x.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v3x.c @@ -1198,7 +1198,7 @@ isp_rawaelite_config(struct rkisp_isp_params_vdev *params_vdev, block_hsize = arg->win.h_size / ae_wnd_num[wnd_num_idx]; value = block_hsize * ae_wnd_num[wnd_num_idx] + arg->win.h_offs; if (ispdev->hw_dev->unite) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (value + 1 > width) block_hsize -= 1; block_vsize = arg->win.v_size / ae_wnd_num[wnd_num_idx]; @@ -1291,7 +1291,7 @@ isp_rawaebig_config(struct rkisp_isp_params_vdev *params_vdev, block_hsize = arg->win.h_size / ae_wnd_num[wnd_num_idx]; value = block_hsize * ae_wnd_num[wnd_num_idx] + arg->win.h_offs; if (ispdev->hw_dev->unite) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + ispdev->hw_dev->unite_extend_pixel; if (value + 1 > width) block_hsize -= 1; block_vsize = arg->win.v_size / ae_wnd_num[wnd_num_idx]; @@ -4149,7 +4149,7 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev, w = ALIGN(isp_sdev->in_crop.width, 16); h = ALIGN(isp_sdev->in_crop.height, 16); if (ispdev->hw_dev->unite) - w = ALIGN(isp_sdev->in_crop.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL, 16); + w = ALIGN(isp_sdev->in_crop.width / 2 + ispdev->hw_dev->unite_extend_pixel, 16); size = ALIGN((w + w / 8) * h * 2, 16); @@ -4243,7 +4243,7 @@ multi_overflow: continue; dev_warn(dev, "isp%d %dx%d over four vir isp max:%dx1536\n", i, hw->isp_size[i].w, hw->isp_size[i].h, - hw->unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); + hw->unite ? (2560 - hw->unite_extend_pixel) * 2 : 2560); hw->is_multi_overflow = true; goto multi_overflow; } @@ -4285,7 +4285,7 @@ multi_overflow: (hw->isp_size[idx1[0]].size > ISP3X_VIR2_MAX_SIZE)) { dev_warn(dev, "isp%d %dx%d over three vir isp max:%dx1536\n", idx1[0], hw->isp_size[idx1[0]].w, hw->isp_size[idx1[0]].h, - hw->unite ? (2560 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 2560); + hw->unite ? (2560 - hw->unite_extend_pixel) * 2 : 2560); hw->is_multi_overflow = true; goto multi_overflow; } else { @@ -4344,7 +4344,7 @@ multi_overflow: hw->isp_size[idx1[k - 1]].size > (ISP3X_VIR4_MAX_SIZE + ISP3X_VIR2_MAX_SIZE)) { dev_warn(dev, "isp%d %dx%d over two vir isp max:%dx2160\n", idx1[k - 1], hw->isp_size[idx1[k - 1]].w, hw->isp_size[idx1[k - 1]].h, - hw->unite ? (3840 - RKMOUDLE_UNITE_EXTEND_PIXEL) * 2 : 3840); + hw->unite ? (3840 - hw->unite_extend_pixel) * 2 : 3840); hw->is_multi_overflow = true; goto multi_overflow; } else { @@ -4367,7 +4367,7 @@ multi_overflow: ispdev->multi_index = 0; width = crop->width; if (hw->unite) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + hw->unite_extend_pixel; height = crop->height; size = width * height; break; @@ -4497,6 +4497,7 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, u32 mesh_size, buf_size; int i, ret, id = meshsize->unite_isp_id; int buf_cnt = meshsize->buf_cnt; + bool is_alloc; priv_val = params_vdev->priv_val; if (!priv_val) { @@ -4529,14 +4530,26 @@ static int rkisp_init_mesh_buf(struct rkisp_isp_params_vdev *params_vdev, buf->is_need_vaddr = true; buf->is_need_dbuf = true; buf->is_need_dmafd = true; - buf->size = buf_size; - ret = rkisp_alloc_buffer(params_vdev->dev, buf); - if (ret) { - dev_err(dev, "%s failed\n", __func__); - goto err; + is_alloc = true; + if (buf->mem_priv) { + if (buf_size > buf->size) { + rkisp_free_buffer(params_vdev->dev, buf); + } else { + is_alloc = false; + if (rkisp_buf_get_fd(ispdev, buf, false) < 0) + goto err; + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; + } + } + if (is_alloc) { + buf->size = buf_size; + ret = rkisp_alloc_buffer(params_vdev->dev, buf); + if (ret) { + dev_err(dev, "%s failed\n", __func__); + goto err; + } + mesh_head = (struct isp2x_mesh_head *)buf->vaddr; } - - mesh_head = (struct isp2x_mesh_head *)buf->vaddr; mesh_head->stat = MESH_BUF_INIT; mesh_head->data_oft = ALIGN(sizeof(struct isp2x_mesh_head), 16); buf++; diff --git a/drivers/media/platform/rockchip/isp/isp_rockit.c b/drivers/media/platform/rockchip/isp/isp_rockit.c index fc3375441a7f..9539aed571cb 100644 --- a/drivers/media/platform/rockchip/isp/isp_rockit.c +++ b/drivers/media/platform/rockchip/isp/isp_rockit.c @@ -172,6 +172,9 @@ int rkisp_rockit_buf_queue(struct rockit_cfg *input_rockit_cfg) isprk_buf->sgt = sgt; stream_cfg->rkisp_buff[i] = isprk_buf; stream->buf_cnt++; + isprk_buf->isp_buf.index = i; + stream->dbuf_pool[i] = input_rockit_cfg->buf; + stream->is_rockit_buf = true; } if (ispdev->cap_dev.wrap_line && stream->id == RKISP_STREAM_MP) { @@ -641,6 +644,7 @@ int rkisp_rockit_buf_free(struct rkisp_stream *stream) } } mutex_unlock(&stream_cfg->freebuf_lock); + stream->is_rockit_buf = false; return 0; } diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c index 370a275b43c6..208ee15ae4af 100644 --- a/drivers/media/platform/rockchip/isp/isp_sditf.c +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -64,7 +64,8 @@ static int rkisp_sditf_s_stream(struct v4l2_subdev *sd, int on) if (ret < 0) goto pipe_close; sditf->is_on = true; - dev->irq_ends_mask |= ISP_FRAME_VPSS; + if (!dev->is_aiisp_sync) + dev->irq_ends_mask |= ISP_FRAME_VPSS; goto unlock; } sditf->is_on = false; @@ -159,7 +160,7 @@ void rkisp_sditf_sof(struct rkisp_device *dev, u32 irq) if (!sditf || !sditf->is_on || !sditf->remote_sd) return; info.irq = irq; - rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, true); + rkisp_dmarx_get_frame(dev, &info.seq, NULL, &info.timestamp, !dev->is_aiisp_en); info.unite_index = dev->unite_index; if (dev->isp_ver == ISP_V35) info.grey = !!(rkisp_read(dev, ISP3X_CNR_CTRL, false) & ISP35_CNR_UV_DIS); @@ -184,14 +185,14 @@ static long rkisp_sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *ar rkisp_check_idle(sditf->isp, ISP_FRAME_VPSS); break; case RKISP_VPSS_GET_UNITE_MODE: - if (sditf->isp->unite_div == ISP_UNITE_DIV2) - *(unsigned int *)arg = sditf->isp->unite_div; - else - *(unsigned int *)arg = 0; + *(unsigned int *)arg = sditf->isp->unite_div - 1; break; case RKISP_VPSS_GET_ISP_WORKING: *(int *)arg = sditf->isp->hw_dev->is_runing; break; + case RKISP_VPSS_GET_UNITE_EXTEND_PIXEL: + *(int *)arg = sditf->isp->hw_dev->unite_extend_pixel; + break; default: ret = -ENOIOCTLCMD; } diff --git a/drivers/media/platform/rockchip/isp/isp_stats.c b/drivers/media/platform/rockchip/isp/isp_stats.c index 170a3a4e0e60..cc75c0dcdcb3 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.c +++ b/drivers/media/platform/rockchip/isp/isp_stats.c @@ -219,6 +219,8 @@ static void rkisp_stats_vb2_stop_streaming(struct vb2_queue *vq) stats_vdev->ae_meas_done_next = false; stats_vdev->af_meas_done_next = false; + if (stats_vdev->ops->stats_stop) + stats_vdev->ops->stats_stop(stats_vdev); } static int diff --git a/drivers/media/platform/rockchip/isp/isp_stats.h b/drivers/media/platform/rockchip/isp/isp_stats.h index 962e8c073f8d..aea0e5d1ffa1 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.h +++ b/drivers/media/platform/rockchip/isp/isp_stats.h @@ -38,6 +38,7 @@ struct rkisp_isp_stats_ops { void (*first_ddr_cfg)(struct rkisp_isp_stats_vdev *stats_vdev); void (*next_ddr_cfg)(struct rkisp_isp_stats_vdev *stats_vdev); int (*stats_tb)(struct rkisp_isp_stats_vdev *stats_vdev, struct rkisp_buffer *stats_buf); + void (*stats_stop)(struct rkisp_isp_stats_vdev *stats_vdev); }; /* diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v32.c b/drivers/media/platform/rockchip/isp/isp_stats_v32.c index 9fe55848abbd..d411bac50e66 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v32.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v32.c @@ -1146,6 +1146,21 @@ rkisp_stats_next_ddr_config_v32(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_stats_update_buf(stats_vdev); } +static void rkisp_stats_stop_v32(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + u32 val, addr; + + /* aiq crash or exit first */ + if (dev->isp_state & ISP_START && + stats_vdev->stats_buf[0].mem_priv) { + rkisp_stats_update_buf(stats_vdev); + addr = stats_vdev->stats_buf[0].dma_addr; + readl_poll_timeout(dev->hw_dev->base_addr + ISP3X_MI_3A_WR_BASE, + val, val == addr, 5000, 50000); + } +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp_stats_isr_v32, .send_meas = rkisp_stats_send_meas_v32, @@ -1154,6 +1169,7 @@ static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .stats_tb = rkisp_stats_tb_v32, .first_ddr_cfg = rkisp_stats_first_ddr_config_v32, .next_ddr_cfg = rkisp_stats_next_ddr_config_v32, + .stats_stop = rkisp_stats_stop_v32, }; void rkisp_init_stats_vdev_v32(struct rkisp_isp_stats_vdev *stats_vdev) @@ -1167,6 +1183,7 @@ void rkisp_init_stats_vdev_v32(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_isp_stats_ops_tbl.stats_tb = NULL; rkisp_isp_stats_ops_tbl.first_ddr_cfg = NULL; rkisp_isp_stats_ops_tbl.next_ddr_cfg = NULL; + rkisp_isp_stats_ops_tbl.stats_stop = NULL; } stats_vdev->ops = &rkisp_isp_stats_ops_tbl; } diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v33.c b/drivers/media/platform/rockchip/isp/isp_stats_v33.c index 887f90f7d487..1c77c480c8f1 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v33.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v33.c @@ -568,6 +568,21 @@ rkisp_stats_next_ddr_config_v33(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_stats_update_buf(stats_vdev); } +static void rkisp_stats_stop_v33(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + u32 val, addr; + + /* aiq crash or exit first */ + if (dev->isp_state & ISP_START && + stats_vdev->stats_buf[0].mem_priv) { + rkisp_stats_update_buf(stats_vdev); + addr = stats_vdev->stats_buf[0].dma_addr; + readl_poll_timeout(dev->hw_dev->base_addr + ISP39_W3A_AEBIG_ADDR_SHD, + val, val == addr, 5000, 50000); + } +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp_stats_isr_v33, .send_meas = rkisp_stats_send_meas_v33, @@ -575,6 +590,7 @@ static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .stats_tb = rkisp_stats_tb_v33, .first_ddr_cfg = rkisp_stats_first_ddr_config_v33, .next_ddr_cfg = rkisp_stats_next_ddr_config_v33, + .stats_stop = rkisp_stats_stop_v33, }; void rkisp_init_stats_vdev_v33(struct rkisp_isp_stats_vdev *stats_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v35.c b/drivers/media/platform/rockchip/isp/isp_stats_v35.c index bfd674f01715..29036ccb311d 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v35.c @@ -164,8 +164,8 @@ rkisp_stats_get_enh_stats(struct rkisp_isp_stats_vdev *stats_vdev, struct rkisp_isp_params_vdev *params = &dev->params_vdev; struct rkisp_isp_params_val_v35 *priv_val = params->priv_val; struct isp35_isp_params_cfg *params_rec = params->isp35_params + dev->unite_index; - struct isp33_enh_cfg *arg_rec = ¶ms_rec->others.enh_cfg; - struct isp33_enh_stat *enh; + struct isp35_enh_cfg *arg_rec = ¶ms_rec->others.enh_cfg; + struct isp35_enh_stat *enh; int val, i, j, timeout; val = isp3_stats_read(stats_vdev, ISP33_ENH_CTRL); @@ -629,17 +629,17 @@ rkisp_stats_send_meas(struct rkisp_isp_stats_vdev *stats_vdev) cur_stat_buf = cur_buf->vaddr[0]; } - /* buffer done when frame of right handle */ - if (dev->unite_div > ISP_UNITE_DIV1) { - if (dev->unite_index == ISP_UNITE_LEFT) { - cur_buf = NULL; - is_dummy = false; - } else if (cur_stat_buf) { - cur_stat_buf = (void *)cur_stat_buf + size / 2; - } + if (dev->unite_index > ISP_UNITE_LEFT && cur_stat_buf) + cur_stat_buf = (void *)cur_stat_buf + size / dev->unite_div * dev->unite_index; + if ((dev->unite_div == ISP_UNITE_DIV2 && dev->unite_index != ISP_UNITE_RIGHT) || + (dev->unite_div == ISP_UNITE_DIV4 && dev->unite_index != ISP_UNITE_RIGHT_B)) { + cur_buf = NULL; + is_dummy = false; } - if (dev->unite_div < ISP_UNITE_DIV2 || dev->unite_index == ISP_UNITE_RIGHT) { + if (dev->unite_div < ISP_UNITE_DIV2 || + (dev->unite_div == ISP_UNITE_DIV2 && dev->unite_index == ISP_UNITE_RIGHT) || + (dev->unite_div == ISP_UNITE_DIV4 && dev->unite_index == ISP_UNITE_RIGHT_B)) { /* config buf for next frame */ stats_vdev->cur_buf = NULL; if (stats_vdev->nxt_buf) { @@ -812,7 +812,9 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_get_stat_size_v35(stats_vdev, &size); stats_vdev->stats_buf[0].is_need_vaddr = true; stats_vdev->stats_buf[0].size = size; - if (rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0])) + if (!stats_vdev->stats_buf[0].mem_priv) + rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0]); + if (!stats_vdev->stats_buf[0].vaddr) v4l2_warn(&dev->v4l2_dev, "stats alloc buf fail\n"); else memset(stats_vdev->stats_buf[0].vaddr, 0, size); @@ -823,12 +825,14 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (dev->hw_dev->is_single) rkisp_unite_set_bits(dev, ISP3X_SWS_CFG, 0, ISP3X_3A_DDR_WRITE_EN, false); val = rkisp_read(dev, ISP39_W3A_CTRL0, false); + val &= ~(ISP39_W3A_AUTO_CLR_EN | ISP35_W3A_FORCE_UPD_F); val |= ISP39_W3A_EN | ISP39_W3A_FORCE_UPD; if (!dev->is_aiisp_en) val |= ISP39_W3A_AUTO_CLR_EN; else val |= ISP35_W3A_FORCE_UPD_F; - if (pdaf_vdev && pdaf_vdev->streaming) { + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) { val |= ISP39_W3A_PDAF_EN; rkisp_pdaf_update_buf(dev); if (pdaf_vdev->next_buf) { @@ -857,17 +861,34 @@ rkisp_stats_next_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (hw->is_single) { if (!dev->is_aiisp_en) rkisp_stats_update_buf(stats_vdev); - if (pdaf_vdev && pdaf_vdev->streaming) + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) rkisp_pdaf_update_buf(dev); } } +static void rkisp_stats_stop_v35(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + u32 val, addr; + + /* aiq crash or exit first */ + if (dev->isp_state & ISP_START && + stats_vdev->stats_buf[0].mem_priv) { + rkisp_stats_update_buf(stats_vdev); + addr = stats_vdev->stats_buf[0].dma_addr; + readl_poll_timeout(dev->hw_dev->base_addr + ISP39_W3A_AEBIG_ADDR_SHD, + val, val == addr, 5000, 50000); + } +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp_stats_isr_v35, .get_stat_size = rkisp_get_stat_size_v35, .stats_tb = rkisp_stats_tb_v35, .first_ddr_cfg = rkisp_stats_first_ddr_config_v35, .next_ddr_cfg = rkisp_stats_next_ddr_config_v35, + .stats_stop = rkisp_stats_stop_v35, }; void rkisp_init_stats_vdev_v35(struct rkisp_isp_stats_vdev *stats_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v39.c b/drivers/media/platform/rockchip/isp/isp_stats_v39.c index 69672a06cb9b..48eb65ba12ad 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v39.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v39.c @@ -536,11 +536,27 @@ rkisp_stats_next_ddr_config_v39(struct rkisp_isp_stats_vdev *stats_vdev) } } +static void rkisp_stats_stop_v39(struct rkisp_isp_stats_vdev *stats_vdev) +{ + struct rkisp_device *dev = stats_vdev->dev; + u32 val, addr; + + /* aiq crash or exit first */ + if (dev->isp_state & ISP_START && + stats_vdev->stats_buf[0].mem_priv) { + rkisp_stats_update_buf(stats_vdev); + addr = stats_vdev->stats_buf[0].dma_addr; + readl_poll_timeout(dev->hw_dev->base_addr + ISP39_W3A_AEBIG_ADDR_SHD, + val, val == addr, 5000, 50000); + } +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp_stats_isr_v39, .get_stat_size = rkisp_get_stat_size_v39, .first_ddr_cfg = rkisp_stats_first_ddr_config_v39, .next_ddr_cfg = rkisp_stats_next_ddr_config_v39, + .stats_stop = rkisp_stats_stop_v39, }; void rkisp_init_stats_vdev_v39(struct rkisp_isp_stats_vdev *stats_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_vpss.h b/drivers/media/platform/rockchip/isp/isp_vpss.h index 686b61a20edc..10d7cf0a4a61 100644 --- a/drivers/media/platform/rockchip/isp/isp_vpss.h +++ b/drivers/media/platform/rockchip/isp/isp_vpss.h @@ -22,6 +22,9 @@ #define RKISP_VPSS_GET_ISP_WORKING \ _IOR('V', BASE_VIDIOC_PRIVATE + 5, int) +#define RKISP_VPSS_GET_UNITE_EXTEND_PIXEL \ + _IOR('V', BASE_VIDIOC_PRIVATE + 6, int) + struct rkisp_vpss_sof { u32 irq; u32 seq; diff --git a/drivers/media/platform/rockchip/isp/procfs.c b/drivers/media/platform/rockchip/isp/procfs.c index b0e6fb56d17f..cc72834bea39 100644 --- a/drivers/media/platform/rockchip/isp/procfs.c +++ b/drivers/media/platform/rockchip/isp/procfs.c @@ -1377,14 +1377,16 @@ static int isp_show(struct seq_file *p, void *v) info, sdev->dbg.frameloss, dev->rdbk_cnt, dev->rdbk_cnt_x1, dev->rdbk_cnt_x2, dev->rdbk_cnt_x3, rkisp_stream_buf_cnt(stream)); - seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d)\n", + seq_printf(p, "\t hw link:%d idle:%d vir(mode:%d index:%d) div:%d extend:%d\n", dev->hw_dev->dev_link_num, dev->hw_dev->is_idle, - dev->multi_mode, dev->multi_index); + dev->multi_mode, dev->multi_index, dev->unite_div, + dev->hw_dev->unite_extend_pixel); } else { - seq_printf(p, "%-10s frame:%d state:%s %s v-blank:%dus\n", + seq_printf(p, "%-10s frame:%d state:%s %s v-blank:%dus div:%d extend:%d\n", "Isp online", sdev->dbg.id, (dev->isp_state & ISP_FRAME_END) ? "idle" : "working", - info, sdev->dbg.delay / 1000); + info, sdev->dbg.delay / 1000, + dev->unite_div, dev->hw_dev->unite_extend_pixel); } if (dev->br_dev.en) seq_printf(p, "%-10s rkispp%d Format:%s%s Size:%dx%d (frame:%d rate:%dms frameloss:%d)\n", diff --git a/drivers/media/platform/rockchip/isp/regs.c b/drivers/media/platform/rockchip/isp/regs.c index 744853926b68..5221dd1f8835 100644 --- a/drivers/media/platform/rockchip/isp/regs.c +++ b/drivers/media/platform/rockchip/isp/regs.c @@ -82,7 +82,7 @@ void rkisp_config_dcrop(struct rkisp_stream *stream, u32 right_w, left_w = tmp.width; reg = stream->config->dual_crop.h_offset; - rkisp_idx_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, ISP_UNITE_RIGHT, false); + rkisp_idx_write(dev, reg, dev->hw_dev->unite_extend_pixel, ISP_UNITE_RIGHT, false); reg = stream->config->dual_crop.h_size; right_w = rect->width - left_w; rkisp_idx_write(dev, reg, right_w, ISP_UNITE_RIGHT, false); @@ -91,7 +91,7 @@ void rkisp_config_dcrop(struct rkisp_stream *stream, rkisp_idx_set_bits(dev, reg, 0, val, ISP_UNITE_RIGHT, false); /* output with scale */ if (stream->out_fmt.width < rect->width) { - left_w += RKMOUDLE_UNITE_EXTEND_PIXEL; + left_w += dev->hw_dev->unite_extend_pixel; reg = stream->config->dual_crop.h_size; rkisp_idx_write(dev, reg, left_w, ISP_UNITE_LEFT, false); } @@ -100,20 +100,20 @@ void rkisp_config_dcrop(struct rkisp_stream *stream, tmp.left, tmp.top, left_w, tmp.height); v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, "right dcrop (%d, %d) %dx%d\n", - RKMOUDLE_UNITE_EXTEND_PIXEL, tmp.top, right_w, tmp.height); + dev->hw_dev->unite_extend_pixel, tmp.top, right_w, tmp.height); } if (dev->unite_div == ISP_UNITE_DIV4) { reg = stream->config->dual_crop.h_offset; rkisp_idx_write(dev, reg, tmp.left, ISP_UNITE_LEFT_B, false); - rkisp_idx_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, ISP_UNITE_RIGHT_B, false); + rkisp_idx_write(dev, reg, dev->hw_dev->unite_extend_pixel, ISP_UNITE_RIGHT_B, false); reg = stream->config->dual_crop.h_size; rkisp_idx_write(dev, reg, tmp.width, ISP_UNITE_LEFT_B, false); rkisp_idx_write(dev, reg, tmp.width, ISP_UNITE_RIGHT_B, false); reg = stream->config->dual_crop.v_offset; - rkisp_idx_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, ISP_UNITE_LEFT_B, false); - rkisp_idx_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, ISP_UNITE_RIGHT_B, false); + rkisp_idx_write(dev, reg, dev->hw_dev->unite_extend_pixel, ISP_UNITE_LEFT_B, false); + rkisp_idx_write(dev, reg, dev->hw_dev->unite_extend_pixel, ISP_UNITE_RIGHT_B, false); reg = stream->config->dual_crop.ctrl; rkisp_idx_set_bits(dev, reg, 0, val, ISP_UNITE_LEFT_B, false); @@ -240,7 +240,7 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, if (dev->unite_div > ISP_UNITE_DIV1) { u32 hy_size_reg, hc_size_reg, hy_offs_mi_reg, hc_offs_mi_reg, in_crop_offs_reg; - u32 isp_in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 isp_in_w = in_y->width / 2 + dev->hw_dev->unite_extend_pixel; u32 scl_w = out_y->width / 2; u32 left_y = scale_hy == 1 ? scl_w : DIV_ROUND_UP(scl_w * 65536, scale_hy); u32 left_c = scale_hc == 1 ? scl_w / 2 : DIV_ROUND_UP(scl_w * 65536 / 2, scale_hc); @@ -254,7 +254,7 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, u32 right_c = phase_left_c ? in_y->width - (left_c - 1) * 2 : in_y->width - left_c * 2; u32 right_crop_y = isp_in_w - right_y; u32 right_crop_c = isp_in_w - right_c; - u32 extend = RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 extend = dev->hw_dev->unite_extend_pixel; u32 right_scl_in_y; u32 right_scl_in_c; @@ -286,7 +286,7 @@ static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y, return; } - if (right_crop_y < RKMOUDLE_UNITE_EXTEND_PIXEL) { + if (right_crop_y < dev->hw_dev->unite_extend_pixel) { u32 reg; extend = right_crop_y & ~0x1; @@ -354,7 +354,7 @@ static void set_bilinear_scale(struct rkisp_stream *stream, struct v4l2_rect *in in_w = in_y->width; out_w = out_y->width; if (dev->unite_div > ISP_UNITE_DIV1) { - in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + in_w = in_y->width / 2 + dev->hw_dev->unite_extend_pixel; out_w /= 2; } val = in_w | in_y->height << 16; @@ -418,7 +418,7 @@ static void set_bilinear_scale(struct rkisp_stream *stream, struct v4l2_rect *in scl_in_hc_offs = right_scl_in_size - right_need_in_size_c; right_crop = in_w - right_scl_in_size; - if (right_crop != RKMOUDLE_UNITE_EXTEND_PIXEL) { + if (right_crop != dev->hw_dev->unite_extend_pixel) { reg = stream->config->dual_crop.h_offset; rkisp_idx_write(dev, reg, right_crop, ISP_UNITE_RIGHT, false); reg = stream->config->dual_crop.h_size; diff --git a/drivers/media/platform/rockchip/isp/regs_v2x.h b/drivers/media/platform/rockchip/isp/regs_v2x.h index fa2efa10708c..bc33b5727d3b 100644 --- a/drivers/media/platform/rockchip/isp/regs_v2x.h +++ b/drivers/media/platform/rockchip/isp/regs_v2x.h @@ -2688,7 +2688,8 @@ static inline void mi_raw_length(struct rkisp_stream *stream) !IS_HDR_RDBK(stream->ispdev->rd_mode) && stream->config->mi.length == MI_RAW2_RD_LENGTH && stream->ispdev->unite_div == ISP_UNITE_DIV2) { - bytesperline = stream->out_fmt.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + bytesperline = stream->out_fmt.width / 2 + + stream->ispdev->hw_dev->unite_extend_pixel; bytesperline = ALIGN(bytesperline * stream->out_isp_fmt.bpp[0] / 8, 256); } } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 49f8c25621ad..27ca6de91a6b 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -241,8 +241,10 @@ int rkisp_align_sensor_resolution(struct rkisp_device *dev, CIF_ISP_INPUT_H_MAX_V33_UNITE : CIF_ISP_INPUT_H_MAX_V33; break; case ISP_V35: - max_w = CIF_ISP_INPUT_W_MAX_V35; - max_h = CIF_ISP_INPUT_H_MAX_V35; + max_w = dev->hw_dev->unite ? + CIF_ISP_INPUT_W_MAX_V35_UNITE : CIF_ISP_INPUT_W_MAX_V35; + max_h = dev->hw_dev->unite ? + CIF_ISP_INPUT_H_MAX_V35_UNITE : CIF_ISP_INPUT_H_MAX_V35; break; default: max_w = CIF_ISP_INPUT_W_MAX; @@ -756,6 +758,8 @@ static void rkisp_check_mi_ends_mask(struct rkisp_device *dev) dev->irq_ends_mask |= ISP_FRAME_LDC; else dev->irq_ends_mask &= ~ISP_FRAME_LDC; + if (dev->sditf_dev && dev->sditf_dev->is_on) + dev->irq_ends_mask |= ISP_FRAME_VPSS; } /* @@ -832,7 +836,6 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo dev->isp_sdev.quantization); rkisp_params_cfg(params_vdev, cur_frame_id, RKISP_PARAMS_IMD); rkisp_config_cmsk(dev); - rkisp_config_aiisp(dev); if (!dev->is_aiisp_en || (dev->is_aiisp_sync && !dev->is_first_frame)) rkisp_stream_frame_start(dev, 0); @@ -1015,7 +1018,7 @@ run_next: cur_frame_id, dma2frm + 1, val, is_try); if (!hw->is_shutdown) { rkisp_unite_write(dev, CSI2RX_CTRL0, val, true); - if (dev->is_aiisp_sync && !dev->is_first_frame) { + if (dev->is_aiisp_en && dev->is_aiisp_sync && !dev->is_first_frame) { dev->irq_ends_mask |= ISP_FRAME_END; if (dev->isp_ver == ISP_V39) { val = rkisp_read(dev, ISP3X_MI_RD_CTRL2, false); @@ -1156,10 +1159,11 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd) goto end; if (isp->is_aiisp_sync && !isp->is_first_frame) { rkisp_rdbk_aiisp_event(isp, T_CMD_LEN, &len[id]); + if (len[id]) + is_aiisp_ready = true; /* wait isp_be frame input */ - if (len[id] == 0) + if (len[id] == 0 && isp->is_aiisp_en) goto end; - is_aiisp_ready = true; } v4l2_dbg(2, rkisp_debug, &isp->v4l2_dev, "trigger fifo len:%d\n", max); @@ -1356,11 +1360,13 @@ static void rkisp_frame_end_idle(struct rkisp_device *dev) if (!(dev->irq_ends_mask & val)) { u32 state = dev->isp_state; struct rkisp_stream *s; + bool sditf_off = true; if (dev->sditf_dev && !dev->sditf_dev->is_on) dev->isp_state = ISP_STOP; - - for (val = 0; val < RKISP_STREAM_VIR; val++) { + else if (dev->sditf_dev && dev->sditf_dev->is_on) + sditf_off = false; + for (val = 0; val < RKISP_STREAM_VIR && sditf_off; val++) { s = &dev->cap_dev.stream[val]; dev->isp_state = ISP_STOP; if (s->streaming) { @@ -1391,6 +1397,7 @@ end: if (dev->is_wait_aiq && (dev->unite_div < ISP_UNITE_DIV2 || dev->unite_index == ISP_UNITE_RIGHT)) return; + rkisp_config_aiisp(dev); if (dev->hw_dev->is_dvfs) schedule_work(&dev->rdbk_work); else @@ -1425,6 +1432,15 @@ static void rkisp_back_end_idle(struct rkisp_device *dev) rkisp_rdbk_aiisp_event(dev, T_CMD_END, NULL); if (dev->isp_state == ISP_STOP && dev->hw_dev->is_idle) wake_up(&dev->sync_onoff); + if (dev->is_aiisp_stopping && dev->hw_dev->is_be_idle && + dev->aiisp_stop_seq == dev->dmarx_dev.cur_be_frame.id) { + dev->is_aiisp_en = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, false); + dev->is_aiisp_stopping = false; + dev->is_aiisp_stop = true; + rkisp_vicap_hw_link(dev, true); + } } void rkisp_check_idle(struct rkisp_device *dev, u32 irq) @@ -1461,15 +1477,19 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags); if (isp_front_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_front_end_idle(dev); } if (isp_back_end) rkisp_back_end_idle(dev); if (isp_frame_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_frame_end_idle(dev); } } @@ -1501,9 +1521,9 @@ static void rkisp_config_ism(struct rkisp_device *dev) return; if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; rkisp_unite_write(dev, CIF_ISP_IS_RECENTER, 0, false); rkisp_unite_write(dev, CIF_ISP_IS_MAX_DX, 0, false); rkisp_unite_write(dev, CIF_ISP_IS_MAX_DY, 0, false); @@ -1844,12 +1864,12 @@ static void rkisp_config_cmsk_dual(struct rkisp_device *dev, left.win[0].win_en &= ~BIT(i); left.win[1].win_en &= ~BIT(i); left.win[2].win_en &= ~BIT(i); - right.win[i].h_offs = h_offs - w + RKMOUDLE_UNITE_EXTEND_PIXEL; + right.win[i].h_offs = h_offs - w + dev->hw_dev->unite_extend_pixel; } else { /* cmsk window at dual isp */ left.win[i].h_size = ALIGN(w - h_offs, 8); - right.win[i].h_offs = RKMOUDLE_UNITE_EXTEND_PIXEL; + right.win[i].h_offs = dev->hw_dev->unite_extend_pixel; val = h_offs + h_size - w; right.win[i].h_size = ALIGN(val, 8); right.win[i].h_offs -= right.win[i].h_size - val; @@ -1871,7 +1891,7 @@ static void rkisp_config_cmsk_dual(struct rkisp_device *dev, rkisp_idx_write(dev, ISP3X_CMSK_SIZE0 + i * 8, val, ISP_UNITE_RIGHT, false); } - w += RKMOUDLE_UNITE_EXTEND_PIXEL; + w += dev->hw_dev->unite_extend_pixel; ctrl = 0; if (left.win[0].win_en) { ctrl |= ISP3X_SW_CMSK_EN_MP; @@ -1970,7 +1990,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) u32 acq_mult = 0; u32 acq_prop = 0; u32 extend_line = 0; - u32 width, height, val; + u32 width, height; sensor = dev->active_sensor; in_fmt = &dev->isp_sdev.in_fmt; @@ -2069,37 +2089,25 @@ static int rkisp_config_isp(struct rkisp_device *dev) rkisp_unite_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true); if (dev->unite_div > ISP_UNITE_DIV1) - width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + width = width / 2 + dev->hw_dev->unite_extend_pixel; if (dev->unite_div == ISP_UNITE_DIV4) - height = height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + height = height / 2 + dev->hw_dev->unite_extend_pixel; /* Acquisition Size */ rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false); rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (acq_mult * width) | (acq_mult * width) << 16; - else - val = acq_mult * width; - rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width, false); /* ISP Out Area differ with ACQ is only FIFO, so don't crop in this */ rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true); rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = width | width << 16; - else - val = width; - rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false); if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) { rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height / 2, false); rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height / 2, false); } else { - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (height + extend_line) | (height + extend_line) << 16; - else - val = height + extend_line; - rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, val, false); - rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height + extend_line, false); + rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height + extend_line, false); } /* interrupt mask */ @@ -2132,7 +2140,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) rkisp_update_regs(dev, CIF_ISP_OUT_H_SIZE, CIF_ISP_OUT_V_SIZE); } - dev->is_aiisp_upd = dev->is_aiisp_en; + dev->is_aiisp_upd = (dev->is_aiisp_en || dev->aiisp_cfg.wr_linecnt); rkisp_config_cmsk(dev); rkisp_config_aiisp(dev); if (dev->hw_dev->is_single) @@ -2980,6 +2988,58 @@ err: return -EINVAL; } +static int rkisp_unite_div(struct rkisp_device *dev, u32 w, u32 h) +{ + struct rkisp_hw_dev *hw = dev->hw_dev; + u32 max_size, max_w, max_h; + + dev->unite_div = ISP_UNITE_DIV1; + if (hw->unite == ISP_UNITE_TWO && hw->isp_ver == ISP_V30) { + dev->unite_div = ISP_UNITE_DIV2; + return 0; + } + + switch (dev->isp_ver) { + case ISP_V30: + max_size = CIF_ISP_INPUT_W_MAX_V30 * CIF_ISP_INPUT_H_MAX_V30; + max_w = CIF_ISP_INPUT_W_MAX_V30; + max_h = max_size / w; + break; + case ISP_V32: + max_size = CIF_ISP_INPUT_W_MAX_V32 * CIF_ISP_INPUT_H_MAX_V32; + max_w = CIF_ISP_INPUT_W_MAX_V32; + max_h = max_size / w; + break; + case ISP_V32_L: + max_size = CIF_ISP_INPUT_W_MAX_V32_L * CIF_ISP_INPUT_H_MAX_V32_L; + max_w = CIF_ISP_INPUT_W_MAX_V32_L; + max_h = max_size / w; + break; + case ISP_V33: + max_size = CIF_ISP_INPUT_W_MAX_V33 * CIF_ISP_INPUT_H_MAX_V33; + max_w = CIF_ISP_INPUT_W_MAX_V33; + max_h = max_size / w; + break; + case ISP_V35: + max_size = CIF_ISP_INPUT_W_MAX_V35 * CIF_ISP_INPUT_H_MAX_V35; + max_w = CIF_ISP_INPUT_W_MAX_V35; + max_h = CIF_ISP_INPUT_H_MAX_V35; + break; + case ISP_V39: + max_size = CIF_ISP_INPUT_W_MAX_V39_UNITE / 2 * CIF_ISP_INPUT_H_MAX_V39_UNITE; + max_w = CIF_ISP_INPUT_W_MAX_V39; + max_h = max_size / w; + break; + default: + return -EINVAL; + } + if (w * h > max_size * 2 || h > max_h) + dev->unite_div = ISP_UNITE_DIV4; + else if (w * h > max_size || w > max_w) + dev->unite_div = ISP_UNITE_DIV2; + return 0; +} + static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd, struct v4l2_rect *crop, u32 pad) @@ -2987,8 +3047,6 @@ static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd, struct rkisp_isp_subdev *isp_sd = sd_to_isp_sd(sd); struct rkisp_device *dev = sd_to_isp_dev(sd); struct v4l2_rect in_crop = isp_sd->in_crop; - struct rkisp_hw_dev *hw = dev->hw_dev; - u32 size; crop->left = ALIGN(crop->left, 2); crop->width = ALIGN(crop->width, 2); @@ -2997,38 +3055,7 @@ static void rkisp_isp_sd_try_crop(struct v4l2_subdev *sd, /* update sensor info if sensor link be changed */ rkisp_update_sensor_info(dev); rkisp_align_sensor_resolution(dev, crop, true); - if (hw->unite == ISP_UNITE_TWO && hw->isp_ver == ISP_V30) { - dev->unite_div = ISP_UNITE_DIV2; - } else { - dev->unite_div = ISP_UNITE_DIV1; - switch (dev->isp_ver) { - case ISP_V30: - size = CIF_ISP_INPUT_W_MAX_V30 * CIF_ISP_INPUT_H_MAX_V30; - break; - case ISP_V32: - size = CIF_ISP_INPUT_W_MAX_V32 * CIF_ISP_INPUT_H_MAX_V32; - break; - case ISP_V32_L: - size = CIF_ISP_INPUT_W_MAX_V32_L * CIF_ISP_INPUT_H_MAX_V32_L; - break; - case ISP_V33: - size = CIF_ISP_INPUT_W_MAX_V33 * CIF_ISP_INPUT_H_MAX_V33; - break; - case ISP_V35: - size = CIF_ISP_INPUT_W_MAX_V35 * CIF_ISP_INPUT_H_MAX_V35; - break; - case ISP_V39: - size = CIF_ISP_INPUT_W_MAX_V39_UNITE * CIF_ISP_INPUT_H_MAX_V39_UNITE; - size /= 2; - break; - default: - return; - } - if (crop->width * crop->height > size * 2) - dev->unite_div = ISP_UNITE_DIV4; - else if (crop->width * crop->height > size) - dev->unite_div = ISP_UNITE_DIV2; - } + rkisp_unite_div(dev, crop->width, crop->height); } else if (pad == RKISP_ISP_PAD_SOURCE_PATH) { crop->left = clamp_t(u32, crop->left, 0, in_crop.width); crop->top = clamp_t(u32, crop->top, 0, in_crop.height); @@ -3105,8 +3132,10 @@ static int rkisp_isp_sd_get_selection(struct v4l2_subdev *sd, CIF_ISP_INPUT_H_MAX_V33_UNITE : CIF_ISP_INPUT_H_MAX_V33; break; case ISP_V35: - max_w = CIF_ISP_INPUT_W_MAX_V35; - max_h = CIF_ISP_INPUT_H_MAX_V35; + max_w = dev->hw_dev->unite ? + CIF_ISP_INPUT_W_MAX_V35_UNITE : CIF_ISP_INPUT_W_MAX_V35; + max_h = dev->hw_dev->unite ? + CIF_ISP_INPUT_H_MAX_V35_UNITE : CIF_ISP_INPUT_H_MAX_V35; break; case ISP_V39: max_w = dev->hw_dev->unite ? @@ -3337,7 +3366,7 @@ static void rkisp_rx_qbuf_online(struct rkisp_stream *stream, rkisp_unite_write(dev, reg, val, false); if (dev->hw_dev->unite == ISP_UNITE_TWO || (dev->unite_div == ISP_UNITE_DIV2 && stream->id == RKISP_STREAM_RAWRD0)) { - u32 offs = stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL; + u32 offs = stream->out_fmt.width / 2 - dev->hw_dev->unite_extend_pixel; if (stream->memory) offs *= DIV_ROUND_UP(stream->out_isp_fmt.bpp[0], 8); @@ -3477,7 +3506,7 @@ static int rkisp_rx_buf_pool_init(struct rkisp_device *dev, "%s type:0x%x first:%d dbufs[%d]:%p", __func__, dbufs->type, dbufs->is_first, i, dbufs); - if (dbufs->is_resmem) { + if (dbufs->is_resmem && !dev->hw_dev->is_mmu) { dma = dbufs->dma; goto end; } @@ -3853,10 +3882,10 @@ static int rkisp_get_info(struct rkisp_device *dev, struct rkisp_isp_info *info) info->mode = mode; info->act_width = in_crop->width; if (dev->unite_div > ISP_UNITE_DIV1) - info->act_width = in_crop->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + info->act_width = in_crop->width / 2 + dev->hw_dev->unite_extend_pixel; info->act_height = in_crop->height; if (dev->unite_div == ISP_UNITE_DIV4) - info->act_height = in_crop->height / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + info->act_height = in_crop->height / 2 + dev->hw_dev->unite_extend_pixel; return 0; } @@ -3929,23 +3958,53 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) { unsigned long lock_flags = 0; u32 h = dev->isp_sdev.out_crop.height; - u32 wr_line, rd_line, irq, irq_mask, en, en_mask; + u32 wr_line, rd_line, irq_mask, en_mask; + u32 irq = 0, en = 0; spin_lock_irqsave(&dev->aiisp_lock, lock_flags); if (!dev->is_aiisp_upd) goto unlock; dev->is_aiisp_upd = false; - if (dev->is_aiisp_en) { - en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + if (dev->aiisp_cfg.wr_linecnt) irq = ISP39_AIISP_LINECNT_DONE; - if (dev->aiisp_cfg.rd_linecnt) - irq |= ISP3X_OUT_FRM_QUARTER; - } else { - irq = 0; - en = 0; + if (dev->aiisp_cfg.rd_linecnt) + irq |= ISP3X_OUT_FRM_QUARTER; + /* init aiisp stop */ + if (!(dev->isp_state & ISP_START) && dev->is_aiisp_stop) + goto unlock; + + if (dev->is_aiisp_en && !dev->aiisp_cfg.mode) { + if (!IS_HDR_RDBK(dev->rd_mode)) { + dev->is_aiisp_stopping = true; + dev->aiisp_stop_seq = dev->dmarx_dev.cur_frame.id; + goto unlock; + } else { + irq = 0; + dev->is_aiisp_en = false; + dev->is_aiisp_stop = true; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, false); + } + } else if (!dev->is_aiisp_en && dev->aiisp_cfg.mode) { + dev->is_aiisp_en = true; + dev->is_aiisp_stop = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, true); + if (!dev->hw_dev->is_single || IS_HDR_RDBK(dev->rd_mode)) + dev->is_aiisp_sync = true; } - irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER; - en_mask = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + + if (dev->is_aiisp_en) { + irq |= ISP3X_BAY3D_FRM_END; + if (!dev->is_aiisp_sync) + dev->irq_f_ends_mask |= ISP_FRAME_BNR; + en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + } + irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + if (dev->isp_ver == ISP_V39) + en_mask = ISP39_AIISP_EN; + else + en_mask = ISP35_AIISP_EN | ISP35_AIISP_ST; if (dev->aiisp_cfg.rd_linecnt >= h) rd_line = h - 1; @@ -3959,6 +4018,7 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_write(dev, ISP32_ISP_IRQ_CFG0, rd_line, false); rkisp_write(dev, ISP32_ISP_IRQ_CFG1, wr_line, false); rkisp_write(dev, ISP39_SLICE_ST_CTRL, 0, false); + rkisp_write(dev, CIF_ISP_ICR, irq_mask, false); rkisp_set_bits(dev, CIF_ISP_IMSC, irq_mask, irq, false); if (dev->isp_ver == ISP_V39) rkisp_set_bits(dev, ISP3X_MI_RD_CTRL2, en_mask, en, false); @@ -3966,21 +4026,40 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_set_bits(dev, ISP35_AI_CTRL, en_mask, en, false); unlock: spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); + if (dev->is_aiisp_stopping) + rkisp_vicap_hw_link(dev, false); } static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, struct rkisp_aiisp_cfg *cfg) { unsigned long lock_flags = 0; + int ret = -EINVAL; if (dev->isp_ver != ISP_V39 && dev->isp_ver != ISP_V35) - return -EINVAL; + return ret; + v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev, + "%s mode:%d wr:%d rd:%d wr_mode:%d\n", __func__, + cfg->mode, cfg->wr_linecnt, cfg->rd_linecnt, cfg->wr_mode); spin_lock_irqsave(&dev->aiisp_lock, lock_flags); - dev->is_aiisp_en = !!cfg->mode; + if (!(dev->isp_state & ISP_START)) { + if (!cfg->mode && cfg->wr_linecnt && cfg->rd_linecnt) { + /* TODO support multi-sensor */ + if (!dev->hw_dev->is_single) { + dev_err(dev->dev, + "aibnr no support dynamic switch for multi-sensor now\n"); + goto unlock; + } + dev->is_aiisp_stop = true; + } + dev->is_aiisp_en = !!cfg->mode; + } dev->is_aiisp_upd = true; dev->aiisp_cfg = *cfg; + ret = 0; +unlock: spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); - return 0; + return ret; } static int rkisp_get_aiisp_linecnt(struct rkisp_device *dev, @@ -4064,7 +4143,19 @@ static int rkisp_rdbk_aiisp_event(struct rkisp_device *dev, u32 cmd, void *arg) unsigned long lock_flags = 0; int val, ret = 0; - if (!dev->is_aiisp_en) + if (dev->is_aiisp_yuv && cmd == T_CMD_QUEUE) { + struct rkisp_stream *stream = &dev->cap_dev.stream[RKISP_STREAM_MP]; + struct rkisp_aiisp_st *st = arg; + + v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + "aiisp yuv input seq:%d idx(vpsl:%d aipre:%d ysrc:%d ydst:%d)\n", + st->sequence, st->vpsl_index, st->aipre_gain_index, + st->y_src_index, st->y_dest_index); + if (stream->ops->push_buf) + stream->ops->push_buf(stream); + } + + if (!dev->is_aiisp_en && !dev->is_aiisp_stop) return -EINVAL; spin_lock_irqsave(&dev->rdbk_lock, lock_flags); @@ -4092,7 +4183,8 @@ static int rkisp_rdbk_aiisp_event(struct rkisp_device *dev, u32 cmd, void *arg) } spin_unlock_irqrestore(&dev->rdbk_lock, lock_flags); - if (dev->is_aiisp_sync && arg && cmd == T_CMD_QUEUE) { + if (dev->is_aiisp_en && dev->is_aiisp_sync && + arg && cmd == T_CMD_QUEUE) { if (dev->hw_dev->is_idle) rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, NULL); goto end; @@ -4239,10 +4331,10 @@ static int rkisp_vicap_sof(struct rkisp_device *dev, struct rkisp_vicap_sof *sof spin_lock_irqsave(&dev->rdbk_lock, flag); if (!IS_HDR_RDBK(dev->rd_mode) && sof->sequence - dev->dmarx_dev.cur_frame.id > 1) { - v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, "vicap sof %d, isp sof %d\n", sof->sequence, dev->dmarx_dev.cur_frame.id); - dev->dmarx_dev.cur_frame.id = sof->sequence; + dev->dmarx_dev.cur_frame.id = sof->sequence - 1; } spin_unlock_irqrestore(&dev->rdbk_lock, flag); return 0; @@ -4397,6 +4489,9 @@ static long rkisp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case RKISP_VICAP_CMD_MODE: ret = rkisp_set_work_mode_by_vicap(isp_dev, arg); break; + case RKISP_VICAP_CMD_GET_UNITE_EXTEND_PIXEL: + *(int *)arg = isp_dev->hw_dev->unite_extend_pixel; + break; case RKISP_CMD_GET_BAY3D_BUFFD: rkisp_params_get_bay3d_buffd(&isp_dev->params_vdev, arg); break; @@ -5229,10 +5324,8 @@ vs_skip: if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode) rkisp_stats_rdbk_enable(&dev->stats_vdev, false); - if (!IS_HDR_RDBK(dev->hdr.op_mode)) { - rkisp_config_aiisp(dev); + if (!IS_HDR_RDBK(dev->hdr.op_mode)) rkisp_config_cmsk(dev); - } } if (isp_mis & CIF_ISP_FRAME) { diff --git a/drivers/media/platform/rockchip/isp/rkisp.h b/drivers/media/platform/rockchip/isp/rkisp.h index 5b635b53c44d..9a3c8fc600a9 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.h +++ b/drivers/media/platform/rockchip/isp/rkisp.h @@ -73,6 +73,8 @@ #define CIF_ISP_INPUT_H_MAX_V33_UNITE 2160 #define CIF_ISP_INPUT_W_MAX_V35 4096 #define CIF_ISP_INPUT_H_MAX_V35 3072 +#define CIF_ISP_INPUT_W_MAX_V35_UNITE 7168 +#define CIF_ISP_INPUT_H_MAX_V35_UNITE 5120 #define CIF_ISP_INPUT_W_MIN 272 #define CIF_ISP_INPUT_H_MIN 264 #define CIF_ISP_OUTPUT_W_MAX CIF_ISP_INPUT_W_MAX diff --git a/drivers/media/platform/rockchip/vpss/common.h b/drivers/media/platform/rockchip/vpss/common.h index 24243c0922db..98ae5bd21593 100644 --- a/drivers/media/platform/rockchip/vpss/common.h +++ b/drivers/media/platform/rockchip/vpss/common.h @@ -51,6 +51,12 @@ enum { ROCKIT_DVBM_START, }; +enum { + DVBM_DEINIT = 0, + DVBM_ONLINE = 1, + DVBM_OFFLINE = 2, +}; + enum rkvpss_fmt_pix_type { FMT_YUV, FMT_RGB, @@ -112,6 +118,7 @@ static inline int vpss_outchn_max(int version) } extern int rkvpss_debug; +extern int rkvpss_buf_dbg; extern struct platform_driver rkvpss_plat_drv; extern int rkvpss_cfginfo_num; diff --git a/drivers/media/platform/rockchip/vpss/dev.c b/drivers/media/platform/rockchip/vpss/dev.c index 9aafaf79b229..0a0bd3373999 100644 --- a/drivers/media/platform/rockchip/vpss/dev.c +++ b/drivers/media/platform/rockchip/vpss/dev.c @@ -18,6 +18,10 @@ int rkvpss_debug; module_param_named(debug, rkvpss_debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-6)"); +int rkvpss_buf_dbg; +module_param_named(buf_dbg, rkvpss_buf_dbg, int, 0644); +MODULE_PARM_DESC(buf_dbg, "rkvpss buf dbg"); + static bool rkvpss_clk_dbg; module_param_named(clk_dbg, rkvpss_clk_dbg, bool, 0644); MODULE_PARM_DESC(clk_dbg, "rkvpss clk set by user"); @@ -315,6 +319,7 @@ static int rkvpss_plat_probe(struct platform_device *pdev) dev_set_drvdata(dev, vpss_dev); vpss_dev->dev = dev; + vpss_dev->unite_extend_pixel = 128; ret = rkvpss_attach_hw(vpss_dev); if (ret) diff --git a/drivers/media/platform/rockchip/vpss/dev.h b/drivers/media/platform/rockchip/vpss/dev.h index a91f844dcad8..70ae49c04e96 100644 --- a/drivers/media/platform/rockchip/vpss/dev.h +++ b/drivers/media/platform/rockchip/vpss/dev.h @@ -91,6 +91,7 @@ struct rkvpss_device { bool mir_en; bool cmsc_upd; u32 unite_mode; + u32 unite_extend_pixel; u8 unite_index; bool stopping; wait_queue_head_t stop_done; diff --git a/drivers/media/platform/rockchip/vpss/hw.h b/drivers/media/platform/rockchip/vpss/hw.h index fc15d667aba3..e1fd4f76b7d9 100644 --- a/drivers/media/platform/rockchip/vpss/hw.h +++ b/drivers/media/platform/rockchip/vpss/hw.h @@ -70,6 +70,8 @@ struct rkvpss_hw_dev { bool is_suspend; bool is_first; bool is_probe_end; + int dvbm_refcnt; + int dvbm_flag; }; #ifdef CONFIG_VIDEO_ROCKCHIP_VPSS_V10 diff --git a/drivers/media/platform/rockchip/vpss/regs_v20.h b/drivers/media/platform/rockchip/vpss/regs_v20.h index f6b01e3db9cf..6eb86c8083ad 100644 --- a/drivers/media/platform/rockchip/vpss/regs_v20.h +++ b/drivers/media/platform/rockchip/vpss/regs_v20.h @@ -296,8 +296,17 @@ /* SCALE_CTRL */ +#define RKVPSS2X_SW_SCL_HY_EN BIT(0) +#define RKVPSS2X_SW_SCL_HC_EN BIT(1) +#define RKVPSS2X_SW_SCL_VY_EN BIT(2) +#define RKVPSS2X_SW_SCL_VC_EN BIT(3) #define RKVPSS2X_SW_AVG_SCALE_H_EN BIT(8) #define RKVPSS2X_SW_AVG_SCALE_V_EN BIT(9) +#define RKVPSS2X_SW_SCL_HPHASE_EN BIT(12) +#define RKVPSS2X_SW_SCL_CLIP_EN BIT(13) +#define RKVPSS2X_SW_SCL_IN_CLIP_EN BIT(14) +#define RKVPSS2X_SW_SCL_422TO420_EN BIT(30) +#define RKVPSS2X_SW_SCL_YUV420_REAL_EN BIT(31) /* MI_FORCE_UPDATE */ #define RKVPSS2X_MI_CHN4_FORCE_UPD BIT(8) diff --git a/drivers/media/platform/rockchip/vpss/stream_v10.c b/drivers/media/platform/rockchip/vpss/stream_v10.c index 6ac0a5a4e50c..f62ee0583e5c 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v10.c +++ b/drivers/media/platform/rockchip/vpss/stream_v10.c @@ -595,17 +595,17 @@ static void calc_unite_scl_params(struct rkvpss_stream *stream) if (stream->id == 0 && stream->crop.width != stream->out_fmt.width) { right_y_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_y - 3; right_c_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_c - 6; } else { right_y_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_y; right_c_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_c; } @@ -1165,7 +1165,7 @@ static int rkvpss_stream_crop(struct rkvpss_stream *stream, bool on, bool sync) VPSS_UNITE_LEFT); else rkvpss_idx_write(dev, reg_h_size, crop->width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL, VPSS_UNITE_LEFT); + dev->unite_extend_pixel, VPSS_UNITE_LEFT); rkvpss_idx_write(dev, reg_v_size, crop->height, VPSS_UNITE_LEFT); v4l2_dbg(4, rkvpss_debug, &dev->v4l2_dev, "left crop left:%d top:%d w:%d h:%d\n", @@ -1180,8 +1180,8 @@ static int rkvpss_stream_crop(struct rkvpss_stream *stream, bool on, bool sync) VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_v_offs, crop->top, VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_h_size, crop->width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - - stream->unite_params.quad_crop_w, VPSS_UNITE_RIGHT); + dev->unite_extend_pixel - stream->unite_params.quad_crop_w, + VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_v_size, crop->height, VPSS_UNITE_RIGHT); v4l2_dbg(4, rkvpss_debug, &dev->v4l2_dev, "right crop left:%d top:%d w:%d h:%d\n", @@ -1264,7 +1264,7 @@ static void poly_phase_scale(struct rkvpss_stream *stream, bool on, bool sync) if (in_w == out_w) val = (in_w / 2 - 1) | ((in_h - 1) << 16); else - val = (in_w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL - 1) | + val = (in_w / 2 + dev->unite_extend_pixel - 1) | ((in_h - 1) << 16); rkvpss_idx_write(dev, RKVPSS_ZME_Y_SRC_SIZE, val, VPSS_UNITE_LEFT); rkvpss_idx_write(dev, RKVPSS_ZME_UV_SRC_SIZE, val, VPSS_UNITE_LEFT); @@ -1602,7 +1602,7 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) if (in_w == out_w) val = (in_w / 2) | (in_h << 16); else - val = (in_w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL) | (in_h << 16); + val = (in_w / 2 + dev->unite_extend_pixel) | (in_h << 16); reg = stream->config->scale.src_size; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_LEFT); @@ -1668,7 +1668,7 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) reg = stream->config->scale.hc_offs_mi; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_RIGHT); - val = (in_w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL) | (in_h << 16); + val = (in_w / 2 + dev->unite_extend_pixel) | (in_h << 16); reg = stream->config->scale.src_size; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_RIGHT); @@ -2469,29 +2469,29 @@ void rkvpss_cmsc_config_v10(struct rkvpss_device *dev, bool sync) win->point[1].x != win->point[2].x) { right_cfg.win[i].win_en &= ~BIT(j); } else { - win->point[0].x = RKMOUDLE_UNITE_EXTEND_PIXEL; - win->point[3].x = RKMOUDLE_UNITE_EXTEND_PIXEL; + win->point[0].x = dev->unite_extend_pixel; + win->point[3].x = dev->unite_extend_pixel; win->point[1].x = win->point[1].x - (dev->vpss_sdev.in_fmt.width / 2) - + RKMOUDLE_UNITE_EXTEND_PIXEL; + + dev->unite_extend_pixel; win->point[2].x = win->point[2].x - (dev->vpss_sdev.in_fmt.width / 2) - + RKMOUDLE_UNITE_EXTEND_PIXEL; + + dev->unite_extend_pixel; } } else { /** all right **/ win->point[0].x = win->point[0].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[1].x = win->point[1].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[2].x = win->point[2].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[3].x = win->point[3].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; } } } diff --git a/drivers/media/platform/rockchip/vpss/stream_v20.c b/drivers/media/platform/rockchip/vpss/stream_v20.c index 420e292c43ef..d2d3f6beff58 100644 --- a/drivers/media/platform/rockchip/vpss/stream_v20.c +++ b/drivers/media/platform/rockchip/vpss/stream_v20.c @@ -746,9 +746,9 @@ static struct stream_config scl5_config = { .uv_offs_cnt = RKVPSS2X_MI_CHN5_WR_CB_OFFS_CNT, .y_pic_width = RKVPSS2X_MI_CHN5_WR_Y_PIC_WIDTH, .y_pic_size = RKVPSS2X_MI_CHN5_WR_Y_PIC_SIZE, - .ctrl_shd = RKVPSS2X_MI_CHN4_WR_CTRL_SHD, - .y_shd = RKVPSS2X_MI_CHN4_WR_Y_BASE_SHD, - .uv_shd = RKVPSS2X_MI_CHN4_WR_CB_BASE_SHD, + .ctrl_shd = RKVPSS2X_MI_CHN5_WR_CTRL_SHD, + .y_shd = RKVPSS2X_MI_CHN5_WR_Y_BASE_SHD, + .uv_shd = RKVPSS2X_MI_CHN5_WR_CB_BASE_SHD, }, }; @@ -791,17 +791,17 @@ static void calc_unite_scl_params(struct rkvpss_stream *stream) if (stream->id == 0 && stream->crop.width != stream->out_fmt.width) { right_y_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_y - 3; right_c_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_c - 6; } else { right_y_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_y; right_c_crop_total = stream->crop.width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - + stream->dev->unite_extend_pixel - right_scl_need_size_c; } @@ -887,7 +887,7 @@ static void scl_force_update(struct rkvpss_stream *stream) val = RKVPSS2X_MI_CHN4_FORCE_UPD; break; case RKVPSS_OUTPUT_CH5: - val = RKVPSS2X_MI_CHN4_FORCE_UPD; + val = RKVPSS2X_MI_CHN5_FORCE_UPD; break; default: return; @@ -1129,7 +1129,7 @@ static void scl_disable_mi(struct rkvpss_stream *stream) val = RKVPSS2X_ISP2VPSS_CHN4_SEL(3); break; case RKVPSS_OUTPUT_CH5: - val = RKVPSS2X_ISP2VPSS_CHN4_SEL(3); + val = RKVPSS2X_ISP2VPSS_CHN5_SEL(3); break; default: return; @@ -1455,7 +1455,7 @@ static int rkvpss_stream_crop_ch4_5(struct rkvpss_stream *stream, bool on, bool if (crop->width == stream->out_fmt.width) h_size = crop->width / 2; else - h_size = crop->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + h_size = crop->width / 2 + dev->unite_extend_pixel; v_size = crop->height; rkvpss_idx_write(dev, reg_ch4_5_size, @@ -1471,7 +1471,7 @@ static int rkvpss_stream_crop_ch4_5(struct rkvpss_stream *stream, bool on, bool rkvpss_idx_set_bits(dev, reg_ctrl, 0, val, VPSS_UNITE_RIGHT); h_offs = stream->unite_params.quad_crop_w; v_offs = crop->top; - h_size = crop->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL - + h_size = crop->width / 2 + dev->unite_extend_pixel - stream->unite_params.quad_crop_w; v_size = crop->height; rkvpss_idx_write(dev, reg_ch4_5_offs, @@ -1554,7 +1554,7 @@ static int rkvpss_stream_crop(struct rkvpss_stream *stream, bool on, bool sync) VPSS_UNITE_LEFT); else rkvpss_idx_write(dev, reg_h_size, crop->width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL, VPSS_UNITE_LEFT); + dev->unite_extend_pixel, VPSS_UNITE_LEFT); rkvpss_idx_write(dev, reg_v_size, crop->height, VPSS_UNITE_LEFT); v4l2_dbg(4, rkvpss_debug, &dev->v4l2_dev, "left crop left:%d top:%d w:%d h:%d\n", @@ -1569,8 +1569,8 @@ static int rkvpss_stream_crop(struct rkvpss_stream *stream, bool on, bool sync) VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_v_offs, crop->top, VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_h_size, crop->width / 2 + - RKMOUDLE_UNITE_EXTEND_PIXEL - - stream->unite_params.quad_crop_w, VPSS_UNITE_RIGHT); + dev->unite_extend_pixel - + stream->unite_params.quad_crop_w, VPSS_UNITE_RIGHT); rkvpss_idx_write(dev, reg_v_size, crop->height, VPSS_UNITE_RIGHT); v4l2_dbg(4, rkvpss_debug, &dev->v4l2_dev, "right crop left:%d top:%d w:%d h:%d\n", @@ -1604,15 +1604,12 @@ static void average_scale_down(struct rkvpss_stream *stream, bool on, bool sync) /*config scl clk gate*/ switch (stream->id) { - case RKVPSS_OUTPUT_CH1: - clk_mask = RKVPSS_SCL1_CKG_DIS; + case RKVPSS_OUTPUT_CH0: + clk_mask = RKVPSS_SCL0_CKG_DIS; break; case RKVPSS_OUTPUT_CH2: clk_mask = RKVPSS_SCL2_CKG_DIS; break; - case RKVPSS_OUTPUT_CH3: - clk_mask = RKVPSS_SCL3_CKG_DIS; - break; default: return; } @@ -1651,11 +1648,11 @@ static void average_scale_down(struct rkvpss_stream *stream, bool on, bool sync) ctrl |= RKVPSS_SCL_HY_EN | RKVPSS_SCL_HC_EN | RKVPSS2X_SW_AVG_SCALE_H_EN; } if (in_h != out_h || !sync) { - val = (out_h - 1) * 65536 / (out_h - 1) + 1; + val = (out_h - 1) * 65536 / (in_h - 1) + 1; reg = stream->config->scale.vy_fac; rkvpss_unite_write(dev, reg, val); - val = (out_h - 1) * 4096 / (in_h - 1) + 1; + val = (out_h - 1) * 65536 / (in_h - 1) + 1; reg = stream->config->scale.vc_fac; rkvpss_unite_write(dev, reg, val); @@ -1822,7 +1819,7 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) if (in_w == out_w) val = (in_w / 2) | (in_h << 16); else - val = (in_w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL) | (in_h << 16); + val = (in_w / 2 + dev->unite_extend_pixel) | (in_h << 16); reg = stream->config->scale.src_size; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_LEFT); @@ -1887,7 +1884,7 @@ static void bilinear_scale(struct rkvpss_stream *stream, bool on, bool sync) reg = stream->config->scale.hc_offs_mi; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_RIGHT); - val = (in_w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL) | (in_h << 16); + val = (in_w / 2 + dev->unite_extend_pixel) | (in_h << 16); reg = stream->config->scale.src_size; rkvpss_idx_write(dev, reg, val, VPSS_UNITE_RIGHT); @@ -1947,12 +1944,10 @@ static void rkvpss_stream_stop(struct rkvpss_stream *stream) int ret; stream->stopping = true; - if (atomic_read(&dev->pipe_stream_cnt) > 0) { - ret = wait_event_timeout(stream->done, !stream->streaming, - msecs_to_jiffies(300)); - if (!ret) - v4l2_warn(&dev->v4l2_dev, "%s id:%d timeout\n", __func__, stream->id); - } + ret = wait_event_timeout(stream->done, !stream->streaming, + msecs_to_jiffies(300)); + if (!ret) + v4l2_warn(&dev->v4l2_dev, "%s id:%d timeout\n", __func__, stream->id); stream->stopping = false; stream->streaming = false; if (stream->ops->disable_mi) @@ -1992,6 +1987,13 @@ static void rkvpss_stop_streaming(struct vb2_queue *queue) destroy_buf_queue(stream, VB2_BUF_STATE_ERROR); rkvpss_pipeline_close(dev); tasklet_disable(&stream->buf_done_tasklet); + + if (hw->dvbm_refcnt <= 0 && hw->dvbm_flag != DVBM_OFFLINE) { + v4l2_dbg(2, rkvpss_debug, &dev->v4l2_dev, "%s: clear vpss2enc_sel\n", __func__); + rkvpss_hw_clear_bits(hw, RKVPSS_VPSS_CTRL, RKVPSS_VPSS2ENC_SEL); + hw->dvbm_refcnt = 0; + } + v4l2_dbg(1, rkvpss_debug, &dev->v4l2_dev, "%s %s id:%d exit\n", __func__, node->vdev.name, stream->id); @@ -2103,7 +2105,10 @@ static int rkvpss_start_streaming(struct vb2_queue *queue, unsigned int count) goto pipe_close; } if (dev->stream_vdev.wrap_line && stream->id == RKVPSS_OUTPUT_CH0) - rkvpss_dvbm_init(stream); + if (rkvpss_dvbm_init(stream) != 0) { + v4l2_err(&dev->v4l2_dev, "dvbm init failed\n"); + goto stop_stream; + } ret = rkvpss_pipeline_stream(dev, true); if (ret < 0) goto stop_stream; @@ -2741,29 +2746,29 @@ void rkvpss_cmsc_config_v20(struct rkvpss_device *dev, bool sync) win->point[1].x != win->point[2].x) { right_cfg.win[i].win_en &= ~BIT(j); } else { - win->point[0].x = RKMOUDLE_UNITE_EXTEND_PIXEL; - win->point[3].x = RKMOUDLE_UNITE_EXTEND_PIXEL; + win->point[0].x = dev->unite_extend_pixel; + win->point[3].x = dev->unite_extend_pixel; win->point[1].x = win->point[1].x - (dev->vpss_sdev.in_fmt.width / 2) - + RKMOUDLE_UNITE_EXTEND_PIXEL; + + dev->unite_extend_pixel; win->point[2].x = win->point[2].x - (dev->vpss_sdev.in_fmt.width / 2) - + RKMOUDLE_UNITE_EXTEND_PIXEL; + + dev->unite_extend_pixel; } } else { /** all right **/ win->point[0].x = win->point[0].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[1].x = win->point[1].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[2].x = win->point[2].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; win->point[3].x = win->point[3].x - (dev->vpss_sdev.in_fmt.width / 2) + - RKMOUDLE_UNITE_EXTEND_PIXEL; + dev->unite_extend_pixel; } } } diff --git a/drivers/media/platform/rockchip/vpss/vpss.c b/drivers/media/platform/rockchip/vpss/vpss.c index b623b1bcdce4..2ec3652a09f9 100644 --- a/drivers/media/platform/rockchip/vpss/vpss.c +++ b/drivers/media/platform/rockchip/vpss/vpss.c @@ -184,7 +184,7 @@ static int rkvpss_sd_s_stream(struct v4l2_subdev *sd, int on) rkvpss_cmsc_config(dev, true); if (dev->unite_mode) - w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL; + w = w / 2 + dev->unite_extend_pixel; rkvpss_unite_write(dev, RKVPSS_VPSS_ONLINE2_SIZE, h << 16 | w); @@ -236,6 +236,8 @@ static int rkvpss_sd_s_power(struct v4l2_subdev *sd, int on) return ret; } } + v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_GET_UNITE_EXTEND_PIXEL, + &dev->unite_extend_pixel); v4l2_subdev_call(dev->remote_sd, core, ioctl, RKISP_VPSS_GET_UNITE_MODE, &dev->unite_mode); ret = pm_runtime_get_sync(dev->dev); diff --git a/drivers/media/platform/rockchip/vpss/vpss_dvbm.c b/drivers/media/platform/rockchip/vpss/vpss_dvbm.c index 8e0dc0f14bc6..bc39e9263f2c 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_dvbm.c +++ b/drivers/media/platform/rockchip/vpss/vpss_dvbm.c @@ -50,6 +50,14 @@ int rkvpss_dvbm_init(struct rkvpss_stream *stream) if (!g_dvbm) return -EINVAL; + if (vpss_dev->hw_dev->dvbm_flag == DVBM_OFFLINE) { + v4l2_err(&vpss_dev->v4l2_dev, + "offline dvbm already set, online dvbm set fail.\n"); + return -EINVAL; + } + + vpss_dev->hw_dev->dvbm_refcnt++; + vpss_dev->hw_dev->dvbm_flag = DVBM_ONLINE; width = stream->out_fmt.plane_fmt[0].bytesperline; height = stream->out_fmt.height; @@ -76,6 +84,11 @@ void rkvpss_dvbm_deinit(struct rkvpss_device *vpss_dev) pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_dvbm, vpss_dev); return; } + + vpss_dev->hw_dev->dvbm_refcnt--; + if (vpss_dev->hw_dev->dvbm_refcnt <= 0) + vpss_dev->hw_dev->dvbm_flag = DVBM_DEINIT; + rk_dvbm_unlink(g_dvbm, vpss_dev->dev_id); } diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.c b/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.c index dcc8050766e2..aa160d29d156 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.c @@ -38,13 +38,20 @@ int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl) return ret; } -int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, - int width, int height, int id) +int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf, u32 dma_addr, + u32 wrap_line, int width, int height, int id) { struct dvbm_isp_cfg_t dvbm_cfg; if (!g_ofl_dvbm) return -EINVAL; + if (ofl->hw->dvbm_flag == DVBM_ONLINE) { + v4l2_err(&ofl->v4l2_dev, + "online dvbm already set, offline dvbm set fail.\n"); + return -EINVAL; + } + + ofl->hw->dvbm_flag = DVBM_OFFLINE; dvbm_cfg.dma_addr = dma_addr; dvbm_cfg.buf = dbuf; @@ -70,7 +77,10 @@ void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id) pr_err("g_dvbm %p or vpss_dev %p is NULL\n", g_ofl_dvbm, ofl); return; } + ofl->hw->dvbm_flag = DVBM_DEINIT; rk_dvbm_unlink(g_ofl_dvbm, id); + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, "%s: clear vpss2enc_sel\n", __func__); + rkvpss_hw_clear_bits(ofl->hw, RKVPSS_VPSS_CTRL, RKVPSS_VPSS2ENC_SEL); } int rkvpss_ofl_dvbm_event(u32 event, u32 seq) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.h b/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.h index 90b22bd72b4c..888221f8557a 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.h +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_dvbm.h @@ -12,12 +12,15 @@ #if IS_ENABLED(CONFIG_ROCKCHIP_DVBM) int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl); -int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id); +int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf, + u32 dma_addr, u32 wrap_line, int width, int height, int id); void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id); int rkvpss_ofl_dvbm_event(u32 event, u32 seq); #else static inline int rkvpss_ofl_dvbm_get(struct rkvpss_offline_dev *ofl) {return -EINVAL; } -static inline int rkvpss_ofl_dvbm_init(struct dma_buf *dbuf, u32 dma_addr, u32 wrap_line, int width, int height, int id) {return -EINVAL; } +static inline int rkvpss_ofl_dvbm_init(struct rkvpss_offline_dev *ofl, struct dma_buf *dbuf, + u32 dma_addr, u32 wrap_line, int width, int height, + int id) {return -EINVAL; } static inline void rkvpss_ofl_dvbm_deinit(struct rkvpss_offline_dev *ofl, int id) {} static inline int rkvpss_ofl_dvbm_event(u32 event, u32 seq) {return -EINVAL; } #endif diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c index e75883ad57b3..2802a156befb 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline_v20.c @@ -324,32 +324,124 @@ static void average_scale_down(struct rkvpss_frame_cfg *frame_cfg, rkvpss_hw_set_bits(hw, RKVPSS_VPSS_CLK_GATE, clk_mask, clk_mask); if (!unite) { - if (in_w == out_w && in_h == out_w) + if (in_w == out_w && in_h == out_h) goto end; val = in_w | (in_h << 16); - rkvpss_hw_write(hw, reg_base + 0x8, val); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ val = out_w | (out_h << 16); - rkvpss_hw_write(hw, reg_base + 0xc, val); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ if (in_w != out_w) { val = (out_w - 1) * 65536 / (in_w - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x10, val); - val = (out_w / 2 - 1) * 65536 / (in_w / 2 - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x14, val); - - ctrl |= RKVPSS_SCL_HY_EN | RKVPSS_SCL_HC_EN | RKVPSS2X_SW_AVG_SCALE_H_EN; + rkvpss_hw_write(hw, reg_base + 0x10, val); /* y_w_fac */ + rkvpss_hw_write(hw, reg_base + 0x14, val); /* c_w_fac */ + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; } + if (in_h != out_h) { val = (out_h - 1) * 65536 / (in_h - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x18, val); - val = (out_h - 1) * 65536 / (in_h - 1) + 1; - rkvpss_hw_write(hw, reg_base + 0x1c, val); + rkvpss_hw_write(hw, reg_base + 0x18, val); /* y_h_fac */ + rkvpss_hw_write(hw, reg_base + 0x1c, val); /* c_h_fac */ + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; + } + } else { + u32 in_width = cfg->crop_width / 2; + u32 out_width = cfg->scl_width / 2; + u32 overlap = UNITE_ENLARGE; - ctrl |= RKVPSS_SCL_VY_EN | RKVPSS_SCL_VC_EN | RKVPSS2X_SW_AVG_SCALE_V_EN; + if (left) { + /* Left side processing */ + rkvpss_hw_write(hw, reg_base + 0x50, 0); /* in_crop_offs */ + rkvpss_hw_write(hw, reg_base + 0x20, 0); /* hy_offs */ + rkvpss_hw_write(hw, reg_base + 0x24, 0); /* hc_offs */ + rkvpss_hw_write(hw, reg_base + 0x28, 0); /* vy_offs */ + rkvpss_hw_write(hw, reg_base + 0x2c, 0); /* vc_offs */ + rkvpss_hw_write(hw, reg_base + 0x48, 0); /* hy_offs_mi */ + rkvpss_hw_write(hw, reg_base + 0x4c, 0); /* hc_offs_mi */ + + u32 in_w_for_hw = (in_width == out_width) ? in_width : (in_width + overlap); + u32 aligned_width = ALIGN(in_w_for_hw, 16); + + val = aligned_width | (cfg->crop_height << 16); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ + + aligned_width = ALIGN(out_width, 16); + val = aligned_width | (cfg->scl_height << 16); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ + + ctrl |= RKVPSS2X_SW_SCL_CLIP_EN; + } else { + /* Right side processing */ + val = ofl->unite_params[idx].scl_in_crop_w_y | + (ofl->unite_params[idx].scl_in_crop_w_c << 4); + rkvpss_hw_write(hw, reg_base + 0x50, val); /* in_crop_offs */ + + ctrl |= RKVPSS2X_SW_SCL_HPHASE_EN; + + u32 y_phase = ofl->unite_params[idx].y_w_phase; + u32 c_phase = ofl->unite_params[idx].c_w_phase; + + rkvpss_hw_write(hw, reg_base + 0x20, y_phase); /* hy_offs */ + rkvpss_hw_write(hw, reg_base + 0x24, c_phase); /* hc_offs */ + rkvpss_hw_write(hw, reg_base + 0x28, 0); /* vy_offs */ + rkvpss_hw_write(hw, reg_base + 0x2c, 0); /* vc_offs */ + + val = 16 - (cfg->scl_width / 2 & 0xf); + if (val == 16) + val = 0; + rkvpss_hw_write(hw, reg_base + 0x48, val); /* hy_offs_mi */ + rkvpss_hw_write(hw, reg_base + 0x4c, val); /* hc_offs_mi */ + + u32 in_w_for_hw = (in_width == out_width) ? in_width : (in_width + overlap); + u32 aligned_width = ALIGN(in_w_for_hw, 16); + + val = aligned_width | (cfg->crop_height << 16); + rkvpss_hw_write(hw, reg_base + 0x8, val); /* input size */ + + aligned_width = ALIGN(out_width, 16); + val = aligned_width | (cfg->scl_height << 16); + rkvpss_hw_write(hw, reg_base + 0xc, val); /* output size */ + + v4l2_dbg(1, rkvpss_debug, &ofl->v4l2_dev, + "Right side: in_w=%d out_w=%d y_phase=0x%x c_phase=0x%x mi_offset=0x%x\n", + aligned_width, out_width, y_phase, c_phase, val); + + if (in_width != out_width) { + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; + } + if (cfg->crop_height != cfg->scl_height) { + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; + } + + if (overlap > 0) { + ctrl |= RKVPSS2X_SW_SCL_CLIP_EN; + if (aligned_width > out_width) + ctrl |= RKVPSS2X_SW_SCL_IN_CLIP_EN; + } + } + + if (cfg->scl_width != frame_cfg->input.width) { + val = ofl->unite_params[idx].y_w_fac; + rkvpss_hw_write(hw, reg_base + 0x10, val); /* y_w_fac */ + val = ofl->unite_params[idx].c_w_fac; + rkvpss_hw_write(hw, reg_base + 0x14, val); /* c_w_fac */ + ctrl |= RKVPSS2X_SW_SCL_HY_EN | RKVPSS2X_SW_SCL_HC_EN | + RKVPSS2X_SW_AVG_SCALE_H_EN; + } + if (cfg->scl_height != frame_cfg->input.height) { + val = ofl->unite_params[idx].y_h_fac; + rkvpss_hw_write(hw, reg_base + 0x18, val); /* y_h_fac */ + val = ofl->unite_params[idx].c_h_fac; + rkvpss_hw_write(hw, reg_base + 0x1c, val); /* c_h_fac */ + ctrl |= RKVPSS2X_SW_SCL_VY_EN | RKVPSS2X_SW_SCL_VC_EN | + RKVPSS2X_SW_AVG_SCALE_V_EN; } } - //unite todo end: rkvpss_hw_write(hw, reg_base, ctrl); @@ -410,7 +502,7 @@ static void bilinear_scale(struct rkvpss_frame_cfg *frame_cfg, rkvpss_hw_set_bits(hw, RKVPSS_VPSS_CLK_GATE, clk_mask, clk_mask); if (!unite) { - if (in_w == out_w && in_h == out_w) + if (in_w == out_w && in_h == out_h) goto end; /* TODO diff for input and output format */ @@ -507,14 +599,42 @@ static void scale_config(struct rkvpss_offline_dev *ofl, struct rkvpss_frame_cfg *cfg, bool unite, bool left) { int i; + bool is_downscale_w; + bool is_downscale_h; + bool use_average; for (i = 0; i < RKVPSS_OUT_V20_MAX; i++) { if (!cfg->output[i].enable) continue; - if ((i == 0 || i == 2) && cfg->output[i].avg_scl_down) - average_scale_down(cfg, ofl, &cfg->output[i], i, unite, left); - else - bilinear_scale(cfg, ofl, &cfg->output[i], i, unite, left); + is_downscale_w = cfg->output[i].scl_width <= cfg->output[i].crop_width; + is_downscale_h = cfg->output[i].scl_height <= cfg->output[i].crop_height; + use_average = is_downscale_w && is_downscale_h; + + /* channel 0 and 2 use average_scale_down when downscale */ + if (use_average && (i == RKVPSS_OUTPUT_CH0 || i == RKVPSS_OUTPUT_CH2)) { + if (unite) { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Unite mode: average_scale_down for channel %d\n", i); + average_scale_down(cfg, ofl, &cfg->output[i], i, true, true); + average_scale_down(cfg, ofl, &cfg->output[i], i, true, false); + } else { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Normal mode: average_scale_down for channel %d\n", i); + average_scale_down(cfg, ofl, &cfg->output[i], i, false, false); + } + } else { + /* use bilinear_scale for other channels */ + if (unite) { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Unite mode: bilinear_scale for channel %d\n", i); + bilinear_scale(cfg, ofl, &cfg->output[i], i, true, true); + bilinear_scale(cfg, ofl, &cfg->output[i], i, true, false); + } else { + v4l2_dbg(2, rkvpss_debug, &ofl->v4l2_dev, + "Normal mode: bilinear_scale for channel %d\n", i); + bilinear_scale(cfg, ofl, &cfg->output[i], i, false, false); + } + } } } @@ -1912,12 +2032,6 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } - /* set unite mode */ - if (cfg->input.width > RKVPSS_MAX_WIDTH_V20) - *unite = true; - else - *unite = false; - /* check input format */ switch (cfg->input.format) { case V4L2_PIX_FMT_NV16: @@ -2044,6 +2158,12 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, goto end; } + /* set unite mode */ + if (out_width > RKVPSS_MAX_WIDTH_V20) + *unite = true; + else + *unite = false; + /* check crop */ cfg->output[i].crop_h_offs = ALIGN(cfg->output[i].crop_h_offs, 2); cfg->output[i].crop_v_offs = ALIGN(cfg->output[i].crop_v_offs, 2); @@ -2233,12 +2353,7 @@ int rkvpss_check_params(struct rkvpss_offline_dev *ofl, ret = -EINVAL; goto end; } - if (cfg->output[i].scl_width > cfg->input.width) { - v4l2_err(&ofl->v4l2_dev, "dev_id:%d unite horizontal no support scale up\n", - cfg->dev_id); - ret = -EINVAL; - goto end; - } + if (cfg->output[i].aspt.enable) { v4l2_err(&ofl->v4l2_dev, "dev_id:%d unite no support aspt\n", cfg->dev_id); @@ -2438,7 +2553,7 @@ static long rkvpss_ofl_wrap_dvbm_init(struct rkvpss_offline_dev *ofl, wrap_line = cfg->output[i].wrap.wrap_line; - rkvpss_ofl_dvbm_init(dbuf, dma_addr, wrap_line, width, height, cfg->dev_id); + rkvpss_ofl_dvbm_init(ofl, dbuf, dma_addr, wrap_line, width, height, cfg->dev_id); v4l2_dbg(4, rkvpss_debug, &ofl->v4l2_dev, "%s file_id:%d dev_id:%d wrap_chn:%d\n", __func__, file_id, cfg->dev_id, i); diff --git a/drivers/media/platform/rockchip/vpss/vpss_rockit.c b/drivers/media/platform/rockchip/vpss/vpss_rockit.c index 6e5d7a8a1aa0..60e705815322 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_rockit.c +++ b/drivers/media/platform/rockchip/vpss/vpss_rockit.c @@ -216,8 +216,13 @@ int rkvpss_rockit_buf_queue(struct rockit_rkvpss_cfg *input_cfg) } vpssrk_buf->vaddr = NULL; - if (dma_buf_vmap(input_cfg->buf, &map) == 0) - vpssrk_buf->vaddr = map.vaddr; + /* default vmap two to get image, rkvpss_buf_dbg > 0 to vmap all */ + if (i < 2 || rkvpss_buf_dbg > 0) { + v4l2_dbg(3, rkvpss_debug, &vpss_dev->v4l2_dev, + "stream:%d rockit vmap buf:%p\n", stream->id, input_cfg->buf); + if (dma_buf_vmap(input_cfg->buf, &map) == 0) + vpssrk_buf->vaddr = map.vaddr; + } vpssrk_buf->buff_addr = sg_dma_address(sgt->sgl); get_dma_buf(input_cfg->buf); diff --git a/drivers/mfd/display-serdes/core.h b/drivers/mfd/display-serdes/core.h index e9b1169ac7dd..b905cbdc79b8 100644 --- a/drivers/mfd/display-serdes/core.h +++ b/drivers/mfd/display-serdes/core.h @@ -78,36 +78,42 @@ #include "../../../../drivers/extcon/extcon.h" #include "../../../../drivers/base/regmap/internal.h" -/* -* if enable all the debug information, -* there will be much log. -* -* so suggest set CONFIG_LOG_BUF_SHIFT to 18 -*/ -//#define SERDES_DEBUG_MFD -//#define SERDES_DEBUG_I2C -//#define SERDES_DEBUG_CHIP +/** + * Enabling verbose debug messages is done through the serdes_log_level parameter, each + * category being enabled by a bit: + * + * - serdes_log_level=0x1 will enable MFD messages + * - serdes_log_level=0x2 will enable I2C messages + * - serdes_log_level=0x4 will enable CHIP messages + * - serdes_log_level=0x7 will enable all messages + * + * An interesting feature is that it's possible to enable verbose logging at + * run-time by echoing the debug value in its sysfs node:: + * + * # echo 0x7 > /sys/kernel/debug/log_level + **/ -#ifdef SERDES_DEBUG_MFD -#define SERDES_DBG_MFD(x...) pr_info(x) -#else -#define SERDES_DBG_MFD(x...) no_printk(x) -#endif +enum serdes_log_category { + SERDES_MFD, + SERDES_I2C, + SERDES_CHIP, +}; -#ifdef SERDES_DEBUG_I2C -#define SERDES_DBG_I2C(x...) pr_info(x) -#else -#define SERDES_DBG_I2C(x...) no_printk(x) -#endif +#define SERDES_DBG_MFD(fmt, ...) serdes_dev_dbg(SERDES_MFD, fmt, ##__VA_ARGS__) +#define SERDES_DBG_I2C(fmt, ...) serdes_dev_dbg(SERDES_I2C, fmt, ##__VA_ARGS__) +#define SERDES_DBG_CHIP(fmt, ...) serdes_dev_dbg(SERDES_CHIP, fmt, ##__VA_ARGS__) -#ifdef SERDES_DEBUG_CHIP -#define SERDES_DBG_CHIP(x...) pr_info(x) -#else -#define SERDES_DBG_CHIP(x...) no_printk(x) -#endif +enum serdes_debug_mode { + SERDES_OPEN_I2C_WRITE, + SERDES_CLOSE_I2C_WRITE, + SERDES_SET_SEQUENCE, + SERDES_SET_PINCTRL_SLEEP, + SERDES_SET_PINCTRL_DEFAULT, +}; #define MFD_SERDES_DISPLAY_VERSION "serdes-mfd-displaly-v11-241025" #define MAX_NUM_SERDES_SPLIT 8 + struct serdes; enum ser_link_mode { SER_DUAL_LINK, @@ -387,13 +393,18 @@ struct serdes { struct workqueue_struct *mfd_wq; struct delayed_work mfd_delay_work; + bool route_enable; bool use_delay_work; + char dir_name[25]; + struct dentry *debugfs_dentry; + enum serdes_debug_mode debug; struct kthread_worker *kworker; struct kthread_delayed_work reg_check_work; bool use_reg_check_work; + bool dual_link; bool split_mode_enable; unsigned int reg_hw; unsigned int reg_use; @@ -420,8 +431,6 @@ struct serdes { /* Device I/O API */ int serdes_reg_read(struct serdes *serdes, unsigned int reg, unsigned int *val); int serdes_reg_write(struct serdes *serdes, unsigned int reg, unsigned int val); -void serdes_reg_lock(struct serdes *serdes); -int serdes_reg_unlock(struct serdes *serdes); int serdes_set_bits(struct serdes *serdes, unsigned int reg, unsigned int mask, unsigned int val); int serdes_bulk_read(struct serdes *serdes, unsigned int reg, @@ -441,11 +450,17 @@ void serdes_device_poweroff(struct serdes *serdes); int serdes_device_shutdown(struct serdes *serdes); int serdes_irq_init(struct serdes *serdes); void serdes_irq_exit(struct serdes *serdes); -void serdes_auxadc_init(struct serdes *serdes); + +void serdes_dev_dbg(enum serdes_log_category category, const char *format, ...); +void serdes_debugfs_init(void); +void serdes_debugfs_exit(void); +void serdes_create_debugfs(struct serdes *serdes); +void serdes_destroy_debugfs(struct serdes *serdes); extern struct serdes_chip_data serdes_bu18tl82_data; extern struct serdes_chip_data serdes_bu18rl82_data; extern struct serdes_chip_data serdes_max96745_data; +extern struct serdes_chip_data serdes_max96749_data; extern struct serdes_chip_data serdes_max96752_data; extern struct serdes_chip_data serdes_max96755_data; extern struct serdes_chip_data serdes_max96772_data; diff --git a/drivers/mfd/display-serdes/gpio.h b/drivers/mfd/display-serdes/gpio.h index 404e86354607..bb87511eb63f 100644 --- a/drivers/mfd/display-serdes/gpio.h +++ b/drivers/mfd/display-serdes/gpio.h @@ -43,6 +43,7 @@ enum serdes_id { ROHM_ID_BU18RL82, MAXIM_ID_MAX96745, + MAXIM_ID_MAX96749, MAXIM_ID_MAX96752, MAXIM_ID_MAX96755, MAXIM_ID_MAX96772, @@ -107,6 +108,35 @@ enum max96745_gpio_list { MAXIM_MAX96745_MFP25, }; +enum max96749_gpio_list { + MAXIM_MAX96749_MFP0 = 0, + MAXIM_MAX96749_MFP1, + MAXIM_MAX96749_MFP2, + MAXIM_MAX96749_MFP3, + MAXIM_MAX96749_MFP4, + MAXIM_MAX96749_MFP5, + MAXIM_MAX96749_MFP6, + MAXIM_MAX96749_MFP7, + MAXIM_MAX96749_MFP8, + MAXIM_MAX96749_MFP9, + MAXIM_MAX96749_MFP10, + MAXIM_MAX96749_MFP11, + MAXIM_MAX96749_MFP12, + MAXIM_MAX96749_MFP13, + MAXIM_MAX96749_MFP14, + MAXIM_MAX96749_MFP15, + MAXIM_MAX96749_MFP16, + MAXIM_MAX96749_MFP17, + MAXIM_MAX96749_MFP18, + MAXIM_MAX96749_MFP19, + MAXIM_MAX96749_MFP20, + MAXIM_MAX96749_MFP21, + MAXIM_MAX96749_MFP22, + MAXIM_MAX96749_MFP23, + MAXIM_MAX96749_MFP24, + MAXIM_MAX96749_MFP25, +}; + enum max96752_gpio_list { MAXIM_MAX96752_GPIO0 = 0, MAXIM_MAX96752_GPIO1, diff --git a/drivers/mfd/display-serdes/maxim/Kconfig b/drivers/mfd/display-serdes/maxim/Kconfig index e889dcd0bf82..fe34367ae86d 100644 --- a/drivers/mfd/display-serdes/maxim/Kconfig +++ b/drivers/mfd/display-serdes/maxim/Kconfig @@ -17,6 +17,12 @@ config SERDES_DISPLAY_CHIP_MAXIM_MAX96745 help To support maxim max96745 display serdes. +config SERDES_DISPLAY_CHIP_MAXIM_MAX96749 + tristate "maxim max96749 serdes" + default y + help + To support maxim max96749 display serdes. + config SERDES_DISPLAY_CHIP_MAXIM_MAX96752 tristate "maxim max96752 serdes" default y diff --git a/drivers/mfd/display-serdes/maxim/Makefile b/drivers/mfd/display-serdes/maxim/Makefile index 349233deda38..9fade01a4049 100644 --- a/drivers/mfd/display-serdes/maxim/Makefile +++ b/drivers/mfd/display-serdes/maxim/Makefile @@ -3,6 +3,7 @@ # maxim display serdes drivers configuration # obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) += maxim-max96745.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96749) += maxim-max96749.o obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) += maxim-max96752.o obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) += maxim-max96755.o obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) += maxim-max96772.o diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96749.c b/drivers/mfd/display-serdes/maxim/maxim-max96749.c new file mode 100644 index 000000000000..0c9de2ace88d --- /dev/null +++ b/drivers/mfd/display-serdes/maxim/maxim-max96749.c @@ -0,0 +1,1028 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96749.c -- I2C register interface access for max96749 serdes chip + * + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + * Author: ZITONG CAI + */ + +#include "../core.h" +#include "maxim-max96749.h" + +static bool max96749_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x0076: + case 0x0086: + case 0x0100: + case 0x0200 ... 0x02ce: + case 0x7000: + case 0x7070: + case 0x7074: + return false; + default: + return true; + } +} + +static struct regmap_config max96749_regmap_config = { + .name = "max96749", + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x8000, + .volatile_reg = max96749_volatile_reg, + .cache_type = REGCACHE_RBTREE, +}; + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_io_rx_en:1; + u8 gpio_tx_en_a:1; + u8 gpio_tx_en_b:1; + u8 gpio_rx_en_a:1; + u8 gpio_rx_en_b:1; + u8 gpio_tx_id; + u8 gpio_rx_id; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96749_MFP0_pins[] = {0}; +static int MAX96749_MFP1_pins[] = {1}; +static int MAX96749_MFP2_pins[] = {2}; +static int MAX96749_MFP3_pins[] = {3}; +static int MAX96749_MFP4_pins[] = {4}; +static int MAX96749_MFP5_pins[] = {5}; +static int MAX96749_MFP6_pins[] = {6}; +static int MAX96749_MFP7_pins[] = {7}; + +static int MAX96749_MFP8_pins[] = {8}; +static int MAX96749_MFP9_pins[] = {9}; +static int MAX96749_MFP10_pins[] = {10}; +static int MAX96749_MFP11_pins[] = {11}; +static int MAX96749_MFP12_pins[] = {12}; +static int MAX96749_MFP13_pins[] = {13}; +static int MAX96749_MFP14_pins[] = {14}; +static int MAX96749_MFP15_pins[] = {15}; + +static int MAX96749_MFP16_pins[] = {16}; +static int MAX96749_MFP17_pins[] = {17}; +static int MAX96749_MFP18_pins[] = {18}; +static int MAX96749_MFP19_pins[] = {19}; +static int MAX96749_MFP20_pins[] = {20}; +static int MAX96749_MFP21_pins[] = {21}; +static int MAX96749_MFP22_pins[] = {22}; +static int MAX96749_MFP23_pins[] = {23}; + +static int MAX96749_MFP24_pins[] = {24}; +static int MAX96749_MFP25_pins[] = {25}; +static int MAX96749_I2C_pins[] = {3, 7}; +static int MAX96749_UART_pins[] = {3, 7}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +static const char * const serdes_gpio_groups[] = { + "MAX96749_MFP0", "MAX96749_MFP1", "MAX96749_MFP2", "MAX96749_MFP3", + "MAX96749_MFP4", "MAX96749_MFP5", "MAX96749_MFP6", "MAX96749_MFP7", + + "MAX96749_MFP8", "MAX96749_MFP9", "MAX96749_MFP10", "MAX96749_MFP11", + "MAX96749_MFP12", "MAX96749_MFP13", "MAX96749_MFP14", "MAX96749_MFP15", + + "MAX96749_MFP16", "MAX96749_MFP17", "MAX96749_MFP18", "MAX96749_MFP19", + "MAX96749_MFP20", "MAX96749_MFP21", "MAX96749_MFP22", "MAX96749_MFP23", + + "MAX96749_MFP24", "MAX96749_MFP25", +}; + +static const char *MAX96749_I2C_groups[] = { "MAX96749_I2C" }; +static const char *MAX96749_UART_groups[] = { "MAX96749_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_A(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES_LINKA", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en_a = 1, \ + .gpio_io_rx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_B(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES_LINKB", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en_b = 1, \ + .gpio_io_rx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT_A(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER_LINKA", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en_a = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT_B(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER_LINKB", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en_b = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO() \ +{ \ + .name = "MAX96749_GPIO", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96749_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96749_MFP0, "MAX96749_MFP0"), + PINCTRL_PIN(MAXIM_MAX96749_MFP1, "MAX96749_MFP1"), + PINCTRL_PIN(MAXIM_MAX96749_MFP2, "MAX96749_MFP2"), + PINCTRL_PIN(MAXIM_MAX96749_MFP3, "MAX96749_MFP3"), + PINCTRL_PIN(MAXIM_MAX96749_MFP4, "MAX96749_MFP4"), + PINCTRL_PIN(MAXIM_MAX96749_MFP5, "MAX96749_MFP5"), + PINCTRL_PIN(MAXIM_MAX96749_MFP6, "MAX96749_MFP6"), + PINCTRL_PIN(MAXIM_MAX96749_MFP7, "MAX96749_MFP7"), + + PINCTRL_PIN(MAXIM_MAX96749_MFP8, "MAX96749_MFP8"), + PINCTRL_PIN(MAXIM_MAX96749_MFP9, "MAX96749_MFP9"), + PINCTRL_PIN(MAXIM_MAX96749_MFP10, "MAX96749_MFP10"), + PINCTRL_PIN(MAXIM_MAX96749_MFP11, "MAX96749_MFP11"), + PINCTRL_PIN(MAXIM_MAX96749_MFP12, "MAX96749_MFP12"), + PINCTRL_PIN(MAXIM_MAX96749_MFP13, "MAX96749_MFP13"), + PINCTRL_PIN(MAXIM_MAX96749_MFP14, "MAX96749_MFP14"), + PINCTRL_PIN(MAXIM_MAX96749_MFP15, "MAX96749_MFP15"), + + PINCTRL_PIN(MAXIM_MAX96749_MFP16, "MAX96749_MFP16"), + PINCTRL_PIN(MAXIM_MAX96749_MFP17, "MAX96749_MFP17"), + PINCTRL_PIN(MAXIM_MAX96749_MFP18, "MAX96749_MFP18"), + PINCTRL_PIN(MAXIM_MAX96749_MFP19, "MAX96749_MFP19"), + PINCTRL_PIN(MAXIM_MAX96749_MFP20, "MAX96749_MFP20"), + PINCTRL_PIN(MAXIM_MAX96749_MFP21, "MAX96749_MFP21"), + PINCTRL_PIN(MAXIM_MAX96749_MFP22, "MAX96749_MFP22"), + PINCTRL_PIN(MAXIM_MAX96749_MFP23, "MAX96749_MFP23"), + + PINCTRL_PIN(MAXIM_MAX96749_MFP24, "MAX96749_MFP24"), + PINCTRL_PIN(MAXIM_MAX96749_MFP25, "MAX96749_MFP25"), +}; + +static struct group_desc max96749_groups_desc[] = { + GROUP_DESC(MAX96749_MFP0), + GROUP_DESC(MAX96749_MFP1), + GROUP_DESC(MAX96749_MFP2), + GROUP_DESC(MAX96749_MFP3), + GROUP_DESC(MAX96749_MFP4), + GROUP_DESC(MAX96749_MFP5), + GROUP_DESC(MAX96749_MFP6), + GROUP_DESC(MAX96749_MFP7), + + GROUP_DESC(MAX96749_MFP8), + GROUP_DESC(MAX96749_MFP9), + GROUP_DESC(MAX96749_MFP10), + GROUP_DESC(MAX96749_MFP11), + GROUP_DESC(MAX96749_MFP12), + GROUP_DESC(MAX96749_MFP13), + GROUP_DESC(MAX96749_MFP14), + GROUP_DESC(MAX96749_MFP15), + + GROUP_DESC(MAX96749_MFP16), + GROUP_DESC(MAX96749_MFP17), + GROUP_DESC(MAX96749_MFP18), + GROUP_DESC(MAX96749_MFP19), + GROUP_DESC(MAX96749_MFP20), + GROUP_DESC(MAX96749_MFP21), + GROUP_DESC(MAX96749_MFP22), + GROUP_DESC(MAX96749_MFP23), + + GROUP_DESC(MAX96749_MFP24), + GROUP_DESC(MAX96749_MFP25), + + GROUP_DESC(MAX96749_I2C), + GROUP_DESC(MAX96749_UART), +}; + +static struct function_desc max96749_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT_A(0), + FUNCTION_DESC_GPIO_INPUT_A(1), + FUNCTION_DESC_GPIO_INPUT_A(2), + FUNCTION_DESC_GPIO_INPUT_A(3), + FUNCTION_DESC_GPIO_INPUT_A(4), + FUNCTION_DESC_GPIO_INPUT_A(5), + FUNCTION_DESC_GPIO_INPUT_A(6), + FUNCTION_DESC_GPIO_INPUT_A(7), + + FUNCTION_DESC_GPIO_INPUT_A(8), + FUNCTION_DESC_GPIO_INPUT_A(9), + FUNCTION_DESC_GPIO_INPUT_A(10), + FUNCTION_DESC_GPIO_INPUT_A(11), + FUNCTION_DESC_GPIO_INPUT_A(12), + FUNCTION_DESC_GPIO_INPUT_A(13), + FUNCTION_DESC_GPIO_INPUT_A(14), + FUNCTION_DESC_GPIO_INPUT_A(15), + + FUNCTION_DESC_GPIO_INPUT_A(16), + FUNCTION_DESC_GPIO_INPUT_A(17), + FUNCTION_DESC_GPIO_INPUT_A(18), + FUNCTION_DESC_GPIO_INPUT_A(19), + FUNCTION_DESC_GPIO_INPUT_A(20), + FUNCTION_DESC_GPIO_INPUT_A(21), + FUNCTION_DESC_GPIO_INPUT_A(22), + FUNCTION_DESC_GPIO_INPUT_A(23), + + FUNCTION_DESC_GPIO_INPUT_A(24), + FUNCTION_DESC_GPIO_INPUT_A(25), + + FUNCTION_DESC_GPIO_OUTPUT_A(0), + FUNCTION_DESC_GPIO_OUTPUT_A(1), + FUNCTION_DESC_GPIO_OUTPUT_A(2), + FUNCTION_DESC_GPIO_OUTPUT_A(3), + FUNCTION_DESC_GPIO_OUTPUT_A(4), + FUNCTION_DESC_GPIO_OUTPUT_A(5), + FUNCTION_DESC_GPIO_OUTPUT_A(6), + FUNCTION_DESC_GPIO_OUTPUT_A(7), + + FUNCTION_DESC_GPIO_OUTPUT_A(8), + FUNCTION_DESC_GPIO_OUTPUT_A(9), + FUNCTION_DESC_GPIO_OUTPUT_A(10), + FUNCTION_DESC_GPIO_OUTPUT_A(11), + FUNCTION_DESC_GPIO_OUTPUT_A(12), + FUNCTION_DESC_GPIO_OUTPUT_A(13), + FUNCTION_DESC_GPIO_OUTPUT_A(14), + FUNCTION_DESC_GPIO_OUTPUT_A(15), + + FUNCTION_DESC_GPIO_OUTPUT_A(16), + FUNCTION_DESC_GPIO_OUTPUT_A(17), + FUNCTION_DESC_GPIO_OUTPUT_A(18), + FUNCTION_DESC_GPIO_OUTPUT_A(19), + FUNCTION_DESC_GPIO_OUTPUT_A(20), + FUNCTION_DESC_GPIO_OUTPUT_A(21), + FUNCTION_DESC_GPIO_OUTPUT_A(22), + FUNCTION_DESC_GPIO_OUTPUT_A(23), + + FUNCTION_DESC_GPIO_OUTPUT_A(24), + FUNCTION_DESC_GPIO_OUTPUT_A(25), + + FUNCTION_DESC_GPIO_INPUT_B(0), + FUNCTION_DESC_GPIO_INPUT_B(1), + FUNCTION_DESC_GPIO_INPUT_B(2), + FUNCTION_DESC_GPIO_INPUT_B(3), + FUNCTION_DESC_GPIO_INPUT_B(4), + FUNCTION_DESC_GPIO_INPUT_B(5), + FUNCTION_DESC_GPIO_INPUT_B(6), + FUNCTION_DESC_GPIO_INPUT_B(7), + + FUNCTION_DESC_GPIO_INPUT_B(8), + FUNCTION_DESC_GPIO_INPUT_B(9), + FUNCTION_DESC_GPIO_INPUT_B(10), + FUNCTION_DESC_GPIO_INPUT_B(11), + FUNCTION_DESC_GPIO_INPUT_B(12), + FUNCTION_DESC_GPIO_INPUT_B(13), + FUNCTION_DESC_GPIO_INPUT_B(14), + FUNCTION_DESC_GPIO_INPUT_B(15), + + FUNCTION_DESC_GPIO_INPUT_B(16), + FUNCTION_DESC_GPIO_INPUT_B(17), + FUNCTION_DESC_GPIO_INPUT_B(18), + FUNCTION_DESC_GPIO_INPUT_B(19), + FUNCTION_DESC_GPIO_INPUT_B(20), + FUNCTION_DESC_GPIO_INPUT_B(21), + FUNCTION_DESC_GPIO_INPUT_B(22), + FUNCTION_DESC_GPIO_INPUT_B(23), + + FUNCTION_DESC_GPIO_INPUT_B(24), + FUNCTION_DESC_GPIO_INPUT_B(25), + + FUNCTION_DESC_GPIO_OUTPUT_B(0), + FUNCTION_DESC_GPIO_OUTPUT_B(1), + FUNCTION_DESC_GPIO_OUTPUT_B(2), + FUNCTION_DESC_GPIO_OUTPUT_B(3), + FUNCTION_DESC_GPIO_OUTPUT_B(4), + FUNCTION_DESC_GPIO_OUTPUT_B(5), + FUNCTION_DESC_GPIO_OUTPUT_B(6), + FUNCTION_DESC_GPIO_OUTPUT_B(7), + + FUNCTION_DESC_GPIO_OUTPUT_B(8), + FUNCTION_DESC_GPIO_OUTPUT_B(9), + FUNCTION_DESC_GPIO_OUTPUT_B(10), + FUNCTION_DESC_GPIO_OUTPUT_B(11), + FUNCTION_DESC_GPIO_OUTPUT_B(12), + FUNCTION_DESC_GPIO_OUTPUT_B(13), + FUNCTION_DESC_GPIO_OUTPUT_B(14), + FUNCTION_DESC_GPIO_OUTPUT_B(15), + + FUNCTION_DESC_GPIO_OUTPUT_B(16), + FUNCTION_DESC_GPIO_OUTPUT_B(17), + FUNCTION_DESC_GPIO_OUTPUT_B(18), + FUNCTION_DESC_GPIO_OUTPUT_B(19), + FUNCTION_DESC_GPIO_OUTPUT_B(20), + FUNCTION_DESC_GPIO_OUTPUT_B(21), + FUNCTION_DESC_GPIO_OUTPUT_B(22), + FUNCTION_DESC_GPIO_OUTPUT_B(23), + + FUNCTION_DESC_GPIO_OUTPUT_B(24), + FUNCTION_DESC_GPIO_OUTPUT_B(25), + + FUNCTION_DESC_GPIO(), + + FUNCTION_DESC(MAX96749_I2C), + FUNCTION_DESC(MAX96749_UART), +}; + +static struct serdes_chip_pinctrl_info max96749_pinctrl_info = { + .pins = max96749_pins_desc, + .num_pins = ARRAY_SIZE(max96749_pins_desc), + .groups = max96749_groups_desc, + .num_groups = ARRAY_SIZE(max96749_groups_desc), + .functions = max96749_functions_desc, + .num_functions = ARRAY_SIZE(max96749_functions_desc), +}; + +static bool max96749_vid_tx_active(struct serdes *serdes) +{ + u32 val; + int i = 0, ret = 0; + + for (i = 0; i < 5; i++) { + ret = serdes_reg_read(serdes, 0x0107, &val); + if (!ret) + break; + + SERDES_DBG_CHIP("serdes %s: false val=%d i=%d ret=%d\n", __func__, val, i, ret); + msleep(20); + } + + if (ret) { + SERDES_DBG_CHIP("serdes %s: false val=%d ret=%d\n", __func__, val, ret); + return false; + } + + if (!FIELD_GET(VID_TX_ACTIVE_A | VID_TX_ACTIVE_B, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + return true; +} + +static int max96749_bridge_init(struct serdes *serdes) +{ + if (max96749_vid_tx_active(serdes)) { + extcon_set_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT, true); + pr_info("serdes %s, extcon is true state=%d\n", __func__, serdes->extcon->state); + } else { + pr_info("serdes %s, extcon is false\n", __func__); + } + + return 0; +} + +static bool max96749_bridge_link_locked(struct serdes *serdes) +{ + u32 val = 0, i; + + if (serdes->lock_gpio) { + for (i = 0; i < 3; i++) { + val = gpiod_get_value_cansleep(serdes->lock_gpio); + if (val) + break; + msleep(20); + } + + SERDES_DBG_CHIP("%s:%s-%s, gpio %s\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, (val) ? "locked" : "unlocked"); + if (val) + return true; + } + + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("serdes %s: unlocked val=0x%x\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("serdes %s: unlocked val=0x%x\n", __func__, val); + return false; + } + + SERDES_DBG_CHIP("%s: serdes reg locked 0x%x\n", __func__, val); + + return true; +} + +static int max96749_select(struct serdes *serdes, int link) +{ + int ret; + u32 i, status; + struct serdes *deser; + struct drm_panel *panel; + struct serdes_panel *serdes_panel; + + /*0076 for linkA and 0086 for linkB*/ + if (link == SER_DUAL_LINK) { + panel = serdes->serdes_bridge->panel; + serdes_panel = container_of(panel, struct serdes_panel, panel); + deser = serdes_panel->parent; + + serdes_reg_write(deser, 0x10, 0x00); + serdes_set_bits(serdes, 0x45, DUAL_LINK_MODE, + FIELD_PREP(DUAL_LINK_MODE, 1)); + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: serdes %s change to use dual link\n", + __func__, serdes->chip_data->name); + } else if (link == SER_LINKA) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + SERDES_DBG_CHIP("%s: only enable %s remote i2c of linkA\n", __func__, + serdes->chip_data->name); + } else if (link == SER_LINKB) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: only enable %s remote i2c of linkB\n", __func__, + serdes->chip_data->name); + } else if (link == SER_SPLITTER_MODE) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: enable %s remote i2c of linkA and linkB\n", __func__, + serdes->chip_data->name); + } + + for (i = 0; i < 80; i++) { + mdelay(5); + ret = serdes_reg_read(serdes, 0x0021, &status); + if (ret) + continue; + + if (serdes->dual_link && link != SER_DUAL_LINK) + return 0; + + switch (link) { + case SER_DUAL_LINK: + case SER_SPLITTER_MODE: + if ((status & LINKA_LOCKED) && + (status & LINKB_LOCKED)) + goto out; + break; + case SER_LINKA: + if (status & LINKA_LOCKED) + goto out; + break; + case SER_LINKB: + if (status & LINKB_LOCKED) + goto out; + break; + } + } + + dev_info(serdes->dev, "%s: link lock timeout, mode=%d val=0x%x\n", + __func__, link, status); + return -1; + +out: + dev_info(serdes->dev, "%s: link locked, mode=%d, val=0x%x\n", + __func__, link, status); + + return 0; +} + +static int max96749_deselect(struct serdes *serdes, int link) +{ + struct serdes *deser; + struct drm_panel *panel; + struct serdes_panel *serdes_panel; + struct serdes_bridge *serdes_bridge = serdes->serdes_bridge; + + if (link == SER_DUAL_LINK) { + panel = serdes_bridge->panel; + serdes_panel = container_of(panel, struct serdes_panel, panel); + deser = serdes_panel->parent; + + serdes_reg_write(deser, 0x10, 0x00); + serdes_set_bits(serdes, 0x45, DUAL_LINK_MODE, + FIELD_PREP(DUAL_LINK_MODE, 0)); + + SERDES_DBG_CHIP("%s: serdes %s disable dual link\n", __func__, + serdes->chip_data->name); + + } + + return 0; +} + +static struct serdes_chip_split_ops max96749_split_ops = { + .select = max96749_select, + .deselect = max96749_deselect, +}; + +static int max96749_bridge_attach(struct serdes *serdes) +{ + int ret; + enum drm_connector_status status; + + if (max96749_bridge_link_locked(serdes)) + status = connector_status_connected; + else { + status = connector_status_disconnected; + if (serdes->dual_link) { + dev_info(serdes->dev, "serdes disconnect, try to change dual link\n"); + + ret = max96749_select(serdes, SER_DUAL_LINK); + if (ret) { + dev_info(serdes->dev, "serdes disconnect, close dual link\n"); + max96749_deselect(serdes, SER_DUAL_LINK); + } else { + status = connector_status_connected; + } + } + } + + serdes->serdes_bridge->status = status; + + return 0; +} + +static enum drm_connector_status +max96749_bridge_detect(struct serdes *serdes) +{ + struct serdes_bridge *serdes_bridge = serdes->serdes_bridge; + enum drm_connector_status status = connector_status_connected; + + if (!drm_kms_helper_is_poll_worker()) + return serdes_bridge->status; + + if (!max96749_bridge_link_locked(serdes)) { + status = connector_status_disconnected; + goto out; + } + + if (extcon_get_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT)) { + u32 dprx_trn_status2; + + if (atomic_cmpxchg(&serdes_bridge->triggered, 1, 0)) { + status = connector_status_disconnected; + SERDES_DBG_CHIP("1 status=%d state=%d\n", status, serdes->extcon->state); + goto out; + } + + if (serdes_reg_read(serdes, 0x641a, &dprx_trn_status2)) { + status = connector_status_disconnected; + SERDES_DBG_CHIP("2 status=%d state=%d\n", status, serdes->extcon->state); + goto out; + } + + if ((dprx_trn_status2 & DPRX_TRAIN_STATE) != DPRX_TRAIN_STATE) { + dev_err(serdes->dev, "Training State: 0x%lx\n", + FIELD_GET(DPRX_TRAIN_STATE, dprx_trn_status2)); + status = connector_status_disconnected; + SERDES_DBG_CHIP("3 status=%d state=%d\n", status, serdes->extcon->state); + goto out; + } + } else { + atomic_set(&serdes_bridge->triggered, 0); + SERDES_DBG_CHIP("4 status=%d state=%d\n", status, serdes->extcon->state); + } + + if (serdes_bridge->next_bridge && (serdes_bridge->next_bridge->ops & DRM_BRIDGE_OP_DETECT)) + return drm_bridge_detect(serdes_bridge->next_bridge); + +out: + serdes_bridge->status = status; + SERDES_DBG_CHIP("%s:%s %s, status=%d state=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, + status, serdes->extcon->state); + return status; +} + +static int max96749_bridge_pre_enable(struct serdes *serdes) +{ + int ret = 0; + struct serdes_bridge *serdes_bridge = serdes->serdes_bridge; + + if (serdes->dual_link) { + ret = max96749_select(serdes, SER_DUAL_LINK); + if (ret) + atomic_set(&serdes_bridge->triggered, 1); + } + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret); + return ret; +} + +static int max96749_bridge_enable(struct serdes *serdes) +{ + int ret = 0; + + return ret; +} + +static int max96749_bridge_disable(struct serdes *serdes) +{ + int ret = 0; + + if (serdes->dual_link) + max96749_deselect(serdes, SER_DUAL_LINK); + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret); + return ret; +} + +static int max96749_bridge_post_disable(struct serdes *serdes) +{ + int ret = 0; + + return ret; +} + +static struct serdes_chip_bridge_ops max96749_bridge_ops = { + .init = max96749_bridge_init, + .attach = max96749_bridge_attach, + .detect = max96749_bridge_detect, + .pre_enable = max96749_bridge_pre_enable, + .enable = max96749_bridge_enable, + .disable = max96749_bridge_disable, + .post_disable = max96749_bridge_post_disable, +}; + +static int max96749_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) +{ + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, + func->name, func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *data = func->data; + + for (i = 0; i < grp->num_pins; i++) { + serdes_set_bits(serdes, + GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS, + FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis)); + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + OUT_TYPE, + FIELD_PREP(OUT_TYPE, 1)); + if (data->gpio_tx_en_a || data->gpio_tx_en_b) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id)); + if (data->gpio_rx_en_a || data->gpio_rx_en_b) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id)); + serdes_set_bits(serdes, + GPIO_D_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN | + GPIO_RX_EN_A | GPIO_RX_EN_B, + FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) | + FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) | + FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) | + FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) | + FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en)); + } + } + + return 0; +} + +static int max96749_pinctrl_config_get(struct serdes *serdes, + unsigned int pin, unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int gpio_a_reg, gpio_b_reg; + u16 arg = 0; + + serdes_reg_read(serdes, GPIO_A_REG(pin), &gpio_a_reg); + serdes_reg_read(serdes, GPIO_B_REG(pin), &gpio_b_reg); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", + __func__, serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_OUTPUT: + if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) + return -EINVAL; + + arg = FIELD_GET(GPIO_OUT, gpio_a_reg); + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int max96749_pinctrl_config_set(struct serdes *serdes, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + enum pin_config_param param; + u32 arg; + u8 res_cfg; + int i; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, arg)); + break; + default: + return -EOPNOTSUPP; + } + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96749_pinctrl_ops = { + .pin_config_get = max96749_pinctrl_config_get, + .pin_config_set = max96749_pinctrl_config_set, + .set_mux = max96749_pinctrl_set_mux, +}; + +static int max96749_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96749_gpio_direction_output(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96749_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96749_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96749_gpio_set_config(struct serdes *serdes, int gpio, unsigned long config) +{ + return 0; +} + +static int max96749_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96749_gpio_ops = { + .direction_input = max96749_gpio_direction_input, + .direction_output = max96749_gpio_direction_output, + .get_level = max96749_gpio_get_level, + .set_level = max96749_gpio_set_level, + .set_config = max96749_gpio_set_config, + .to_irq = max96749_gpio_to_irq, +}; + +static const struct check_reg_data max96749_improtant_reg[10] = { + { + "MAX96749 LINK LOCK", + { 0x0013, (1 << 3) }, + }, { + "MAX96749 LINKA LOCK", + { 0x002A, (1 << 0) }, + }, { + "MAX96749 LINKB LOCK", + { 0x0034, (1 << 0) }, + }, { + "MAX96749 X PCLK DET", + { 0x0102, (1 << 7) }, + }, { + "MAX96749 Y PCLK DET", + { 0x0112, (1 << 7) }, + }, +}; + +static int max96749_check_reg(struct serdes *serdes) +{ + int i = 0, ret = 0; + unsigned int val = 0; + + for (i = 0; i < ARRAY_SIZE(max96749_improtant_reg); i++) { + if (!max96749_improtant_reg[i].seq.reg) + break; + + ret = serdes_reg_read(serdes, max96749_improtant_reg[i].seq.reg, &val); + if (!ret && !(val & max96749_improtant_reg[i].seq.def) + && (!atomic_read(&serdes->flag_early_suspend))) + dev_info(serdes->dev, "warning %s %s reg[0x%x] = 0x%x\n", __func__, + max96749_improtant_reg[i].name, + max96749_improtant_reg[i].seq.reg, val); + } + + return 0; +} + +static struct serdes_check_reg_ops max96749_check_reg_ops = { + .check_reg = max96749_check_reg, +}; + +static int max96749_pm_suspend(struct serdes *serdes) +{ + return 0; +} + +static int max96749_pm_resume(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_pm_ops max96749_pm_ops = { + .suspend = max96749_pm_suspend, + .resume = max96749_pm_resume, +}; + +static int max96749_irq_lock_handle(struct serdes *serdes) +{ + return IRQ_HANDLED; +} + +static int max96749_irq_err_handle(struct serdes *serdes) +{ + return IRQ_HANDLED; +} + +static struct serdes_chip_irq_ops max96749_irq_ops = { + .lock_handle = max96749_irq_lock_handle, + .err_handle = max96749_irq_err_handle, +}; + +struct serdes_chip_data serdes_max96749_data = { + .name = "max96749", + .serdes_type = TYPE_SER, + .serdes_id = MAXIM_ID_MAX96749, + .connector_type = DRM_MODE_CONNECTOR_eDP, + .regmap_config = &max96749_regmap_config, + .pinctrl_info = &max96749_pinctrl_info, + .bridge_ops = &max96749_bridge_ops, + .pinctrl_ops = &max96749_pinctrl_ops, + .gpio_ops = &max96749_gpio_ops, + .split_ops = &max96749_split_ops, + .check_ops = &max96749_check_reg_ops, + .pm_ops = &max96749_pm_ops, + .irq_ops = &max96749_irq_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96749_data); + +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96749.h b/drivers/mfd/display-serdes/maxim/maxim-max96749.h new file mode 100644 index 000000000000..6351a61cb657 --- /dev/null +++ b/drivers/mfd/display-serdes/maxim/maxim-max96749.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * maxim-max96749.h -- register define for max96749 chip + * + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + * Author: ZITONG CAI + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96745_H__ +#define __MFD_SERDES_MAXIM_MAX96745_H__ + +#include + +#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 8)) +#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 8)) +#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 8)) +#define GPIO_D_REG(gpio) (0x0203 + ((gpio) * 8)) + +/* 0005h */ +#define PU_LF3 BIT(3) +#define PU_LF2 BIT(2) +#define PU_LF1 BIT(1) +#define PU_LF0 BIT(0) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define SLEEP BIT(3) + +/* 0011h */ +#define CXTP_B BIT(2) +#define CXTP_A BIT(0) + +/* 0013h */ +#define LOCKED BIT(3) +#define ERROR BIT(2) + +/* 0021h */ +#define LINKA_LOCKED BIT(2) +#define LINKB_LOCKED BIT(3) + +/* 0026h */ +#define LF_0 GENMASK(2, 0) +#define LF_1 GENMASK(6, 4) + +/* 0027h */ +#define LF_2 GENMASK(2, 0) +#define LF_3 GENMASK(6, 4) + +/* 0028h, 0032h */ +#define LINK_EN BIT(7) +#define TX_RATE GENMASK(3, 2) + +/* 0029h, 0033h */ +#define RESET_LINK BIT(0) +#define RESET_ONESHOT BIT(1) + +/* 0045h */ +#define DUAL_LINK_MODE BIT(1) + +/* 002Ah, 0034h */ +#define LINK_LOCKED BIT(0) + +/* 0076h, 0086h */ +#define DIS_REM_CC BIT(7) + +/* 0100h */ +#define VID_LINK_SEL GENMASK(2, 1) +#define VID_TX_EN BIT(0) + +/* 0101h */ +#define BPP GENMASK(5, 0) + +/* 0102h */ +#define PCLKDET_A BIT(7) +#define DRIFT_ERR_A BIT(6) +#define OVERFLOW_A BIT(5) +#define FIFO_WARN_A BIT(4) +#define LIM_HEART BIT(2) + +/* 0107h */ +#define VID_TX_ACTIVE_B BIT(7) +#define VID_TX_ACTIVE_A BIT(6) + +/* 0108h */ +#define PCLKDET_B BIT(7) +#define DRIFT_ERR_B BIT(6) +#define OVERFLOW_B BIT(5) +#define FIFO_WARN_B BIT(4) + +/* 0200h */ +#define RES_CFG BIT(7) +#define TX_COM_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_OUT_DIS BIT(0) + +/* 0201h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 0202h */ +#define OVR_RES_CFG BIT(7) +#define IO_EDGE_RATE GENMASK(6, 5) +#define GPIO_RX_ID GENMASK(4, 0) + +/* 0203h */ +#define GPIO_IO_RX_EN BIT(5) +#define GPIO_OUT_LGC BIT(4) +#define GPIO_RX_EN_B BIT(3) +#define GPIO_TX_EN_B BIT(2) +#define GPIO_RX_EN_A BIT(1) +#define GPIO_TX_EN_A BIT(0) + +/* 0750h */ +#define FRCZEROPAD GENMASK(7, 6) +#define FRCZPEN BIT(5) +#define FRCSDGAIN BIT(4) +#define FRCSDEN BIT(3) +#define FRCGAIN GENMASK(2, 1) +#define FRCEN BIT(0) + +/* 0751h */ +#define FRCDATAWIDTH BIT(3) +#define FRCASYNCEN BIT(2) +#define FRCHSPOL BIT(1) +#define FRCVSPOL BIT(0) + +/* 0752h */ +#define FRCDCMODE GENMASK(1, 0) + +/* 641Ah */ +#define DPRX_TRAIN_STATE GENMASK(7, 4) + +/* 7000h */ +#define LINK_ENABLE BIT(0) + +/* 7070h */ +#define MAX_LANE_COUNT GENMASK(7, 0) + +/* 7074h */ +#define MAX_LINK_RATE GENMASK(7, 0) + +#endif diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96772.c b/drivers/mfd/display-serdes/maxim/maxim-max96772.c index 8394ec2c22b5..b6db704fea9e 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96772.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96772.c @@ -14,11 +14,13 @@ static const struct regmap_range max96772_readable_ranges[] = { regmap_reg_range(0x0000, 0x0800), regmap_reg_range(0x1700, 0x1700), regmap_reg_range(0x4100, 0x4100), - regmap_reg_range(0x6230, 0x6230), + regmap_reg_range(0x6000, 0x6230), regmap_reg_range(0x7014, 0x7016), regmap_reg_range(0xe75e, 0xe75e), regmap_reg_range(0xe7c4, 0xe7c6), regmap_reg_range(0xe776, 0xe7bf), + regmap_reg_range(0xe7d1, 0xe7d1), + regmap_reg_range(0xe7de, 0xe7de), }; static const struct regmap_access_table max96772_readable_table = { @@ -70,6 +72,23 @@ static int MAX96772_GPIO15_pins[] = {15}; .num_pins = ARRAY_SIZE(nm ## _pins), \ } +#define GROUP_DESC_CONFIG(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ + .data = (void *)(const struct serdes_group_data []) { \ + { \ + .configs = nm ## _configs, \ + .num_configs = ARRAY_SIZE(nm ## _configs), \ + } \ + }, \ +} + +static const struct config_desc MAX96772_GPIO7_configs[] = { + { 0x02, AUD_TX_EN, 0}, +}; + struct serdes_function_data { u8 gpio_out_dis:1; u8 gpio_tx_en:1; @@ -169,7 +188,7 @@ static struct group_desc max96772_groups_desc[] = { GROUP_DESC(MAX96772_GPIO4), GROUP_DESC(MAX96772_GPIO5), GROUP_DESC(MAX96772_GPIO6), - GROUP_DESC(MAX96772_GPIO7), + GROUP_DESC_CONFIG(MAX96772_GPIO7), GROUP_DESC(MAX96772_GPIO8), GROUP_DESC(MAX96772_GPIO9), @@ -337,6 +356,70 @@ static const struct reg_sequence max96772_clk_ref[4][14] = { } }; +static const struct reg_sequence max96772_clk_ssc[4][14] = { + { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0x35 }, + { 0xe7b5, 0x42 }, + { 0xe7b6, 0x81 }, + { 0xe7b7, 0x30 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x10 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0xd7 }, + { 0xe7b5, 0x45 }, + { 0xe7b6, 0x6b }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x30 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0xd7 }, + { 0xe7b5, 0x45 }, + { 0xe7b6, 0x6b }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x14 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x2e }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x02 }, + { 0xe7bd, 0x01 }, + { 0xe7be, 0x32 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x30 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0xd7 }, + { 0xe7b5, 0x45 }, + { 0xe7b6, 0x6b }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x14 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x2e }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x32 }, + { 0xe7bf, 0x00 }, + } +}; + static int max96772_aux_dpcd_read(struct serdes *serdes, unsigned int reg, unsigned int *value) { serdes_reg_write(serdes, 0xe778, reg & 0xff); @@ -358,6 +441,35 @@ static int max96772_panel_prepare(struct serdes *serdes) u32 vact, vsa, vfp, vbp; u64 hwords, mvid; bool hsync_pol, vsync_pol; + int ret; + u32 dpcd; + int link_rate; + + if (!serdes->serdes_panel->link_rate || !serdes->serdes_panel->lane_count) { + ret = max96772_aux_dpcd_read(serdes, DP_MAX_LANE_COUNT, &dpcd); + if (ret) { + dev_err(serdes->dev, "failed to read max lane count\n"); + return ret; + } + + serdes->serdes_panel->lane_count = min_t(int, 4, dpcd & DP_MAX_LANE_COUNT_MASK); + + ret = max96772_aux_dpcd_read(serdes, DP_MAX_LINK_RATE, &dpcd); + if (ret) { + dev_err(serdes->dev, "failed to read max link rate\n"); + return ret; + } + + serdes->serdes_panel->link_rate = min_t(int, dpcd, DP_LINK_BW_5_4); + + ret = max96772_aux_dpcd_read(serdes, DP_MAX_DOWNSPREAD, &dpcd); + if (ret) { + dev_err(serdes->dev, "failed to read max downspread\n"); + return ret; + } + + serdes->serdes_panel->ssc = !!(dpcd & DP_MAX_DOWNSPREAD_0_5); + } serdes_reg_write(serdes, 0xe790, serdes->serdes_panel->link_rate); serdes_reg_write(serdes, 0xe792, serdes->serdes_panel->lane_count); @@ -373,20 +485,46 @@ static int max96772_panel_prepare(struct serdes *serdes) serdes->serdes_panel->link_rate, serdes->serdes_panel->lane_count, serdes->serdes_panel->ssc); - switch (serdes->serdes_panel->link_rate) { - case DP_LINK_BW_5_4: - serdes_multi_reg_write(serdes, max96772_clk_ref[2], - ARRAY_SIZE(max96772_clk_ref[2])); + if (serdes->serdes_panel->ssc) { + switch (serdes->serdes_panel->link_rate) { + case DP_LINK_BW_8_1: + serdes_multi_reg_write(serdes, max96772_clk_ssc[3], + ARRAY_SIZE(max96772_clk_ssc[3])); break; - case DP_LINK_BW_2_7: - serdes_multi_reg_write(serdes, max96772_clk_ref[1], - ARRAY_SIZE(max96772_clk_ref[1])); + case DP_LINK_BW_5_4: + serdes_multi_reg_write(serdes, max96772_clk_ssc[2], + ARRAY_SIZE(max96772_clk_ssc[2])); break; - case DP_LINK_BW_1_62: - default: - serdes_multi_reg_write(serdes, max96772_clk_ref[0], - ARRAY_SIZE(max96772_clk_ref[0])); + case DP_LINK_BW_2_7: + serdes_multi_reg_write(serdes, max96772_clk_ssc[1], + ARRAY_SIZE(max96772_clk_ssc[1])); break; + case DP_LINK_BW_1_62: + default: + serdes_multi_reg_write(serdes, max96772_clk_ssc[0], + ARRAY_SIZE(max96772_clk_ssc[0])); + break; + } + } else { + switch (serdes->serdes_panel->link_rate) { + case DP_LINK_BW_8_1: + serdes_multi_reg_write(serdes, max96772_clk_ref[3], + ARRAY_SIZE(max96772_clk_ref[3])); + break; + case DP_LINK_BW_5_4: + serdes_multi_reg_write(serdes, max96772_clk_ref[2], + ARRAY_SIZE(max96772_clk_ref[2])); + break; + case DP_LINK_BW_2_7: + serdes_multi_reg_write(serdes, max96772_clk_ref[1], + ARRAY_SIZE(max96772_clk_ref[1])); + break; + case DP_LINK_BW_1_62: + default: + serdes_multi_reg_write(serdes, max96772_clk_ref[0], + ARRAY_SIZE(max96772_clk_ref[0])); + break; + } } vact = mode->vdisplay; @@ -428,9 +566,11 @@ static int max96772_panel_prepare(struct serdes *serdes) serdes_reg_write(serdes, 0xe7a4, hwords); serdes_reg_write(serdes, 0xe7a5, hwords >> 8); - /* MVID = (PCLK x NVID) x 10 / Link Rate */ + /* MVID = (PCLK_in_MHz x NVID)/(Link_Rate_in_GBs * 100) */ + link_rate = drm_dp_bw_code_to_link_rate(serdes->serdes_panel->link_rate); mvid = DIV_ROUND_CLOSEST_ULL((u64)mode->clock * 32768, - drm_dp_bw_code_to_link_rate(serdes->serdes_panel->link_rate)); + link_rate); + serdes_reg_write(serdes, 0xe7a6, mvid & 0xff); serdes_reg_write(serdes, 0xe7a7, (mvid >> 8) & 0xff); @@ -568,7 +708,6 @@ static int max96772_pinctrl_set_mux(struct serdes *serdes, for (i = 0; i < gdata->num_configs; i++) { const struct config_desc *config = &gdata->configs[i]; - serdes_set_bits(serdes, config->reg, config->mask, config->val); } @@ -730,21 +869,101 @@ static struct serdes_chip_pinctrl_ops max96772_pinctrl_ops = { static int max96772_gpio_direction_input(struct serdes *serdes, int gpio) { + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct group_desc *grp; + int i; + + grp = pinctrl_generic_get_group(pinctrl->pctl, gpio); + if (!grp) + return -EINVAL; + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + serdes_set_bits(serdes, GPIO_A_REG(gpio), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_RX_EN, 1) | + FIELD_PREP(GPIO_TX_EN, 0)); + + serdes_set_bits(serdes, GPIO_B_REG(gpio), + OUT_TYPE, + FIELD_PREP(OUT_TYPE, 1)); + + SERDES_DBG_CHIP("%s: serdes chip %s gpio=%d\n", + __func__, serdes->chip_data->name, gpio); + return 0; } static int max96772_gpio_direction_output(struct serdes *serdes, int gpio, int value) { + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct group_desc *grp; + int i; + + grp = pinctrl_generic_get_group(pinctrl->pctl, gpio); + if (!grp) + return -EINVAL; + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + serdes_set_bits(serdes, GPIO_A_REG(gpio), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_RX_EN, 0) | + FIELD_PREP(GPIO_TX_EN, 0) | + FIELD_PREP(GPIO_OUT, value)); + + serdes_set_bits(serdes, + GPIO_B_REG(gpio), + OUT_TYPE, + FIELD_PREP(OUT_TYPE, 1)); + + SERDES_DBG_CHIP("%s: serdes chip %s gpio=%d value=%d\n", + __func__, serdes->chip_data->name, gpio, value); + return 0; } static int max96772_gpio_get_level(struct serdes *serdes, int gpio) { - return 0; + unsigned int value; + + serdes_reg_read(serdes, GPIO_A_REG(gpio), &value); + + value &= GPIO_IN; + SERDES_DBG_CHIP("%s: serdes chip %s gpio=%d\n", + __func__, serdes->chip_data->name, gpio, value); + + return value; } static int max96772_gpio_set_level(struct serdes *serdes, int gpio, int value) { + serdes_set_bits(serdes, GPIO_A_REG(gpio), GPIO_OUT, + FIELD_PREP(GPIO_OUT, value)); + + SERDES_DBG_CHIP("%s: serdes chip %s gpio=%d value=%d\n", + __func__, serdes->chip_data->name, gpio, value); + return 0; } diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96772.h b/drivers/mfd/display-serdes/maxim/maxim-max96772.h index 3ef5b2defe79..a660ea29db17 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96772.h +++ b/drivers/mfd/display-serdes/maxim/maxim-max96772.h @@ -11,28 +11,55 @@ #ifndef __MFD_SERDES_MAXIM_MAX96772_H__ #define __MFD_SERDES_MAXIM_MAX96772_H__ -#define GPIO_A_REG(gpio) (0x02b0 + ((gpio) * 3)) -#define GPIO_B_REG(gpio) (0x02b1 + ((gpio) * 3)) -#define GPIO_C_REG(gpio) (0x02b2 + ((gpio) * 3)) +#define GPIO_A_REG(gpio) (0x02b0 + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02b1 + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02b2 + ((gpio) * 3)) +/* 0002h */ +#define VID_EN_U BIT(7) +#define VID_EN_Z BIT(6) +#define VID_EN_Y BIT(5) +#define VID_EN_X BIT(4) +#define AUD_TX_EN BIT(2) + +/* 0004h */ +#define LINK_EN_B BIT(5) +#define LINK_EN_A BIT(4) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define RESET_LINK BIT(6) +#define RESET_ONESHOT BIT(5) +#define AUTO_LINK BIT(4) +#define SLEEP BIT(3) +#define REG_ENABLE BIT(2) +#define LINK_CFG GENMASK(1, 0) + +/* 0013h */ +#define LINK_MODE BIT(4) +#define LOCKED BIT(3) + +/* 001fh */ +#define LINKA_LOCKED BIT(4) +#define LINKB_LOCKED BIT(5) /* 02b0h */ -#define RES_CFG BIT(7) -#define RSVD BIT(6) -#define TX_COMP_EN BIT(5) -#define GPIO_OUT BIT(4) -#define GPIO_IN BIT(3) -#define GPIO_RX_EN BIT(2) -#define GPIO_TX_EN BIT(1) -#define GPIO_OUT_DIS BIT(0) +#define RES_CFG BIT(7) +#define RSVD BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) /* 02b1h */ -#define PULL_UPDN_SEL GENMASK(7, 6) -#define OUT_TYPE BIT(5) -#define GPIO_TX_ID GENMASK(4, 0) +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) /* 02b2h */ -#define OVR_RES_CFG BIT(7) -#define GPIO_RX_ID GENMASK(4, 0) +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) #endif diff --git a/drivers/mfd/display-serdes/serdes-bridge-split.c b/drivers/mfd/display-serdes/serdes-bridge-split.c index 2a40cc37722a..e44c51736157 100644 --- a/drivers/mfd/display-serdes/serdes-bridge-split.c +++ b/drivers/mfd/display-serdes/serdes-bridge-split.c @@ -327,6 +327,7 @@ static const struct of_device_id serdes_bridge_split_of_match[] = { { .compatible = "rohm,bu18tl82-bridge-split", }, { .compatible = "rohm,bu18rl82-bridge-split", }, { .compatible = "maxim,max96745-bridge-split", }, + { .compatible = "maxim,max96749-bridge-split", }, { .compatible = "maxim,max96755-bridge-split", }, { .compatible = "maxim,max96752-bridge-split", }, { .compatible = "maxim,max96789-bridge-split", }, diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 9a6f9bf8aef4..381c4085938a 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -326,6 +326,7 @@ static const struct of_device_id serdes_bridge_of_match[] = { { .compatible = "rohm,bu18tl82-bridge", }, { .compatible = "rohm,bu18rl82-bridge", }, { .compatible = "maxim,max96745-bridge", }, + { .compatible = "maxim,max96749-bridge", }, { .compatible = "maxim,max96755-bridge", }, { .compatible = "maxim,max96789-bridge", }, { .compatible = "rockchip,rkx111-bridge", }, diff --git a/drivers/mfd/display-serdes/serdes-core.c b/drivers/mfd/display-serdes/serdes-core.c index 6a8f7e1c18a4..cbd0cd02eb72 100644 --- a/drivers/mfd/display-serdes/serdes-core.c +++ b/drivers/mfd/display-serdes/serdes-core.c @@ -9,6 +9,9 @@ #include "core.h" +static unsigned long serdes_log_level; +static struct dentry *serdes_debugfs_root; + static const struct mfd_cell serdes_bu18tl82_devs[] = { { .name = "serdes-pinctrl", @@ -46,6 +49,21 @@ static const struct mfd_cell serdes_max96745_devs[] = { }, }; +static const struct mfd_cell serdes_max96749_devs[] = { + { + .name = "serdes-pinctrl", + .of_compatible = "maxim,max96749-pinctrl", + }, + { + .name = "serdes-bridge", + .of_compatible = "maxim,max96749-bridge", + }, + { + .name = "serdes-bridge-split", + .of_compatible = "maxim,max96749-bridge-split", + }, +}; + static const struct mfd_cell serdes_max96755_devs[] = { { .name = "serdes-pinctrl", @@ -175,6 +193,9 @@ int serdes_bulk_write(struct serdes *serdes, unsigned int reg, u16 *buf = src; int i, ret; + if (serdes->debug == SERDES_CLOSE_I2C_WRITE) + return 0; + WARN_ON(count <= 0); mutex_lock(&serdes->io_lock); @@ -205,6 +226,9 @@ int serdes_multi_reg_write(struct serdes *serdes, const struct reg_sequence *reg { int i, ret; + if (serdes->debug == SERDES_CLOSE_I2C_WRITE) + return 0; + SERDES_DBG_I2C("%s %s %s num=%d\n", __func__, dev_name(serdes->dev), serdes->chip_data->name, num_regs); ret = regmap_multi_reg_write(serdes->regmap, regs, num_regs); @@ -229,6 +253,9 @@ int serdes_reg_write(struct serdes *serdes, unsigned int reg, { int ret; + if (serdes->debug == SERDES_CLOSE_I2C_WRITE) + return 0; + ret = regmap_write(serdes->regmap, reg, val); SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x ret=%d\n", __func__, dev_name(serdes->dev), serdes->chip_data->name, reg, val, ret); @@ -252,6 +279,9 @@ int serdes_set_bits(struct serdes *serdes, unsigned int reg, { int ret; + if (serdes->debug == SERDES_CLOSE_I2C_WRITE) + return 0; + SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x) mask=%04x\n", __func__, dev_name(serdes->dev), serdes->chip_data->name, reg, val, mask); ret = regmap_update_bits(serdes->regmap, reg, mask, val); @@ -349,6 +379,10 @@ int serdes_device_init(struct serdes *serdes) serdes_devs = serdes_max96745_devs; mfd_num = ARRAY_SIZE(serdes_max96745_devs); break; + case MAXIM_ID_MAX96749: + serdes_devs = serdes_max96749_devs; + mfd_num = ARRAY_SIZE(serdes_max96749_devs); + break; case MAXIM_ID_MAX96752: serdes_devs = serdes_max96752_devs; mfd_num = ARRAY_SIZE(serdes_max96752_devs); @@ -390,6 +424,162 @@ int serdes_device_init(struct serdes *serdes) } EXPORT_SYMBOL_GPL(serdes_device_init); +static int log_level_show(struct seq_file *m, void *data) +{ + seq_printf(m, "%lu\n", serdes_log_level); + + return 0; +} + +static int log_level_open(struct inode *inode, struct file *file) +{ + return single_open(file, log_level_show, NULL); +} + +static ssize_t log_level_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + char buf[12]; + unsigned long value; + + if (len > sizeof(buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, len)) + return -EFAULT; + + buf[len] = '\0'; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + serdes_log_level = value; + + return len; +} + +static int debug_show(struct seq_file *m, void *data) +{ + struct serdes *serdes = m->private; + + seq_printf(m, "%d\n", serdes->debug); + + return 0; +} + +static int debug_open(struct inode *inode, struct file *file) +{ + struct serdes *serdes = inode->i_private; + + return single_open(file, debug_show, serdes); +} + +static ssize_t debug_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct serdes *serdes = m->private; + char buf[12]; + + if (!serdes) + return -EINVAL; + + if (len > sizeof(buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, len)) + return -EFAULT; + + buf[len] = '\0'; + + if (sysfs_streq(buf, "on")) + serdes->debug = SERDES_OPEN_I2C_WRITE; + else if (sysfs_streq(buf, "off")) + serdes->debug = SERDES_CLOSE_I2C_WRITE; + else if (sysfs_streq(buf, "default")) { + serdes->debug = SERDES_SET_PINCTRL_DEFAULT; + serdes_set_pinctrl_default(serdes); + } else if (sysfs_streq(buf, "sleep")) { + serdes->debug = SERDES_SET_PINCTRL_SLEEP; + serdes_set_pinctrl_sleep(serdes); + } else if (sysfs_streq(buf, "seq")) { + serdes->debug = SERDES_SET_SEQUENCE; + serdes_i2c_set_sequence(serdes); + } else + return -EINVAL; + + return len; +} + +static const struct file_operations log_level_fops = { + .owner = THIS_MODULE, + .open = log_level_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = log_level_write +}; + +static const struct file_operations debug_fops = { + .owner = THIS_MODULE, + .open = debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = debug_write +}; + +void serdes_create_debugfs(struct serdes *serdes) +{ + + snprintf(serdes->dir_name, sizeof(serdes->dir_name), "%s-%s", + dev_name(serdes->dev), serdes->chip_data->name); + + serdes->debugfs_dentry = debugfs_create_dir(serdes->dir_name, serdes_debugfs_root); + debugfs_create_file("debug", 0664, serdes->debugfs_dentry, serdes, + &debug_fops); +} +EXPORT_SYMBOL(serdes_create_debugfs); + +void serdes_destroy_debugfs(struct serdes *serdes) +{ + debugfs_remove_recursive(serdes->debugfs_dentry); +} +EXPORT_SYMBOL(serdes_destroy_debugfs); + +void serdes_debugfs_init(void) +{ + serdes_debugfs_root = debugfs_create_dir("serdes", NULL); + + debugfs_create_file("log_level", 0664, serdes_debugfs_root, NULL, + &log_level_fops); +} +EXPORT_SYMBOL(serdes_debugfs_init); + +void serdes_debugfs_exit(void) +{ + debugfs_remove_recursive(serdes_debugfs_root); +} +EXPORT_SYMBOL(serdes_debugfs_exit); + +void serdes_dev_dbg(enum serdes_log_category category, const char *format, ...) +{ + struct va_format vaf; + va_list args; + + if (!unlikely(serdes_log_level & BIT(category))) + return; + + va_start(args, format); + vaf.fmt = format; + vaf.va = &args; + + pr_info("%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL(serdes_dev_dbg); + int serdes_set_pinctrl_default(struct serdes *serdes) { int ret = 0; diff --git a/drivers/mfd/display-serdes/serdes-gpio.c b/drivers/mfd/display-serdes/serdes-gpio.c index 1c49cf55fc28..eaaeb60eac34 100644 --- a/drivers/mfd/display-serdes/serdes-gpio.c +++ b/drivers/mfd/display-serdes/serdes-gpio.c @@ -209,6 +209,7 @@ static const struct of_device_id serdes_gpio_of_match[] = { { .compatible = "rohm,bu18tl82-gpio", }, { .compatible = "rohm,bu18rl82-gpio", }, { .compatible = "maxim,max96745-gpio", }, + { .compatible = "maxim,max96749-gpio", }, { .compatible = "maxim,max96752-gpio", }, { .compatible = "maxim,max96755-gpio", }, { .compatible = "maxim,max96772-gpio", }, diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index 3dfaf256f8fc..e2a7ef30908a 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -310,6 +310,8 @@ static int serdes_get_init_seq(struct serdes *serdes) return err; } + serdes->dual_link = of_property_read_bool(dev->of_node, "dual-link"); + /* init ser register(not des register) more early if uboot logo disabled */ serdes->route_enable = of_property_read_bool(dev->of_node, "route-enable"); if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER)) { @@ -445,6 +447,8 @@ static int serdes_i2c_probe(struct i2c_client *client) SERDES_DBG_MFD("%s: use_reg_check_work=%d\n", __func__, serdes->use_reg_check_work); } + serdes_create_debugfs(serdes); + dev_info(dev, "serdes %s serdes_i2c_probe successful version %s\n", serdes->chip_data->name, MFD_SERDES_DISPLAY_VERSION); @@ -471,6 +475,8 @@ static void serdes_i2c_remove(struct i2c_client *client) cancel_delayed_work_sync(&serdes->mfd_delay_work); destroy_workqueue(serdes->mfd_wq); } + + serdes_destroy_debugfs(serdes); } static int serdes_i2c_prepare(struct device *dev) @@ -535,6 +541,9 @@ static const struct of_device_id serdes_of_match[] = { #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) { .compatible = "maxim,max96745", .data = &serdes_max96745_data }, #endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96749) + { .compatible = "maxim,max96749", .data = &serdes_max96749_data }, +#endif #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) { .compatible = "maxim,max96752", .data = &serdes_max96752_data }, #endif @@ -583,12 +592,24 @@ static int __init serdes_i2c_init(void) int ret; ret = i2c_add_driver(&serdes_i2c_driver); - if (ret != 0) + if (ret != 0) { pr_err("Failed to register serdes I2C driver: %d\n", ret); + return ret; + } - return ret; + serdes_debugfs_init(); + + return 0; } + +static void __exit serdes_i2c_exit(void) +{ + i2c_del_driver(&serdes_i2c_driver); + serdes_debugfs_exit(); +} + subsys_initcall(serdes_i2c_init); +module_exit(serdes_i2c_exit); MODULE_AUTHOR("Luo Wei "); MODULE_DESCRIPTION("display i2c interface for different serdes"); diff --git a/drivers/mfd/display-serdes/serdes-panel-split.c b/drivers/mfd/display-serdes/serdes-panel-split.c index 01a2a8153860..1915de98359b 100644 --- a/drivers/mfd/display-serdes/serdes-panel-split.c +++ b/drivers/mfd/display-serdes/serdes-panel-split.c @@ -148,10 +148,6 @@ static int serdes_panel_split_parse_dt(struct serdes_panel_split *serdes_panel_s serdes_panel_split->width_mm = panel_size[0]; serdes_panel_split->height_mm = panel_size[1]; - serdes_panel_split->link_rate = link_rate_count_ssc[0]; - serdes_panel_split->lane_count = link_rate_count_ssc[1]; - serdes_panel_split->ssc = link_rate_count_ssc[2]; - if (of_find_property(dev->of_node, "panel-size", &len)) { len /= sizeof(unsigned int); ret = of_property_read_u32_array(dev->of_node, "panel-size", diff --git a/drivers/mfd/display-serdes/serdes-panel.c b/drivers/mfd/display-serdes/serdes-panel.c index 3691501510f2..b7fbfae76d96 100644 --- a/drivers/mfd/display-serdes/serdes-panel.c +++ b/drivers/mfd/display-serdes/serdes-panel.c @@ -147,10 +147,6 @@ static int serdes_panel_parse_dt(struct serdes_panel *serdes_panel) serdes_panel->width_mm = panel_size[0]; serdes_panel->height_mm = panel_size[1]; - serdes_panel->link_rate = link_rate_count_ssc[0]; - serdes_panel->lane_count = link_rate_count_ssc[1]; - serdes_panel->ssc = link_rate_count_ssc[2]; - if (of_find_property(dev->of_node, "panel-size", &len)) { len /= sizeof(unsigned int); if (len != 2) { diff --git a/drivers/mfd/display-serdes/serdes-pinctrl.c b/drivers/mfd/display-serdes/serdes-pinctrl.c index 27605732ff66..d16852ddd3c6 100644 --- a/drivers/mfd/display-serdes/serdes-pinctrl.c +++ b/drivers/mfd/display-serdes/serdes-pinctrl.c @@ -30,6 +30,13 @@ static const struct mfd_cell serdes_gpio_max96745_devs[] = { }, }; +static const struct mfd_cell serdes_gpio_max96749_devs[] = { + { + .name = "serdes-gpio", + .of_compatible = "maxim,max96749-gpio", + }, +}; + static const struct mfd_cell serdes_gpio_max96755_devs[] = { { .name = "serdes-gpio", @@ -173,6 +180,10 @@ static int serdes_pinctrl_gpio_init(struct serdes *serdes) serdes_devs = serdes_gpio_max96745_devs; mfd_num = ARRAY_SIZE(serdes_gpio_max96745_devs); break; + case MAXIM_ID_MAX96749: + serdes_devs = serdes_gpio_max96749_devs; + mfd_num = ARRAY_SIZE(serdes_gpio_max96749_devs); + break; case MAXIM_ID_MAX96752: serdes_devs = serdes_gpio_max96752_devs; mfd_num = ARRAY_SIZE(serdes_gpio_max96752_devs); diff --git a/drivers/mfd/rk806-core.c b/drivers/mfd/rk806-core.c index b0e9eb16fc00..d6b1af88289e 100644 --- a/drivers/mfd/rk806-core.c +++ b/drivers/mfd/rk806-core.c @@ -966,6 +966,28 @@ int rk806_device_init(struct rk806 *rk806) } EXPORT_SYMBOL_GPL(rk806_device_init); +int rk806_core_suspend(struct device *dev) +{ + struct rk806 *rk806 = dev_get_drvdata(dev); + + disable_irq(rk806->irq); + enable_irq_wake(rk806->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(rk806_core_suspend); + +int rk806_core_resume(struct device *dev) +{ + struct rk806 *rk806 = dev_get_drvdata(dev); + + enable_irq(rk806->irq); + disable_irq_wake(rk806->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(rk806_core_resume); + int rk806_device_exit(struct rk806 *rk806) { struct device_node *np = rk806->dev->of_node; diff --git a/drivers/mfd/rk806-i2c.c b/drivers/mfd/rk806-i2c.c index f0658805b022..09096c0ae262 100644 --- a/drivers/mfd/rk806-i2c.c +++ b/drivers/mfd/rk806-i2c.c @@ -44,10 +44,13 @@ static void rk806_remove(struct i2c_client *client) rk806_device_exit(rk806); } +static DEFINE_SIMPLE_DEV_PM_OPS(rk806_i2c_pm_ops, rk806_core_suspend, rk806_core_resume); + static struct i2c_driver rk806_i2c_driver = { .driver = { .name = "rk806", .of_match_table = of_match_ptr(rk806_of_match), + .pm = pm_sleep_ptr(&rk806_i2c_pm_ops), }, .probe = rk806_i2c_probe, .remove = rk806_remove, diff --git a/drivers/mfd/rk806-spi.c b/drivers/mfd/rk806-spi.c index c1053078558a..071493b3c8ce 100644 --- a/drivers/mfd/rk806-spi.c +++ b/drivers/mfd/rk806-spi.c @@ -111,6 +111,8 @@ static void rk806_spi_remove(struct spi_device *spi) rk806_device_exit(rk806); } +static DEFINE_SIMPLE_DEV_PM_OPS(rk806_spi_pm_ops, rk806_core_suspend, rk806_core_resume); + static const struct spi_device_id rk806_spi_id_table[] = { { "rk806", 0 }, { /* sentinel */ } @@ -122,6 +124,7 @@ static struct spi_driver rk806_spi_driver = { .name = "rk806", .owner = THIS_MODULE, .of_match_table = of_match_ptr(rk806_of_match), + .pm = pm_sleep_ptr(&rk806_spi_pm_ops), }, .probe = rk806_spi_probe, .remove = rk806_spi_remove, diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index c1c2d8ac329b..8ea84f399d11 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -299,8 +300,7 @@ static const struct mfd_cell rk818s[] = { static const struct rk808_reg_data rk801_pre_init_reg[] = { { RK801_SLEEP_CFG_REG, RK801_SLEEP_FUN_MSK, RK801_NONE_FUN }, - { RK801_SYS_CFG2_REG, RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H }, - { RK801_SYS_CFG2_REG, RK801_RST_MSK, RK801_RST_RESTART_REG }, + { RK801_SYS_CFG2_REG, RK801_RST_MSK, RK801_RST_RESTART_REG_RESETB }, { RK801_INT_CONFIG_REG, RK801_INT_POL_MSK, RK801_INT_ACT_L }, { RK801_POWER_FPWM_EN_REG, RK801_PLDO_HRDEC_EN, RK801_PLDO_HRDEC_EN }, { RK801_BUCK_DEBUG5_REG, 0xff, 0x54 }, @@ -850,6 +850,46 @@ static struct i2c_client *rk808_i2c_client; static struct rk808_reg_data *suspend_reg, *resume_reg; static int suspend_reg_num, resume_reg_num; +static inline int rk801_act_pol(bool act_low) +{ + return act_low ? RK801_SLEEP_ACT_L : RK801_SLEEP_ACT_H; +} + +static inline int rk801_inact_pol(bool act_low) +{ + return act_low ? RK801_SLEEP_ACT_H : RK801_SLEEP_ACT_L; +} + +static void rk801_device_reboot(void) +{ + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + int ret, act_pol; + + if (!rk808->pins || !rk808->pins->reset) + return; + + regmap_update_bits(rk808->regmap, RK801_SLEEP_CFG_REG, + RK801_SLEEP_FUN_MSK, RK801_NONE_FUN); + + ret = pinctrl_select_state(rk808->pins->p, rk808->pins->reset); + if (ret) + pr_err("failed to pmic-reset pinctrl state, ret=%d\n", ret); + + /* raw value ! */ + act_pol = gpiod_get_raw_value(rk808->pwrctrl.gpio) ? + RK801_SLEEP_ACT_L : RK801_SLEEP_ACT_H; + regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, + RK801_SLEEP_POL_MSK, act_pol); + + /* pmic rst func: register + 5ms-npor-signal */ + regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, + RK801_RST_MSK, RK801_RST_RESTART_REG_RESETB); + regmap_update_bits(rk808->regmap, RK801_SLEEP_CFG_REG, + RK801_SLEEP_FUN_MSK, RK801_RESET_FUN); + + dev_info(&rk808_i2c_client->dev, "rk801 system reboot ready\n"); +} + static int rk801_device_shutdown_prepare(struct sys_off_data *data) { int ret = 0; @@ -859,7 +899,8 @@ static int rk801_device_shutdown_prepare(struct sys_off_data *data) return -1; ret = regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, - RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H); + RK801_SLEEP_POL_MSK, + rk801_act_pol(rk808->pwrctrl.act_low)); if (ret < 0) return ret; @@ -966,6 +1007,7 @@ static void rk8xx_device_shutdown(void) /* Called in syscore shutdown */ static void (*pm_shutdown)(void); +static void (*pm_reboot)(void); static void rk8xx_syscore_shutdown(void) { @@ -1017,6 +1059,11 @@ static void rk8xx_syscore_shutdown(void) while (1) ; } + } else if (system_state == SYSTEM_RESTART) { + if (pm_reboot) { + dev_info(&rk808_i2c_client->dev, "System reboot\n"); + pm_reboot(); + } } } @@ -1088,6 +1135,42 @@ out: return count; } +static int rk801_pinctrl_init(struct device *dev, struct rk808 *rk808) +{ + struct gpio_desc *gpio; + + /* init soc-pwrctrl inactive pol (GPIOD_OUT_LOW is logic value) */ + gpio = devm_gpiod_get_optional(dev, "pwrctrl", GPIOD_OUT_LOW); + if (IS_ERR_OR_NULL(gpio)) { + dev_err(dev, "there is no pwrctrl gpio!\n"); + return -EINVAL; + } + rk808->pwrctrl.gpio = gpio; + rk808->pwrctrl.act_low = gpiod_is_active_low(gpio); + + /* init pmic-pwrctrl active pol */ + regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, + RK801_SLEEP_POL_MSK, + rk801_act_pol(rk808->pwrctrl.act_low)); + + /* pinctrl */ + rk808->pins = devm_kzalloc(dev, sizeof(struct rk808_pin_info), GFP_KERNEL); + if (!rk808->pins) + return -ENOMEM; + + rk808->pins->p = devm_pinctrl_get(dev); + if (IS_ERR(rk808->pins->p)) { + dev_err(dev, "no pinctrl settings\n"); + return -EINVAL; + } + + rk808->pins->reset = pinctrl_lookup_state(rk808->pins->p, "pmic-reset"); + if (IS_ERR(rk808->pins->reset)) + rk808->pins->reset = NULL; + + return 0; +} + static int rk817_pinctrl_init(struct device *dev, struct rk808 *rk808) { int ret; @@ -1316,8 +1399,10 @@ static int rk808_probe(struct i2c_client *client) const struct mfd_cell *cells; u8 on_source = 0, off_source = 0; unsigned int on, off; + u32 pmic_id_mask = RK8XX_ID_MSK; int nr_pre_init_regs; int nr_cells; + int pmic_id; int msb, lsb; unsigned char pmic_id_msb, pmic_id_lsb; int ret; @@ -1326,6 +1411,7 @@ static int rk808_probe(struct i2c_client *client) struct device *dev) = NULL; int (*pinctrl_init)(struct device *dev, struct rk808 *rk808) = NULL; void (*device_shutdown_fn)(void) = NULL; + void (*device_reboot_fn)(void) = NULL; rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); if (!rk808) @@ -1338,6 +1424,7 @@ static int rk808_probe(struct i2c_client *client) } else if (of_device_is_compatible(np, "rockchip,rk801")) { pmic_id_msb = RK801_ID_MSB; pmic_id_lsb = RK801_ID_LSB; + pmic_id_mask = RK801_ID_MSK; } else { pmic_id_msb = RK808_ID_MSB; pmic_id_lsb = RK808_ID_LSB; @@ -1358,11 +1445,13 @@ static int rk808_probe(struct i2c_client *client) return lsb; } - rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; - dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); + pmic_id = (msb << 8) | lsb; + rk808->variant = pmic_id & RK8XX_ID_MSK; + dev_info(&client->dev, "chip id: 0x%x\n", pmic_id & pmic_id_mask); switch (rk808->variant) { case RK801_ID: + rk808->pwrctrl.req_pwrctrl_dvs = (lsb & 0x0f) < 3; rk808->regmap_cfg = &rk801_regmap_config; rk808->regmap_irq_chip = &rk801_irq_chip; pre_init_reg = rk801_pre_init_reg; @@ -1372,6 +1461,8 @@ static int rk808_probe(struct i2c_client *client) on_source = RK801_ON_SOURCE_REG; off_source = RK801_OFF_SOURCE_REG; device_shutdown_fn = rk8xx_device_shutdown; + device_reboot_fn = rk801_device_reboot; + pinctrl_init = rk801_pinctrl_init; break; case RK805_ID: rk808->regmap_cfg = &rk805_regmap_config; @@ -1576,6 +1667,7 @@ static int rk808_probe(struct i2c_client *client) register_syscore_ops(&rk808_syscore_ops); /* power off system in the syscore shutdown ! */ pm_shutdown = device_shutdown_fn; + pm_reboot = device_reboot_fn; } } @@ -1636,7 +1728,8 @@ static int __maybe_unused rk8xx_suspend(struct device *dev) switch (rk808->variant) { case RK801_ID: ret = regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, - RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H); + RK801_SLEEP_POL_MSK, + rk801_act_pol(rk808->pwrctrl.act_low)); if (ret < 0) return ret; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b0e23b077729..8e6c17f7f4e8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -14,6 +14,7 @@ config RK803 Driver for RK803 which is used for driving porjector and IR flood LED. source "drivers/misc/rockchip/Kconfig" +source "drivers/misc/vehicle/Kconfig" config LT7911D_FB_NOTIFIER tristate "Lontium LT7911D FB Notifier" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 970bdcddefd2..cf2033145961 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -6,6 +6,7 @@ obj-y += rk628/ obj-$(CONFIG_RK803) += rk803.o obj-y += rockchip/ +obj-y += vehicle/ obj-$(CONFIG_LT7911D_FB_NOTIFIER) += lt7911d-fb-notifier.o obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_IBMVMC) += ibmvmc.o diff --git a/drivers/misc/rockchip/Kconfig b/drivers/misc/rockchip/Kconfig index 3329c6cd9c2b..259b4f386a9d 100644 --- a/drivers/misc/rockchip/Kconfig +++ b/drivers/misc/rockchip/Kconfig @@ -10,10 +10,3 @@ config PCIE_FUNC_RKEP help Enable this configuration option to enable the host side function driver for Rockchip's EP demo function driver. - -config PCIE_FUNC_RKEP_USERPAGES - bool "EP function driver reserve continuous physical space for user layer" - depends on PCIE_FUNC_RKEP=y - help - Enable this configuration option to reserve continuous physical space - for user layer in Rockchip's EP demo function driver. diff --git a/drivers/misc/rockchip/pcie-rkep.c b/drivers/misc/rockchip/pcie-rkep.c index 4dbe0653f006..1d96a61d53a4 100644 --- a/drivers/misc/rockchip/pcie-rkep.c +++ b/drivers/misc/rockchip/pcie-rkep.c @@ -89,7 +89,7 @@ static DEFINE_MUTEX(rkep_mutex); #define PCIE_DMA_CHANEL_MAX_NUM 2 -#define RKEP_USER_MEM_SIZE SZ_64M +#define RKEP_USER_MEM_SIZE SZ_4M #define PCIE_CFG_ELBI_APP_OFFSET 0xe00 #define PCIE_CFG_ELBI_USER_DATA_OFF 0x10 @@ -351,8 +351,10 @@ static int pcie_rkep_release(struct inode *inode, struct file *file) mutex_lock(&pcie_file->file_lock_mutex); index = find_first_bit(pcie_file->child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX); - if (index >= RKEP_EP_VIRTUAL_ID_MAX) + if (index >= RKEP_EP_VIRTUAL_ID_MAX) { + mutex_unlock(&pcie_file->file_lock_mutex); break; + } __clear_bit(index, pcie_file->child_vid_bitmap); mutex_unlock(&pcie_file->file_lock_mutex); @@ -1331,9 +1333,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } -#if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES) - pcie_rkep->user_pages = - alloc_contig_pages(RKEP_USER_MEM_SIZE >> PAGE_SHIFT, GFP_KERNEL, 0, NULL); + pcie_rkep->user_pages = alloc_pages(GFP_KERNEL, get_order(RKEP_USER_MEM_SIZE)); if (!pcie_rkep->user_pages) { dev_err(&pcie_rkep->pdev->dev, "failed to allocate contiguous pages\n"); ret = -EINVAL; @@ -1342,8 +1342,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_register_obj; } pcie_rkep->cur_mmap_res = PCIE_EP_MMAP_RESOURCE_USER_MEM; - dev_err(&pdev->dev, "successfully allocate continuouse buffer for userspace\n"); -#endif + dev_info(&pdev->dev, "successfully allocate continuouse buffer for userspace\n"); pci_read_config_word(pcie_rkep->pdev, PCI_VENDOR_ID, &val); dev_info(&pdev->dev, "vid=%x\n", val); @@ -1385,9 +1384,7 @@ static void pcie_rkep_remove(struct pci_dev *pdev) pcie_dw_dmatest_unregister(pcie_rkep->dma_obj); device_remove_file(&pdev->dev, &dev_attr_rkep); -#if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES) - free_contig_range(page_to_pfn(pcie_rkep->user_pages), RKEP_USER_MEM_SIZE >> PAGE_SHIFT); -#endif + __free_pages(pcie_rkep->user_pages, get_order(RKEP_USER_MEM_SIZE)); pcie_rkep_release_irq(pcie_rkep); if (pcie_rkep->bar0) @@ -1443,6 +1440,7 @@ static const struct pci_error_handlers pcie_rkep_err_handler = { static const struct pci_device_id pcie_rkep_pcidev_id[] = { { PCI_VDEVICE(ROCKCHIP, 0x356a), 1, }, + { PCI_VDEVICE(ROCKCHIP, 0x182a), 1, }, { } }; MODULE_DEVICE_TABLE(pcie_rkep, pcie_rkep_pcidev_id); diff --git a/drivers/misc/vehicle/Kconfig b/drivers/misc/vehicle/Kconfig new file mode 100644 index 000000000000..64b7eba956e2 --- /dev/null +++ b/drivers/misc/vehicle/Kconfig @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# vehicle configuration +# + +menu "misc vehicle setting" + +config VEHICLE_CORE + tristate "ROCKCHIP VEHICLE core support" + help + If you say yes here you get support for the RK + vehicle core module. + +config VEHICLE_DUMMY + tristate "RK VEHICLE DUMMY support" + select EXTCON + depends on VEHICLE_CORE + help + If you say yes here you get support for the RK dummy MCU + which simulate the vehicle signal. + +config VEHICLE_ADC + tristate "VEHICLE ADC support" + depends on VEHICLE_CORE + help + If you say yes here you get support for the vehicle with adc + which simulate the vehicle signal. + +config VEHICLE_GPIO + tristate "VEHICLE GPIO support" + depends on VEHICLE_CORE + help + If you say yes here you get support for the vehicle with gpio + which simulate the vehicle signal. + +config VEHICLE_SPI + tristate "VEHICLE SPI support" + depends on VEHICLE_CORE + help + If you say yes here you get support for the vehicle with spi bus + which simulate the vehicle signal. + +config VEHICLE_SPI_PROTOCOL + tristate "VEHICLE SPI_PROTOCOL support" + depends on VEHICLE_SPI + help + If you say yes here, you can get support for vehicle spi protocol. + +config VEHICLE_GPIO_MCU_EXPANDER + tristate "VEHICLE MCU GPIO EXPANDER support" + help + If you say yes here you get support for the mcu gpio expander. + +config VEHICLE_DRIVER_OREO + bool "RK vehicle driver for android oreo" + help + If you say yes here, you can get support for vehicle protocol + in android o, otherwise it support android p. + +endmenu diff --git a/drivers/misc/vehicle/Makefile b/drivers/misc/vehicle/Makefile new file mode 100644 index 000000000000..f0b749867907 --- /dev/null +++ b/drivers/misc/vehicle/Makefile @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for vehicle driver +# + +ccflags-y := -std=gnu99 -Wno-declaration-after-statement -DPB_SYSTEM_HEADER=\"pb_system.h\" -I$(srctree)/drivers/misc/vehicle/nanopb-c/ + +obj-$(CONFIG_VEHICLE_CORE) += vehicle-core.o +vehicle-core-objs = \ + nanopb-c/pb_common.o \ + nanopb-c/pb_decode.o \ + nanopb-c/pb_encode.o \ + vehicle_core.o \ + vehicle_protocol_callback.o \ + vehiclehalproto.pb.o + +obj-$(CONFIG_VEHICLE_DUMMY) += \ + vehicle_dummy_hw.o + +obj-$(CONFIG_VEHICLE_ADC) += \ + vehicle-adc.o + +obj-$(CONFIG_VEHICLE_GPIO) += \ + vehicle-gpio.o + +obj-$(CONFIG_VEHICLE_SPI) += \ + vehicle-spi.o \ + +obj-$(CONFIG_VEHICLE_SPI_PROTOCOL) += \ + vehicle_spi_protocol.o + +obj-$(CONFIG_VEHICLE_GPIO_MCU_EXPANDER) += \ + vehicle-gpio-mcu.o diff --git a/drivers/misc/vehicle/core.h b/drivers/misc/vehicle/core.h new file mode 100644 index 000000000000..4fb38adb2bdf --- /dev/null +++ b/drivers/misc/vehicle/core.h @@ -0,0 +1,375 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * core.h -- core define for mfd display arch + * + * Copyright (c) 2023-2028 Rockchip Electronics Co., Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_VEHICLE_CORE_H__ +#define __MFD_VEHICLE_CORE_H__ + +#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 +#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 "vehicle_core.h" + +/* + * if enable all the debug information, + * there will be much log. + * + * so suggest set CONFIG_LOG_BUF_SHIFT to 18 + */ +#define VEHICLE_DEBUG + + +#ifdef VEHICLE_DEBUG +#define VEHICLE_DBG(x...) pr_info(x) +#else +#define VEHICLE_DBG(x...) no_printk(x) +#endif + +#define MCU_MAX_REGS 64 +struct mcu_gpio_chip { + const char *name; + struct platform_device *pdev; + struct gpio_chip gpio_chip; + struct regmap *regmap; + struct regulator *regulator; + unsigned int ngpio; + u8 backup_regs[MCU_MAX_REGS]; + + struct gpio_desc *reset_gpio_desc; + int reset_gpio_irq; +}; + +struct vehicle; +enum vehicle_hw_type { + VEHICLE_HW_TYPE_INVALID = 0, + + VEHICLE_HW_TYPE_ADC, + VEHICLE_HW_TYPE_GPIO, + VEHICLE_HW_TYPE_I2C, + VEHICLE_HW_TYPE_SPI, + VEHICLE_HW_TYPE_UART, + VEHICLE_HW_TYPE_CHIP_MCU, + + VEHICLE_HW_TYPE_END, +}; + +/* VEHICLE is in state parking */ +#define GEAR_0 1 +/* VEHICLE is in state reverse */ +#define GEAR_1 2 +/* VEHICLE is in state neutral */ +#define GEAR_3 3 +/* VEHICLE is in state driver */ +#define GEAR_2 4 +/* no turn signal */ +#define TURN_0 0 +/* left turn signal */ +#define TURN_1 1 +/* right turn signal */ +#define TURN_2 2 + +#define POWER_REQ_STATE_ON 0 +#define POWER_REQ_STATE_SHUTDOWN_PREPARE 1 +#define POWER_REQ_STATE_CANCEL_SHUTDOWN 2 +#define POWER_REQ_STATE_FINISHED 3 + +#define POWER_REQ_PARAM_SHUTDOWN_IMMEDIATELY 1 +#define POWER_REQ_PARAM_CAN_SLEEP 2 +#define POWER_REQ_PARAM_SHUTDOWN_ONLY 3 +#define POWER_REQ_PARAM_SLEEP_IMMEDIATELY 4 +#define POWER_REQ_PARAM_HIBERNATE_IMMEDIATELY 5 +#define POWER_REQ_PARAM_CAN_HIBERNATE 6 + +/* temperature set from hardware on Android OREO and PIE uses below indexes */ +#define AC_TEMP_LEFT_INDEX 1 +#define AC_TEMP_RIGHT_INDEX 4 + +/* temperature set from APP on Android PIE uses below indexes */ +#define PIE_AC_TEMP_LEFT_INDEX 49 +#define PIE_AC_TEMP_RIGHT_INDEX 68 + + +struct vehicle_hw_data { + const char *name; + enum vehicle_hw_type vehicle_hw_type; + + int (*hw_init)(struct vehicle *vehicle); + int (*data_update)(struct vehicle *vehicle); + int (*suspend)(struct vehicle *vehicle); + int (*resume)(struct vehicle *vehicle); +}; + +struct vehicle_event_data { + u32 gear; + u32 turn; + u32 temp_right; + u32 temp_left; + u32 fan_direction; + u32 fan_speed; + u32 defrost_left; + u32 defrost_right; + u32 ac_on; + u32 auto_on; + u32 hvac_on; + u32 recirc_on; + u32 power_req_state; + u32 power_req_param; + u32 seat_temp_left; + u32 seat_temp_right; +}; + +struct vehicle_gpio { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type type; + struct device *dev; + struct platform_device *pdev; + struct vehicle *parent; + struct regmap *regmap; + int irq; + + struct gpio_desc *gear_gpio_park; + struct gpio_desc *gear_gpio_reverse; + struct gpio_desc *gear_gpio_neutral; + struct gpio_desc *gear_gpio_drive; + struct gpio_desc *gear_gpio_manual; + struct gpio_desc *turn_gpio; + struct gpio_desc *temp_right_gpio; + struct gpio_desc *temp_left_gpio; + struct gpio_desc *fan_direction_gpio; + struct gpio_desc *fan_speed_gpio; + struct gpio_desc *defrost_left_gpio; + struct gpio_desc *defrost_right_gpio; + struct gpio_desc *ac_on_gpio; + struct gpio_desc *auto_on_gpio; + struct gpio_desc *hvac_on_gpio; + struct gpio_desc *recirc_on_gpio; + struct gpio_desc *power_req_state_gpio; + struct gpio_desc *power_req_param_gpio; + struct gpio_desc *seat_temp_left_gpio; + struct gpio_desc *seat_temp_right_gpio; + + struct vehicle_hw_data *hw_data; +}; + +struct vehicle_chip_mcu { + enum vehicle_hw_type type; + struct device *dev; + struct vehicle *parent; + struct regmap *regmap; + +}; + +struct vehicle_spi { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type hw_type; + struct device *dev; + struct platform_device *pdev; + struct spi_device *spi; + int irq; + struct vehicle *parent; + struct regmap *regmap; + + struct mcu_gpio_chip *gpio_mcu; + + char *rx_buf; + int rx_len; + char *tx_buf; + int tx_len; + + struct vehicle_event_data spi_data; + struct vehicle_hw_data *hw_data; +}; + +struct vehicle_uart { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type hw_type; + struct device *dev; + struct platform_device *pdev; + struct vehicle *parent; + struct regmap *regmap; + + struct vehicle_event_data uart_data; + struct vehicle_hw_data *hw_data; +}; + +struct vehicle_dummy { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type hw_type; + struct device *dev; + struct platform_device *pdev; + struct vehicle *parent; + struct regmap *regmap; + + struct vehicle_event_data dummy_hw_data; +}; + +struct vehicle_adc { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type type; + struct device *dev; + struct platform_device *pdev; + struct vehicle *parent; + struct regmap *regmap; + int irq; + + struct iio_channel *gear_adc_chn; + struct iio_channel *turn_left_adc_chn; + struct iio_channel *turn_right_adc_chn; + struct iio_channel *temp_right_adc_chn; + struct iio_channel *temp_left_adc_chn; + struct iio_channel *fan_direction_adc_chn; + struct iio_channel *fan_speed_adc_chn; + struct iio_channel *defrost_left_adc_chn; + struct iio_channel *defrost_right_adc_chn; + struct iio_channel *ac_on_adc_chn; + struct iio_channel *auto_on_adc_chn; + struct iio_channel *hvac_on_adc_chn; + struct iio_channel *recirc_on_adc_chn; + struct iio_channel *power_req_state_adc_chn; + struct iio_channel *power_req_param_adc_chn; + struct iio_channel *seat_temp_left_adc_chn; + struct iio_channel *seat_temp_right_adc_chn; + + struct vehicle_hw_data *hw_data; +}; + +struct vehicle_i2c { + struct mutex wq_lock; + int use_delay_work; + struct delayed_work irq_work; + struct workqueue_struct *vehicle_wq; + struct delayed_work vehicle_delay_work; + + enum vehicle_hw_type hw_type; + struct device *dev; + struct platform_device *pdev; + struct vehicle *parent; + struct regmap *regmap; + + struct i2c_client *client; + struct vehicle_event_data i2c_data; + struct vehicle_hw_data *hw_data; +}; + +struct vehicle { + enum vehicle_hw_type hw_type; + struct device *dev; + struct platform_device *pdev; + + struct vehicle_event_data vehicle_data; + + struct vehicle_adc *vehicle_adc; + struct vehicle_gpio *vehicle_gpio; + struct vehicle_i2c *vehicle_i2c; + struct vehicle_spi *vehicle_spi; + struct vehicle_uart *vehicle_uart; + struct vehicle_dummy *vehicle_dummy; + struct vehicle_chip_mcu *vehicle_chip_mcu; +}; + +extern struct vehicle_hw_data vehicle_adc_data; +extern struct vehicle_hw_data vehicle_gpio_data; +extern struct vehicle_hw_data vehicle_i2c_data; +extern struct vehicle_hw_data vehicle_spi_data; +extern struct vehicle_hw_data vehicle_uart_data; +extern struct vehicle_hw_data vehicle_chip_mcu_data; + +extern struct vehicle *g_vehicle_hw; +extern const struct regmap_bus vehicle_regmap_spi; +extern void vehicle_set_property(u16 prop, u8 index, u32 value, u32 param); +extern int gpio_mcu_register(struct spi_device *spi); +extern int vehicle_spi_write_slt(struct vehicle *vehicle, const void *txbuf, size_t n); +extern int vehicle_spi_read_slt(struct vehicle *vehicle, void *rxbuf, size_t n); + +#endif diff --git a/drivers/misc/vehicle/nanopb-c/Makefile b/drivers/misc/vehicle/nanopb-c/Makefile new file mode 100644 index 000000000000..3e2725cd98e5 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile file pb_encode pb_decode pb_common +# + +ccflags-y := -Wall -W -Wno-unused-parameter -DPB_SYSTEM_HEADER=\"pb_system.h\" diff --git a/drivers/misc/vehicle/nanopb-c/pb.h b/drivers/misc/vehicle/nanopb-c/pb.h new file mode 100644 index 000000000000..d74a6a60acd0 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb.h @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. + */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. + */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. + */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ****************************************************************** + */ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. + */ +#define NANOPB_VERSION (nanopb-0.3.9.1) + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +#define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +#define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +#define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +#define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +#define PB_PACKED_STRUCT_END __pragma(pack(pop)) +#define pb_packed +#else + /* Unknown compiler */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) ((void)(x)) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND, MSG) \ + typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND) ? 1 : -1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#ifndef STATIC_ASSERT +#define STATIC_ASSERT PB_STATIC_ASSERT +#define STATIC_ASSERT_MSG PB_STATIC_ASSERT_MSG +#define STATIC_ASSERT_MSG_ PB_STATIC_ASSERT_MSG_ +#endif +#else +#define PB_STATIC_ASSERT(COND, MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x04 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. + */ +#define PB_LTYPE_BYTES 0x05 + +/* String with pre-allocated buffer. + * data_size is the maximum length. + */ +#define PB_LTYPE_STRING 0x06 + +/* Submessage + * submsg_fields is pointer to field descriptions + */ +#define PB_LTYPE_SUBMESSAGE 0x07 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t + */ +#define PB_LTYPE_EXTENSION 0x08 + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. + */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0A +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) +typedef uint32_t pb_size_t; +typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) +typedef uint_least16_t pb_size_t; +typedef int_least16_t pb_ssize_t; +#else +typedef uint_least8_t pb_size_t; +typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. + */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ +union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); +} funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ +union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); +} funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. + */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. + */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. + */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. + */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. + */ +#ifdef PB_ENABLE_MALLOC +#ifndef pb_realloc +#define pb_realloc(ptr, size) realloc(ptr, size) +#endif +#ifndef pb_free +#define pb_free(ptr) free(ptr) +#endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) ((sizeof((st *)0)->m)) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0, (pb_type_t) 0, 0, 0, 0, 0, 0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) \ + (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside a union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) \ + ((int)(offsetof(st, m1) == offsetof(st, m2)) \ + ? (PB_DATAOFFSET_FIRST(st, m1, m2)) \ + : (PB_DATAOFFSET_OTHER(st, m1, m2))) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. + */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) +#define PB_FIELD2 PB_FIELD + +/* Field description for repeated static fixed count fields.*/ +#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + 0, \ + pb_membersize(message, field[0]), \ + pb_arraysize(message, field), ptr} + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, \ + allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, \ + allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) \ + (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return (PB_SET_ERROR(stream, msg), false) + +#endif diff --git a/drivers/misc/vehicle/nanopb-c/pb_common.c b/drivers/misc/vehicle/nanopb-c/pb_common.c new file mode 100644 index 000000000000..51555d4f8f90 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_common.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char *)dest_struct + iter->pos->data_offset; + iter->pSize = (char *)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. + */ + return false; + + iter->pos++; + + if (iter->pos->tag == 0) { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } else { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && + iter->pos->data_offset == PB_SIZE_MAX) + /* Don't advance pointers inside unions */ + return true; + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries + */ + prev_size *= prev_field->array_size; + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. + */ + prev_size = sizeof(void *); + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + /* Count the required fields, in order to check their presence in the + * decoder. + */ + iter->required_field_index++; + + iter->pData = (char *)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char *)iter->pData + iter->pos->size_offset; + + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + /* Found the wanted field */ + return true; + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + diff --git a/drivers/misc/vehicle/nanopb-c/pb_common.h b/drivers/misc/vehicle/nanopb-c/pb_common.h new file mode 100644 index 000000000000..9f0edf002f92 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_common.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + /* Zero-based index that counts only the required fields */ + unsigned int required_field_index; + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. + */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. + */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. + */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/drivers/misc/vehicle/nanopb-c/pb_decode.c b/drivers/misc/vehicle/nanopb-c/pb_decode.c new file mode 100644 index 000000000000..f2b6334b1f14 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_decode.c @@ -0,0 +1,1503 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if (!defined(__GNUC__)) || (__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn read_raw_value(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_byte_t *buf, + size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, + pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, + uint32_t tag, + pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, + pb_wire_type_t wire_type, + pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], + void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, + uint32_t *dest, + bool *eof); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, + const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, + const pb_field_t *field, + void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, + size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, + pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + + const pb_byte_t *source = (const pb_byte_t *)stream->state; + + stream->state = (pb_byte_t *)stream->state + count; + if (buf != NULL) { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) { + /* Skip input bytes */ + pb_byte_t tmp[16]; + + while (count > 16) { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. + */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t *)stream->state; + stream->state = (pb_byte_t *)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; + +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) { + if (stream->bytes_left == 0) { + if (eof) + *eof = true; + } + + return false; + } + + if ((byte & 0x80) == 0) + /* Quick case, 1 byte value */ + result = byte; + else { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + + result = byte & 0x7F; + + do { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) { + /* The varint could have trailing 0x80 bytes, + * or 0xFF for negative. + */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && + ((result >> 31) == 0 || byte != sign_extension)) + PB_RETURN_ERROR(stream, "varint overflow"); + } else + result |= (uint32_t)(byte & 0x7F) << bitpos; + + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + + do { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, + pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + return false; + + if (temp == 0) { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: + PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, + pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + + switch (wire_type) { + case PB_WT_VARINT: + *size = 0; + do { + (*size)++; + if (*size > max_size) + return false; + if (!pb_read(stream, buf, 1)) + return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: + PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, + pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + if (iter->pSize != iter->pData) + *(bool *)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t *)iter->pSize; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) { + void *pItem = (char *)iter->pData + iter->pos->data_size * (*size); + + if (!func(&substream, iter->pos, pItem)) { + status = false; + break; + } + (*size)++; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } else { + /* Repeated field */ + pb_size_t *size = (pb_size_t *)iter->pSize; + char *pItem = (char *)iter->pData + iter->pos->data_size * (*size); + + if ((*size)++ >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t *)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. + */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, + size_t array_size) +{ + void *ptr = *(void **)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + + if (data_size >= check_limit || array_size >= check_limit) { + const size_t size_max = (size_t)-1; + + if (size_max / array_size < data_size) + PB_RETURN_ERROR(stream, "size too large"); + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. + */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void **)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + *(void **)pItem = NULL; + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. + */ + memset(pItem, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, + pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void **)iter->pData != NULL) + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + *(pb_size_t *)iter->pSize = iter->pos->tag; + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + return func(stream, iter->pos, iter->pData); + else { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void **)iter->pData, iter); + return func(stream, iter->pos, *(void **)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t *)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) { + if ((size_t)*size + 1 > allocated_size) { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. + */ + allocated_size += (substream.bytes_left - 1) / + iter->pos->data_size + 1; + + if (!allocate_field(&substream, iter->pData, + iter->pos->data_size, allocated_size)) { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char **)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } else { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t *)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size)) + return false; + + pItem = *(char **)iter->pData + iter->pos->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, + pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t *)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } else { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. + */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, + pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. + */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. + */ + const pb_field_t *field = (const pb_field_t *)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. + */ + iter->pData = &extension->dest; +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. + */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t *)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. + */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, + pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t * const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) { + bool status; + + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. + */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + + type = iter->pos->type; + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { + pb_extension_t *ext = *(pb_extension_t * const *)iter->pData; + + while (ext != NULL) { + pb_field_iter_t ext_iter; + + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } else if (PB_ATYPE(type) == PB_ATYPE_STATIC) { + bool init_data = true; + + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) + /* Set has_field to false. Still initialize the optional field + * itself also. + */ + *(bool *)iter->pSize = false; + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) { + /* REPEATED: Set array count to 0, no need to initialize contents. + *ONEOF: Set which_field to 0. + */ + *(pb_size_t *)iter->pSize = 0; + init_data = false; + } + + if (init_data) { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, + iter->pData); + else if (iter->pos->ptr != NULL) + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + else + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } else if (PB_ATYPE(type) == PB_ATYPE_POINTER) { + /* Initialize the pointer to NULL. */ + *(void **)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + *(pb_size_t *)iter->pSize = 0; + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], + void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + const pb_field_t *fixed_count_field = NULL; + pb_size_t fixed_count_size = 0; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. + */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + /* The field was handled */ + continue; + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED + && iter.pSize == iter.pData) { + if (fixed_count_field != iter.pos) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + + fixed_count_field = iter.pos; + fixed_count_size = 0; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + + /* Check that all required fields were present. */ + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned int req_field_count; + pb_type_t last_type; + unsigned int i; + + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) { + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) + PB_RETURN_ERROR(stream, "missing required field"); + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_noinit(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. + */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t *)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. + */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. + */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + + type = iter->pos->type; + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { + if (*(pb_size_t *)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. + */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t **)iter->pData; + + while (ext != NULL) { + pb_field_iter_t ext_iter; + + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + pItem = *(void **)iter->pData; + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { + if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) + /* No _count field so use size of the array */ + count = iter->pos->array_size; + else + count = *(pb_size_t *)iter->pSize; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } + + if (pItem) { + while (count--) { + pb_release((const pb_field_t *)iter->pos->ptr, pItem); + pItem = (char *)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void ***)iter->pData; + pb_size_t count = *(pb_size_t *)iter->pSize; + + while (count--) { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t *)iter->pSize = 0; + + /* Release main item */ + pb_free(*(void **)iter->pData); + *(void **)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t *)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t *)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} +#endif + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t *)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t *)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t *)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t *)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value, clamped; + + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t *)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t *)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t *)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t *)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t *)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t *)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t *)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t *)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t **)dest; +#endif + } else { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t *)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void **)dest; +#endif + } else { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t *)dest, size); + *((pb_byte_t *)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t *submsg_fields = (const pb_field_t *)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. + */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, + void *dest) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) { + /* As a special case, treat empty bytes string + * as all zeros for fixed_length_bytes. + */ + memset(dest, 0, field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t *)dest, field->data_size); +} diff --git a/drivers/misc/vehicle/nanopb-c/pb_decode.h b/drivers/misc/vehicle/nanopb-c/pb_decode.h new file mode 100644 index 000000000000..55dee5750e98 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_decode.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s { +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. + */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * int64, uint32 and uint64 field types. + */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * and uint32 field types. + */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. + */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. + */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. + */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/drivers/misc/vehicle/nanopb-c/pb_encode.c b/drivers/misc/vehicle/nanopb-c/pb_encode.c new file mode 100644 index 000000000000..35bae5f2e08d --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_encode.c @@ -0,0 +1,889 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, + const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, + const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, + const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, + const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, + const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, + const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, + const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, + const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, + const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, + const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, + const pb_field_t *field, const void *src); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t + +static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, + size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t *)stream->state; + + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; + +#ifdef PB_BUFFER_ONLY + stream.callback = (void *)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (stream->callback != NULL) { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; + size_t size; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + size = 4 * count; + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + size = 8 * count; + else { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + p = pData; + for (i = 0; i < count; i++) { + if (!func(&sizestream, field, p)) + return false; + p = (const char *)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) { + if (!func(stream, field, p)) + return false; + p = (const char *)p + field->data_size; + } + } else { + p = pData; + for (i = 0; i < count; i++) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. + */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { + if (!func(stream, field, *(const void * const *)p)) + return false; + } else { + if (!func(stream, field, p)) + return false; + } + p = (const char *)p + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded + * if their value is "non-zero". + * This function implements the check for the zero value. + */ +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) +{ + pb_type_t type = field->type; + const void *pSize = (const char *)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t *)pSize == 0; + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + /* Oneof fields */ + return *(const pb_size_t *)pSize == 0; + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool *)pSize == false; + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t *)pData; + + return bytes->size == 0; + } else if (PB_LTYPE(type) == PB_LTYPE_STRING) + return *(const char *)pData == '\0'; + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. + */ + return field->data_size == 0; + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + + if (pb_field_iter_begin(&iter, (const pb_field_t *)field->ptr, + pb_const_cast(pData))) { + do { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + return false; + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char *)pData; + + for (i = 0; i < field->data_size; i++) { + if (p[i] != 0) + return false; + } + + return true; + +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. + */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + /* Static optional, repeated or oneof field */ + pSize = (const char *)pData + field->size_offset; + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + else + /* Required field, always present */ + implicit_has = true; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void * const *)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool *)pSize) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: { + pb_size_t count; + + if (field->size_offset != 0) + count = *(const pb_size_t *)pSize; + else + count = field->array_size; + + if (!encode_array(stream, field, pData, count, func)) + return false; + break; + } + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t *)pSize == field->tag) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. + * This means that a user function is + * called to provide and encode the actual data. + */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, + const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t *)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. + */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t *)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. + */ + return encode_field(stream, field, &extension->dest); + } else + return encode_field(stream, field, extension->dest); +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. + */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, + const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t * const *)pData; + + PB_UNUSED(field); + while (extension) { + bool status; + + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, + * in order to use the common field iterator + * logic for both encoding and decoding. + */ + union { + void *p1; + const void *p2; + } t; + + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } else { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct) +{ + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], + const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +#ifdef PB_WITHOUT_64BIT +bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ + + while (value) { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + if (compensation) { + /* re-set all the compensation bits we can or need */ + size_t bits = compensation > 7 ? 7 : compensation; + + value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); + /* set the number of bits needed on the lowest + * of the most significant 7 bits + */ + compensation -= bits; + } + i++; + } + buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} +#endif + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) { + pb_byte_t v = (pb_byte_t)value; + + return pb_write(stream, &v, 1); + } + + while (value) { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t *)value; + pb_byte_t bytes[4]; + + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t *)value; + pb_byte_t bytes[8]; + + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, + uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + + switch (PB_LTYPE(field->type)) { + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. + */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t *)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t *)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t *)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t *)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + +#ifdef PB_WITHOUT_64BIT + if (value < 0) + return pb_encode_negative_varint(stream, (pb_uint64_t)value); +#endif + return pb_encode_varint(stream, (pb_uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t *)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t *)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t *)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t *)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t *)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t *)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t *)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t *)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, + const void *src) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t *)src; + + if (src == NULL) { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + PB_RETURN_ERROR(stream, "bytes size exceeded"); + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, + const pb_field_t *field, + const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char *)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + size = 0; /* Treat null pointer as an empty string */ + else { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t *)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, + const pb_field_t *field, + const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t *)field->ptr, src); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, + const pb_field_t *field, + const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t *)src, field->data_size); +} + diff --git a/drivers/misc/vehicle/nanopb-c/pb_encode.h b/drivers/misc/vehicle/nanopb-c/pb_encode.h new file mode 100644 index 000000000000..0ad04e494304 --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_encode.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * + * This software is provided 'as-is', without any express or + * implied warranty. In no event will the authors be held liable + * for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s { +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct); + +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, + * so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. + */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], + const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0, 0, 0, 0, 0} +#else +#define PB_OSTREAM_SIZING {0, 0, 0, 0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. + */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifying wire type. You need to use this + * if you want to write out packed arrays from a callback field. + */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, + uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. + */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. + */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. + */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. + */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], + const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/drivers/misc/vehicle/nanopb-c/pb_system.h b/drivers/misc/vehicle/nanopb-c/pb_system.h new file mode 100644 index 000000000000..2166e4b7256b --- /dev/null +++ b/drivers/misc/vehicle/nanopb-c/pb_system.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018 NXP + * + * 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 PB_SYSTEM_H +#define PB_SYSTEM_H + +#include + +typedef u8 uint_least8_t; +typedef s8 int_least8_t; +typedef u8 uint_fast8_t; + +typedef u16 uint_least16_t; +typedef s16 int_least16_t; + +#endif diff --git a/drivers/misc/vehicle/vehicle-adc.c b/drivers/misc/vehicle/vehicle-adc.c new file mode 100644 index 000000000000..0477f52ac061 --- /dev/null +++ b/drivers/misc/vehicle/vehicle-adc.c @@ -0,0 +1,274 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * vehicle-adc.c -- I2C register interface access for adc + * + * Copyright (c) 2025-2030 Rockchip Electronics Co., Ltd. + * + * Author: LuoWei + */ + +#include "core.h" + +static int vehicle_adc_init_channel(struct vehicle *vehicle, struct iio_channel **channel, + const char *name) +{ + int err = 0; + enum iio_chan_type type; + struct device *dev = vehicle->vehicle_adc->dev; + + struct iio_channel *tmp_channel = devm_iio_channel_get(dev, name); + + if (IS_ERR(tmp_channel)) + return PTR_ERR(tmp_channel); + + if (!tmp_channel->indio_dev) + return -ENXIO; + + err = iio_get_channel_type(tmp_channel, &type); + if (err < 0) + return err; + + if (type != IIO_VOLTAGE) { + dev_err(dev, "Incompatible channel type %d\n", type); + return -EINVAL; + } + + *channel = tmp_channel; + + return err; +} + +static int vehicle_adc_update_data(struct vehicle *vehicle) +{ + int val; + struct device *dev = vehicle->vehicle_adc->dev; + + vehicle->vehicle_data.turn = TURN_0; + if (vehicle->vehicle_adc->gear_adc_chn) { + if (iio_read_channel_raw(vehicle->vehicle_adc->gear_adc_chn, &val) < 0) + dev_err(dev, "Failed to read gear adc value\n"); + + if (val < 200) + vehicle->vehicle_data.gear = GEAR_0; + else if (val > 200 && val < 1200) + vehicle->vehicle_data.gear = GEAR_1; + else if (val > 1200 && val < 2200) + vehicle->vehicle_data.gear = GEAR_3; + else if (val > 2200 && val < 3200) + vehicle->vehicle_data.gear = GEAR_2; + } + + if (vehicle->vehicle_adc->turn_left_adc_chn) { + if (iio_read_channel_raw(vehicle->vehicle_adc->turn_left_adc_chn, &val) < 0) + dev_err(dev, "Failed to read turn adc value\n"); + + if (val < 100) + vehicle->vehicle_data.turn = TURN_1; + } + + if (vehicle->vehicle_adc->turn_right_adc_chn) { + if (iio_read_channel_raw(vehicle->vehicle_adc->turn_right_adc_chn, &val) < 0) + dev_err(dev, "Failed to read turn adc value\n"); + + if (val < 100) + vehicle->vehicle_data.turn = TURN_2; + } + + vehicle_set_property(VEHICLE_GEAR, 0, vehicle->vehicle_data.gear, 0); + vehicle_set_property(VEHICLE_TURN_SIGNAL, 0, vehicle->vehicle_data.turn, 0); + + dev_info(dev, "gear %u turn %u\n", vehicle->vehicle_data.gear, + vehicle->vehicle_data.turn); + + /* to do others adc */ + return 0; +} + +static void vehicle_adc_delay_work_func(struct work_struct *work) +{ + struct vehicle_adc *vehicle_adc = container_of(work, struct vehicle_adc, + vehicle_delay_work.work); + struct device *dev = vehicle_adc->dev; + + vehicle_adc_update_data(g_vehicle_hw); + + if (vehicle_adc->use_delay_work) + queue_delayed_work(vehicle_adc->vehicle_wq, &vehicle_adc->vehicle_delay_work, + msecs_to_jiffies(1000)); + + dev_info(dev, "%s\n", __func__); +} + +static irqreturn_t vehicle_adc_irq_handle(int irq, void *_data) +{ + struct vehicle_adc *vehicle_adc = _data; + + queue_delayed_work(vehicle_adc->vehicle_wq, &vehicle_adc->vehicle_delay_work, + msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static int vehicle_adc_irq_init(struct vehicle_adc *vehicle_adc) +{ + struct device *dev = vehicle_adc->dev; + int ret; + + vehicle_adc->irq = platform_get_irq(vehicle_adc->pdev, 0); + if (vehicle_adc->irq < 0) { + dev_err(dev, "failed to get irq\n"); + return -ENODEV; + } + ret = devm_request_threaded_irq(dev, vehicle_adc->irq, + vehicle_adc_irq_handle, NULL, + IRQF_TRIGGER_HIGH, + dev_name(dev), vehicle_adc); + + if (ret < 0) { + dev_err(dev, "error: irq %d\n", vehicle_adc->irq); + return ret; + } + + return 0; +} + +static int adc_hw_init(struct vehicle *vehicle) +{ + int err = 0; + struct device *dev = vehicle->dev; + + err = vehicle_adc_init_channel(vehicle, + &vehicle->vehicle_adc->gear_adc_chn, + "gear"); + if (err) + dev_err(dev, "failed to get turn adc channel.\n"); + + err = vehicle_adc_init_channel(vehicle, + &vehicle->vehicle_adc->turn_left_adc_chn, + "turn_left"); + if (err) + dev_err(dev, "failed to get turn_left adc channel.\n"); + + err = vehicle_adc_init_channel(vehicle, + &vehicle->vehicle_adc->turn_right_adc_chn, + "turn_right"); + if (err) + dev_err(dev, "failed to get turn_right adc channel.\n"); + + vehicle->vehicle_adc->vehicle_wq = alloc_ordered_workqueue("%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, + "vehicle-adc-wq"); + mutex_init(&vehicle->vehicle_adc->wq_lock); + INIT_DELAYED_WORK(&vehicle->vehicle_adc->vehicle_delay_work, vehicle_adc_delay_work_func); + + //vehicle->vehicle_adc->use_delay_work = + // of_property_read_bool(vehicle->dev->of_node, "use-delay-work"); + vehicle->vehicle_adc->use_delay_work = 1; + if (vehicle->vehicle_adc->use_delay_work) { + queue_delayed_work(vehicle->vehicle_adc->vehicle_wq, + &vehicle->vehicle_adc->vehicle_delay_work, + msecs_to_jiffies(100)); + VEHICLE_DBG("%s: vehicle_adc->use_delay_work=%d\n", __func__, + vehicle->vehicle_adc->use_delay_work); + } else { + vehicle_adc_irq_init(vehicle->vehicle_adc); + VEHICLE_DBG("%s: vehicle_adc->use_delay_work=%d\n", __func__, + vehicle->vehicle_adc->use_delay_work); + } + + return 0; +} + +static int adc_pm_suspend(struct vehicle *vehicle) +{ + return 0; +} + +static int adc_pm_resume(struct vehicle *vehicle) +{ + return 0; +} + +struct vehicle_hw_data vehicle_adc_data = { + .name = "vehicle-adc", + .vehicle_hw_type = VEHICLE_HW_TYPE_ADC, + .data_update = vehicle_adc_update_data, + .hw_init = adc_hw_init, + .suspend = adc_pm_suspend, + .resume = adc_pm_resume, +}; +EXPORT_SYMBOL_GPL(vehicle_adc_data); + +static int vehicle_adc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vehicle_adc *vehicle_adc; + + if (!pdev) + return -ENOMEM; + + if (g_vehicle_hw == NULL) + return -ENOMEM; + + vehicle_adc = devm_kzalloc(dev, sizeof(*vehicle_adc), GFP_KERNEL); + if (vehicle_adc == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, vehicle_adc); + vehicle_adc->hw_data = &vehicle_adc_data; + vehicle_adc->dev = dev; + vehicle_adc->pdev = pdev; + + g_vehicle_hw->vehicle_adc = vehicle_adc; + + adc_hw_init(g_vehicle_hw); + + pr_info("%s successfully\n", __func__); + + return 0; +} + +static int vehicle_adc_remove(struct platform_device *pdev) +{ + struct vehicle_adc *vehicle_adc = platform_get_drvdata(pdev); + + destroy_workqueue(vehicle_adc->vehicle_wq); + return 0; +} + +static const struct of_device_id vehicle_adc_id[] = { + { .compatible = "rockchip,vehicle-adc", }, + { .compatible = "rockchip,vehicle-dummy-adc", }, + {}, +}; + +static struct platform_driver vehicle_adc_device_driver = { + .probe = vehicle_adc_probe, + .remove = vehicle_adc_remove, + .driver = { + .name = "vehicle-adc", + .of_match_table = vehicle_adc_id, + } +}; + +static int vehicle_adc_init(void) +{ + int err; + + err = platform_driver_register(&vehicle_adc_device_driver); + if (err) + pr_err("Failed to register vehicle driver\n"); + + pr_info("%s successfully\n", __func__); + return err; +} + +static void __exit vehicle_adc_exit(void) +{ + platform_driver_unregister(&vehicle_adc_device_driver); +} + +postcore_initcall(vehicle_adc_init); +module_exit(vehicle_adc_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/vehicle/vehicle-gpio-mcu.c b/drivers/misc/vehicle/vehicle-gpio-mcu.c new file mode 100644 index 000000000000..794bb3373e4b --- /dev/null +++ b/drivers/misc/vehicle/vehicle-gpio-mcu.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MCU I2C Port Expander I/O + * + * Copyright (C) 2023 Cody Xie + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" + +#define MCU_REG_CONFIG_BASE 0x00 +#define MCU_REG_CONFIG_PORT0 (MCU_REG_CONFIG_BASE + 0x0) +#define MCU_REG_CONFIG_PORT1 (MCU_REG_CONFIG_BASE + 0x1) +#define MCU_REG_CONFIG_PORT31 (MCU_REG_CONFIG_BASE + 0x1f) + +#define MCU_REG_DIRECTION_BASE (MCU_REG_CONFIG_PORT31 + 0x1) +#define MCU_REG_DIRECTION_END (MCU_REG_DIRECTION_BASE + 0x20) + + +static struct mcu_gpio_chip *g_gpio_mcu_chip; + +static int mcu_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + struct mcu_gpio_chip *priv = gpiochip_get_data(gc); + unsigned int value; + int ret; + + dev_info(gc->parent, "%s offset(%d)", __func__, offset); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(&priv->pdev->dev, "%s register map not ready: %d\n", + __func__, ret); + return ret; + } + + ret = regmap_read(priv->regmap, MCU_REG_DIRECTION_BASE + offset, &value); + if (ret < 0) { + dev_err(gc->parent, "%s offset(%d) read config failed", + __func__, offset); + return ret; + } + + return value; +} + +static int mcu_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + struct mcu_gpio_chip *priv = gpiochip_get_data(gc); + int ret; + + dev_dbg(gc->parent, "%s offset(%d)", __func__, offset); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(&priv->pdev->dev, "%s register map not ready: %d\n", + __func__, ret); + return ret; + } + + ret = regmap_write(priv->regmap, MCU_REG_DIRECTION_BASE + offset, GPIO_LINE_DIRECTION_IN); + if (ret < 0) { + dev_err(gc->parent, "%s offset(%d) read config failed", + __func__, offset); + } + + return ret; +} + +static int mcu_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct mcu_gpio_chip *priv = gpiochip_get_data(gc); + int ret; + + dev_dbg(gc->parent, "%s offset(%d) val(%d)", __func__, offset, val); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(&priv->pdev->dev, "%s register map not ready: %d\n", + __func__, ret); + return ret; + } + + + ret = regmap_write(priv->regmap, MCU_REG_DIRECTION_BASE + offset, GPIO_LINE_DIRECTION_OUT); + if (ret < 0) { + dev_err(gc->parent, + "%s offset(%d) val(%d) update config failed", __func__, + offset, val); + return ret; + } + + ret = regmap_write(priv->regmap, MCU_REG_CONFIG_BASE + offset, val); + if (ret < 0) { + dev_err(gc->parent, + "%s offset(%d) val(%d) update output failed", __func__, + offset, val); + return ret; + } + + return ret; +} + +static int mcu_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct mcu_gpio_chip *priv = gpiochip_get_data(gc); + unsigned int value; + int ret; + + dev_info(gc->parent, "%s offset(%d)", __func__, offset); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(&priv->pdev->dev, "%s register map not ready: %d\n", + __func__, ret); + return ret; + } + + ret = regmap_read(priv->regmap, MCU_REG_CONFIG_BASE + offset, &value); + if (ret < 0) { + dev_err(gc->parent, "%s offset(%d) check config failed", + __func__, offset); + return ret; + } + + return value; +} + +static void mcu_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct mcu_gpio_chip *priv = gpiochip_get_data(gc); + int ret; + + dev_info(gc->parent, "%s offset(%d) val(%d)", __func__, offset, val); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + dev_err(&priv->pdev->dev, "%s register map not ready\n", + __func__); + return; + } + + ret = regmap_write(priv->regmap, MCU_REG_CONFIG_BASE + offset, val); + if (ret < 0) { + dev_err(gc->parent, "%s offset(%d) val(%d) set output failed", + __func__, offset, val); + } +} + +static bool mcu_is_writeable_reg(struct device *dev, unsigned int reg) +{ + if ((reg <= MCU_REG_DIRECTION_END) && (reg >= MCU_REG_CONFIG_PORT0)) + return true; + + return false; +} + +static bool mcu_is_readable_reg(struct device *dev, unsigned int reg) +{ + if ((reg <= MCU_REG_DIRECTION_END) && (reg >= MCU_REG_CONFIG_PORT0)) + return true; + + return false; +} + +static bool mcu_is_volatile_reg(struct device *dev, unsigned int reg) +{ + return true; +} + +static const struct reg_default mcu_regmap_default[MCU_MAX_REGS] = { + { MCU_REG_CONFIG_PORT0, 0xFF }, + { MCU_REG_CONFIG_PORT1, 0xFF }, + { } +}; + +static const struct regmap_config mcu_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x3f, + .writeable_reg = mcu_is_writeable_reg, + .readable_reg = mcu_is_readable_reg, + .volatile_reg = mcu_is_volatile_reg, + .reg_defaults = mcu_regmap_default, + .num_reg_defaults = ARRAY_SIZE(mcu_regmap_default), + .cache_type = REGCACHE_FLAT, +}; + +static const struct gpio_chip template_chip = { + .label = "mcu-gpio", + .owner = THIS_MODULE, + .get_direction = mcu_gpio_get_direction, + .direction_input = mcu_gpio_direction_input, + .direction_output = mcu_gpio_direction_output, + .get = mcu_gpio_get, + .set = mcu_gpio_set, + .base = -1, + .can_sleep = true, +}; + +#ifdef CONFIG_PM +static int mcu_suspend(struct device *dev) +{ + struct mcu_gpio_chip *priv = dev_get_drvdata(dev); + int ret = 0; + + dev_info(dev, "%s: registers backup", __func__); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(dev, "%s register map not ready: %d\n", __func__, ret); + return ret; + } + + regcache_mark_dirty(priv->regmap); + regcache_cache_only(priv->regmap, true); + + return 0; +} + +static int mcu_resume(struct device *dev) +{ + struct mcu_gpio_chip *priv = dev_get_drvdata(dev); + int ret = 0; + + dev_info(dev, "%s: registers recovery", __func__); + + if ((!priv->regmap) || IS_ERR(priv->regmap)) { + ret = -ENOMEM; + dev_err(dev, "%s register map not ready: %d\n", __func__, ret); + return ret; + } + + regcache_cache_only(priv->regmap, false); + ret = regcache_sync(priv->regmap); + if (ret != 0) { + dev_err(dev, "Failed to restore register map: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct dev_pm_ops mcu_dev_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(mcu_suspend, mcu_resume) +}; +#endif + +int gpio_mcu_register(struct spi_device *spi) +{ + struct mcu_gpio_chip *chip = NULL; + struct vehicle_spi *vehicle_spi; + int ret; + + if (!g_gpio_mcu_chip) { + g_gpio_mcu_chip = devm_kzalloc(&spi->dev, sizeof(struct mcu_gpio_chip), + GFP_KERNEL); + if (!g_gpio_mcu_chip) + return -ENOMEM; + } + + chip = g_gpio_mcu_chip; + vehicle_spi = spi_get_drvdata(spi); + vehicle_spi->gpio_mcu = chip; + + chip->regmap = devm_regmap_init(&spi->dev, &vehicle_regmap_spi, + &spi->dev, &mcu_regmap_config); + if (IS_ERR(chip->regmap)) { + ret = PTR_ERR(chip->regmap); + dev_err(&spi->dev, "Failed to allocate register map: %d\n", ret); + goto err_exit; + } + + pr_info("%s successfully\n", __func__); + return 0; + +err_exit: + return ret; +} +EXPORT_SYMBOL_GPL(gpio_mcu_register); + +static int gpio_mcu_probe(struct platform_device *pdev) +{ + struct mcu_gpio_chip *chip; + struct device_node *np = pdev->dev.of_node; + int ret; + int i; + + if (!g_gpio_mcu_chip) { + g_gpio_mcu_chip = devm_kzalloc(&pdev->dev, sizeof(struct mcu_gpio_chip), + GFP_KERNEL); + if (!g_gpio_mcu_chip) + return -ENOMEM; + } + + chip = g_gpio_mcu_chip; + chip->pdev = pdev; + + chip->name = "gpio-mcu"; + chip->gpio_chip = template_chip; + chip->gpio_chip.label = "mcu-gpio"; + chip->gpio_chip.parent = &pdev->dev; + chip->ngpio = (uintptr_t)of_device_get_match_data(&pdev->dev); + chip->gpio_chip.ngpio = chip->ngpio; + + for (i = 0; i < MCU_MAX_REGS; i++) + chip->backup_regs[i] = 0xff; + + if (np) { + chip->reset_gpio_desc = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_IN); + if (IS_ERR_OR_NULL(chip->reset_gpio_desc)) + dev_warn(&pdev->dev, "Failed to request reset-gpio\n"); + else + chip->reset_gpio_irq = gpiod_to_irq(chip->reset_gpio_desc); + } + + /* Add gpiochip */ + ret = devm_gpiochip_add_data(&pdev->dev, &chip->gpio_chip, chip); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to register gpiochip\n"); + goto err_exit; + } + + platform_set_drvdata(pdev, chip); + + pr_info("%s successfully\n", __func__); + + return 0; + +err_exit: + return ret; +} + +static int gpio_mcu_remove(struct platform_device *pdev) +{ + struct mcu_gpio_chip *chip = platform_get_drvdata(pdev); + + pr_info("%s name=%s\n", __func__, chip->name); + + return 0; +} + +static const struct of_device_id mcu_gpio_of_match_table[] = { + { + .compatible = "rockchip,mcu-gpio", + .data = (void *)32, + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mcu_gpio_of_match_table); + +static struct platform_driver gpio_mcu_driver = { + .driver = { + .name = "mcu-gpio", + .of_match_table = mcu_gpio_of_match_table, +#ifdef CONFIG_PM + .pm = &mcu_dev_pm_ops, +#endif + }, + .probe = gpio_mcu_probe, + .remove = gpio_mcu_remove, +}; + +static int __init gpio_mcu_driver_init(void) +{ + return platform_driver_register(&gpio_mcu_driver); +} + +static void __exit gpio_mcu_driver_exit(void) +{ + platform_driver_unregister(&gpio_mcu_driver); +} + +/* it should be later than vehicle spi */ +#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT +fs_initcall(gpio_mcu_driver_init); +#else +module_init(gpio_mcu_driver_init); +#endif +module_exit(gpio_mcu_driver_exit); + +MODULE_AUTHOR("Luo Wei "); +MODULE_DESCRIPTION("GPIO expander driver for rockchip mcu"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/vehicle/vehicle-gpio.c b/drivers/misc/vehicle/vehicle-gpio.c new file mode 100644 index 000000000000..f10ed247e400 --- /dev/null +++ b/drivers/misc/vehicle/vehicle-gpio.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * vehicle-gpio.c -- I2C register interface access for gpio + * + * Copyright (c) 2025-2030 Rockchip Electronics Co., Ltd. + * + * Author: LuoWei + */ + +#include "core.h" + +static int vehicle_gpio_init_io(struct vehicle_gpio *vehicle_gpio) +{ + int err = 0; + struct device *dev = vehicle_gpio->dev; + + vehicle_gpio->gear_gpio_reverse = devm_gpiod_get_optional(dev, "reverse", GPIOD_IN); + if (IS_ERR(vehicle_gpio->gear_gpio_reverse)) { + dev_err(dev, "failed to get gpio reverse\n"); + err = PTR_ERR(vehicle_gpio->gear_gpio_reverse); + } + + vehicle_gpio->gear_gpio_park = devm_gpiod_get_optional(dev, "park", GPIOD_IN); + if (IS_ERR(vehicle_gpio->gear_gpio_park)) { + dev_err(dev, "failed to get gpio park\n"); + err = PTR_ERR(vehicle_gpio->gear_gpio_park); + } + + return err; +} + +static int vehicle_gpio_update_data(struct vehicle *vehicle) +{ + int gear = 0; + int park_value = 0; + int reverse_value = 0; + struct device *dev = vehicle->vehicle_gpio->dev; + + if (vehicle->vehicle_gpio->gear_gpio_park) + park_value = !!gpiod_get_value(vehicle->vehicle_gpio->gear_gpio_park); + + if (vehicle->vehicle_gpio->gear_gpio_reverse) + reverse_value = !!gpiod_get_value(vehicle->vehicle_gpio->gear_gpio_reverse); + + dev_info(dev, "vehicle gpio %d %d\n", park_value, reverse_value); + + if (park_value && reverse_value) + vehicle->vehicle_data.gear = GEAR_2; + else if (!park_value && reverse_value) + vehicle->vehicle_data.gear = GEAR_1; + else if (park_value && !reverse_value) + vehicle->vehicle_data.gear = GEAR_0; + else + vehicle->vehicle_data.gear = GEAR_3; + + vehicle_set_property(VEHICLE_GEAR, 0, vehicle->vehicle_data.gear, 0); + vehicle_set_property(VEHICLE_TURN_SIGNAL, 0, vehicle->vehicle_data.turn, 0); + + dev_info(dev, "gear %u turn %u\n", vehicle->vehicle_data.gear, + vehicle->vehicle_data.turn); + + /* to do others gpio*/ + + return gear; +} + +static void vehicle_gpio_delay_work_func(struct work_struct *work) +{ + struct vehicle_gpio *vehicle_gpio = container_of(work, struct vehicle_gpio, + vehicle_delay_work.work); + struct device *dev = vehicle_gpio->dev; + + vehicle_gpio_update_data(g_vehicle_hw); + + if (vehicle_gpio->use_delay_work) + queue_delayed_work(vehicle_gpio->vehicle_wq, &vehicle_gpio->vehicle_delay_work, + msecs_to_jiffies(1000)); + + dev_info(dev, "%s\n", __func__); +} + +static irqreturn_t vehicle_gpio_irq_handle(int irq, void *_data) +{ + struct vehicle_gpio *vehicle_gpio = _data; + + queue_delayed_work(vehicle_gpio->vehicle_wq, &vehicle_gpio->vehicle_delay_work, + msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} + +static int vehicle_gpio_irq_init(struct vehicle_gpio *vehicle_gpio) +{ + struct device *dev = vehicle_gpio->dev; + int ret; + + vehicle_gpio->irq = platform_get_irq(vehicle_gpio->pdev, 0); + if (vehicle_gpio->irq < 0) { + dev_err(dev, "failed to get irq\n"); + return -ENODEV; + } + ret = devm_request_threaded_irq(dev, vehicle_gpio->irq, + vehicle_gpio_irq_handle, NULL, + IRQF_TRIGGER_HIGH, + dev_name(dev), vehicle_gpio); + + if (ret < 0) { + dev_err(dev, "error: irq %d\n", vehicle_gpio->irq); + return ret; + } + + return 0; +} + +static int gpio_hw_init(struct vehicle *vehicle) +{ + vehicle_gpio_init_io(vehicle->vehicle_gpio); + vehicle->vehicle_gpio->vehicle_wq = + alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM | WQ_FREEZABLE, + "vehicle-gpio-wq"); + mutex_init(&vehicle->vehicle_gpio->wq_lock); + INIT_DELAYED_WORK(&vehicle->vehicle_gpio->vehicle_delay_work, vehicle_gpio_delay_work_func); + + vehicle->vehicle_gpio->use_delay_work = + of_property_read_bool(vehicle->vehicle_gpio->dev->of_node, "use-delay-work"); + if (vehicle->vehicle_gpio->use_delay_work) { + queue_delayed_work(vehicle->vehicle_gpio->vehicle_wq, + &vehicle->vehicle_gpio->vehicle_delay_work, + msecs_to_jiffies(100)); + VEHICLE_DBG("%s: vehicle_gpio->use_delay_work=%d\n", __func__, + vehicle->vehicle_gpio->use_delay_work); + } else { + vehicle_gpio_irq_init(vehicle->vehicle_gpio); + VEHICLE_DBG("%s: vehicle_gpio->use_delay_work=%d\n", __func__, + vehicle->vehicle_gpio->use_delay_work); + } + + return 0; +} + +static int gpio_pm_suspend(struct vehicle *vehicle) +{ + return 0; +} + +static int gpio_pm_resume(struct vehicle *vehicle) +{ + return 0; +} + +struct vehicle_hw_data vehicle_gpio_data = { + .name = "vehicle-gpio", + .vehicle_hw_type = VEHICLE_HW_TYPE_GPIO, + .data_update = vehicle_gpio_update_data, + .hw_init = gpio_hw_init, + .suspend = gpio_pm_suspend, + .resume = gpio_pm_resume, +}; +EXPORT_SYMBOL_GPL(vehicle_gpio_data); + +static int vehicle_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vehicle_gpio *vehicle_gpio; + + if (!pdev) + return -ENOMEM; + + if (g_vehicle_hw == NULL) + return -ENOMEM; + + vehicle_gpio = devm_kzalloc(dev, sizeof(*vehicle_gpio), GFP_KERNEL); + if (vehicle_gpio == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, vehicle_gpio); + vehicle_gpio->hw_data = &vehicle_gpio_data; + vehicle_gpio->dev = dev; + vehicle_gpio->pdev = pdev; + + g_vehicle_hw->vehicle_gpio = vehicle_gpio; + + gpio_hw_init(g_vehicle_hw); + + return 0; +} + +static int vehicle_gpio_remove(struct platform_device *pdev) +{ + struct vehicle_gpio *vehicle_gpio = platform_get_drvdata(pdev); + + destroy_workqueue(vehicle_gpio->vehicle_wq); + return 0; +} + +static const struct of_device_id vehicle_gpio_id[] = { + { .compatible = "rockchip,vehicle-gpio", }, + { .compatible = "rockchip,vehicle-dummy-gpio", }, + {}, +}; + +static struct platform_driver vehicle_gpio_device_driver = { + .probe = vehicle_gpio_probe, + .remove = vehicle_gpio_remove, + .driver = { + .name = "vehicle-gpio", + .of_match_table = vehicle_gpio_id, + } +}; + +static int vehicle_gpio_init(void) +{ + int err; + + err = platform_driver_register(&vehicle_gpio_device_driver); + if (err) + pr_err("Failed to register vehicle driver\n"); + + return err; +} + +static void __exit vehicle_gpio_exit(void) +{ + platform_driver_unregister(&vehicle_gpio_device_driver); +} + +postcore_initcall(vehicle_gpio_init); +module_exit(vehicle_gpio_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/vehicle/vehicle-spi.c b/drivers/misc/vehicle/vehicle-spi.c new file mode 100644 index 000000000000..57d269e94909 --- /dev/null +++ b/drivers/misc/vehicle/vehicle-spi.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * vehicle-spi.c -- I2C register interface access for spi + * + * Copyright (c) 2025-2030 Rockchip Electronics Co., Ltd. + * + * Author: LuoWei + */ + +#include "core.h" +#ifdef CONFIG_VEHICLE_SPI_PROTOCOL +#include "vehicle_spi_protocol.h" +#endif + +static struct completion spi_complete; +#define SPI_TIMEOUT_MS 20 + +static void spi_complete_callback(void *arg) +{ + complete(&spi_complete); +} + +int vehicle_spi_write_slt(struct vehicle *vehicle, const void *txbuf, size_t n) +{ + int ret = -1; + struct spi_device *spi = NULL; + struct spi_transfer t = { + .tx_buf = txbuf, + .len = n, + .bits_per_word = 8, + }; + struct spi_message m; + + mutex_lock(&vehicle->vehicle_spi->wq_lock); + spi = vehicle->vehicle_spi->spi; + reinit_completion(&spi_complete); + spi_message_init(&m); + spi_message_add_tail(&t, &m); + m.complete = spi_complete_callback; + ret = spi_async(spi, &m); + + if (ret) { + dev_err(&spi->dev, "SPI write async error: %d\n", ret); + goto unlock; + } + + if (!wait_for_completion_timeout(&spi_complete, msecs_to_jiffies(SPI_TIMEOUT_MS))) { + dev_err(&spi->dev, "SPI write operation timed out\n"); + goto unlock; + } +unlock: + mutex_unlock(&vehicle->vehicle_spi->wq_lock); + return ret; +} + +int vehicle_spi_read_slt(struct vehicle *vehicle, void *rxbuf, size_t n) +{ + int ret = -1; + struct spi_device *spi = NULL; + struct spi_transfer t = { + .rx_buf = rxbuf, + .len = n, + .bits_per_word = 8, + }; + struct spi_message m; + + mutex_lock(&vehicle->vehicle_spi->wq_lock); + spi = vehicle->vehicle_spi->spi; + reinit_completion(&spi_complete); + spi_message_init(&m); + spi_message_add_tail(&t, &m); + m.complete = spi_complete_callback; + ret = spi_async(spi, &m); + if (ret) { + dev_err(&spi->dev, "SPI read async error: %d\n", ret); + goto unlock; + } + + if (!wait_for_completion_timeout(&spi_complete, msecs_to_jiffies(SPI_TIMEOUT_MS))) { + dev_err(&spi->dev, "SPI read operation timed out\n"); + goto unlock; + } +unlock: + mutex_unlock(&vehicle->vehicle_spi->wq_lock); + return ret; +} + +static int vehicle_spi_update_data(struct vehicle *vehicle) +{ + int i = 0; + unsigned int times = 1, size = 12; + unsigned long us = 0, bytes = 0; + unsigned char *rxbuf = NULL; + ktime_t start_time; + ktime_t end_time; + ktime_t cost_time; + struct device *dev = vehicle->vehicle_spi->dev; + + rxbuf = kzalloc(size, GFP_KERNEL); + + if (!rxbuf) + return -ENOMEM; + + start_time = ktime_get(); + for (i = 0; i < times; i++) +#ifndef CONFIG_VEHICLE_SPI_PROTOCOL + vehicle_spi_read_slt(vehicle, rxbuf, size); +#else + vehicle_analyze_read_data(vehicle, rxbuf, size); +#endif + end_time = ktime_get(); + cost_time = ktime_sub(end_time, start_time); + us = ktime_to_us(cost_time); + + bytes = size * times * 1; + bytes = bytes * 1000 / us; + pr_info("spi read %d*%d cost %ldus speed:%ldKB/S\n", size, times, us, bytes); + print_hex_dump(KERN_ERR, "SPI RX: ", + DUMP_PREFIX_OFFSET, + 16, + 1, + rxbuf, + size, + 1); + + kfree(rxbuf); + vehicle_set_property(VEHICLE_GEAR, 0, vehicle->vehicle_data.gear, 0); + vehicle_set_property(VEHICLE_TURN_SIGNAL, 0, vehicle->vehicle_data.turn, 0); + + dev_info(dev, "gear %u turn %u\n", vehicle->vehicle_data.gear, vehicle->vehicle_data.turn); + + /* to do others spi */ + return 0; +} + + +static void vehicle_spi_delay_work_func(struct work_struct *work) +{ + struct vehicle_spi *vehicle_spi = container_of(work, struct vehicle_spi, + vehicle_delay_work.work); + struct device *dev = vehicle_spi->dev; + + vehicle_spi_update_data(g_vehicle_hw); + + if (vehicle_spi->use_delay_work) + queue_delayed_work(vehicle_spi->vehicle_wq, &vehicle_spi->vehicle_delay_work, + msecs_to_jiffies(1000)); + + dev_info(dev, "%s end\n", __func__); +} + +static irqreturn_t vehicle_spi_irq_handle(int irq, void *_data) +{ + struct vehicle_spi *vehicle_spi = _data; + + queue_delayed_work(vehicle_spi->vehicle_wq, &vehicle_spi->vehicle_delay_work, + msecs_to_jiffies(0)); + + return IRQ_HANDLED; +} + +#if defined(CONFIG_VEHICLE_GPIO_MCU_EXPANDER) && defined(CONFIG_VEHICLE_SPI_PROTOCOL) +static int vehicle_spi_write_data(void *context, unsigned int reg, + unsigned int val) +{ + unsigned char value = 0; + + value = val & 0x0f; + return vehicle_analyze_write_data(g_vehicle_hw, (unsigned char)reg, &value, sizeof(value)); + +} + +static int vehicle_spi_read_data(void *context, unsigned int reg, + unsigned int *val) +{ + return vehicle_analyze_read_reg(g_vehicle_hw, reg, val); +} + +static int vehicle_analyze_update_bits(void *context, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return 0; +} + +const struct regmap_bus vehicle_regmap_spi = { + .reg_write = vehicle_spi_write_data, + .reg_read = vehicle_spi_read_data, + .reg_update_bits = vehicle_analyze_update_bits, +}; +#endif + +static int vehicle_spi_irq_init(struct vehicle_spi *vehicle_spi) +{ + struct device *dev = vehicle_spi->dev; + struct gpio_desc *irq_gpio_desc; + int ret; + + irq_gpio_desc = devm_gpiod_get_optional(dev, "irq", GPIOD_IN); + if (IS_ERR_OR_NULL(irq_gpio_desc)) + dev_warn(dev, "Failed to request irq-gpio\n"); + else { + vehicle_spi->irq = gpiod_to_irq(irq_gpio_desc); + ret = devm_request_threaded_irq(dev, vehicle_spi->irq, + vehicle_spi_irq_handle, NULL, + IRQF_TRIGGER_FALLING, + dev_name(dev), vehicle_spi); + + if (ret < 0) { + dev_err(dev, "error: irq %d\n", vehicle_spi->irq); + gpio_free(vehicle_spi->irq); + return ret; + } + } + + return 0; +} + +static int spi_hw_init(struct vehicle *vehicle) +{ + vehicle->vehicle_spi->vehicle_wq = alloc_ordered_workqueue("%s", + WQ_MEM_RECLAIM | WQ_FREEZABLE, + "vehicle-spi-wq"); + mutex_init(&vehicle->vehicle_spi->wq_lock); + INIT_DELAYED_WORK(&vehicle->vehicle_spi->vehicle_delay_work, + vehicle_spi_delay_work_func); + + vehicle->vehicle_spi->use_delay_work = + of_property_read_bool(vehicle->vehicle_spi->dev->of_node, "use-delay-work"); + + if (vehicle->vehicle_spi->use_delay_work) { + queue_delayed_work(vehicle->vehicle_spi->vehicle_wq, + &vehicle->vehicle_spi->vehicle_delay_work, + msecs_to_jiffies(100)); + VEHICLE_DBG("%s: vehicle_spi->use_delay_work=%d\n", __func__, + vehicle->vehicle_spi->use_delay_work); + } else { + vehicle_spi_irq_init(vehicle->vehicle_spi); + VEHICLE_DBG("%s: vehicle_spi->use_delay_work=%d\n", __func__, + vehicle->vehicle_spi->use_delay_work); + } + + return 0; +} + +static int spi_pm_suspend(struct vehicle *vehicle) +{ + return 0; +} + +static int spi_pm_resume(struct vehicle *vehicle) +{ + return 0; +} + +struct vehicle_hw_data vehicle_spi_data = { + .name = "vehicle-spi", + .vehicle_hw_type = VEHICLE_HW_TYPE_SPI, + .data_update = vehicle_spi_update_data, + .hw_init = spi_hw_init, + .suspend = spi_pm_suspend, + .resume = spi_pm_resume, +}; +EXPORT_SYMBOL_GPL(vehicle_spi_data); + +static ssize_t spi_test_write(struct file *file, + const char __user *buf, size_t n, loff_t *offset) +{ + int argc = 0, i; + char tmp[64]; + char *argv[16]; + char *cmd, *data; + unsigned int id = 0, times = 0, size = 0, cmd_spi = 0; + unsigned long us = 0, bytes = 0; + char *txbuf = NULL; + ktime_t start_time; + ktime_t end_time; + ktime_t cost_time; + + if (n >= sizeof(tmp)) { + pr_info("%s error size > 64\n", __func__); + return -EINVAL; + } + + memset(tmp, 0, sizeof(tmp)); + if (copy_from_user(tmp, buf, n)) + return -EFAULT; + cmd = tmp; + data = tmp; + + memset(argv, 0, sizeof(argv)); + + while (data < (tmp + n)) { + data = strstr(data, " "); + if (!data) + break; + *data = 0; + argv[argc] = ++data; + argc++; + if (argc >= 16) + break; + } + + tmp[n - 1] = 0; + + if (!strcmp(cmd, "write")) { + if (kstrtoint(argv[0], 10, &id) < 0) + return -EFAULT; + + if (kstrtoint(argv[1], 10, ×) < 0) + return -EFAULT; + + if (kstrtoint(argv[2], 10, &size) < 0) + return -EFAULT; + + if (kstrtoint(argv[3], 16, &cmd_spi) < 0) + return -EFAULT; + + txbuf = kzalloc(size, GFP_KERNEL); + if (!txbuf) + return n; + + for (i = 0; i < size; i++) { + if (kstrtoint(argv[4+i], 16, (int *)(txbuf+i)) < 0) + return -EFAULT; + } + + start_time = ktime_get(); + for (i = 0; i < times; i++) +#ifndef CONFIG_VEHICLE_SPI_PROTOCOL + vehicle_spi_write_slt(g_vehicle_hw, txbuf, size); +#else + vehicle_analyze_write_data(g_vehicle_hw, (unsigned char)cmd_spi, + txbuf, size); +#endif + end_time = ktime_get(); + cost_time = ktime_sub(end_time, start_time); + us = ktime_to_us(cost_time); + + bytes = size * times * 1; + bytes = bytes * 1000 / us; + pr_info("spi write %d*%d cost %ldus speed:%ldKB/S\n", size, times, us, bytes); + kfree(txbuf); + } + return n; +} +static const struct file_operations spi_test_fops = { + .write = spi_test_write, +}; + +static struct miscdevice spi_test_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "spi_misc_test", + .fops = &spi_test_fops, +}; + +static int vehicle_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct vehicle_spi *vehicle_spi; + int ret = 0; + int id = 0; + + if (!spi) + return -ENOMEM; + + if (g_vehicle_hw == NULL) + return -ENOMEM; + + vehicle_spi = devm_kzalloc(dev, sizeof(*vehicle_spi), GFP_KERNEL); + if (vehicle_spi == NULL) + return -ENOMEM; + + spi_set_drvdata(spi, vehicle_spi); + + vehicle_spi->hw_data = &vehicle_spi_data; + spi->bits_per_word = 8; + vehicle_spi->dev = dev; + vehicle_spi->spi = spi; + g_vehicle_hw->vehicle_spi = vehicle_spi; + + ret = spi_setup(spi); + if (ret < 0) { + dev_err(dev, "ERR: fail to setup spi\n"); + return -1; + } + + if (device_property_read_u32(&spi->dev, "id", &id)) { + dev_warn(&spi->dev, "fail to get id, default set 0\n"); + id = 0; + } + + init_completion(&spi_complete); + spi_hw_init(g_vehicle_hw); + +#if defined(CONFIG_VEHICLE_GPIO_MCU_EXPANDER) && defined(CONFIG_VEHICLE_SPI_PROTOCOL) + ret = vehicle_analyze_read_reg(g_vehicle_hw, VERSION, &id); + if (ret == 0 && id == VERSION_ID) + gpio_mcu_register(spi); +#endif + + return 0; +} + +static void vehicle_spi_remove(struct spi_device *spi) +{ + struct vehicle_spi *vehicle_spi = spi_get_drvdata(spi); + + destroy_workqueue(vehicle_spi->vehicle_wq); +} + +#ifdef CONFIG_OF +static const struct of_device_id vehicle_spi_id[] = { + { .compatible = "rockchip,vehicle-spi", }, + {}, +}; +#endif + +static struct spi_driver vehicle_spi_device_driver = { + .probe = vehicle_spi_probe, + .remove = vehicle_spi_remove, + .driver = { + .name = "vehicle-spi", + .of_match_table = vehicle_spi_id, + } +}; + +static int vehicle_spi_init(void) +{ + int err; + + misc_register(&spi_test_misc); + err = spi_register_driver(&vehicle_spi_device_driver); + if (err) { + pr_err("Failed to register vehicle spi driver\n"); + misc_deregister(&spi_test_misc); + } + + return err; +} +module_init(vehicle_spi_init); + +static void __exit vehicle_spi_exit(void) +{ + misc_deregister(&spi_test_misc); + spi_unregister_driver(&vehicle_spi_device_driver); +} + +module_exit(vehicle_spi_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/vehicle/vehicle_core.c b/drivers/misc/vehicle/vehicle_core.c new file mode 100644 index 000000000000..5a800e0f88c4 --- /dev/null +++ b/drivers/misc/vehicle/vehicle_core.c @@ -0,0 +1,418 @@ +/* + * Copyright 2018 NXP + * + * 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 "core.h" + +#include "pb_encode.h" +#include "pb_decode.h" +#include "pb.h" +#include "vehiclehalproto.pb.h" +#include "vehicle_protocol_callback.h" +#include "vehicle_core.h" + +#define PROTOCOL_ID 30 + +struct vehicle *g_vehicle_hw; +EXPORT_SYMBOL(g_vehicle_hw); +static struct sock *nlsk; +static int g_user_pid; + +struct vehicle_core_drvdata { + const struct hw_prop_ops *prop_ops; +}; + +/* param in command PWR_REQ */ +enum vehicle_power_request_param { + AP_POWER_REQUEST_PARAM_SHUTDOWN_IMMEDIATELY = 1, + AP_POWER_REQUEST_PARAM_CAN_SLEEP, + AP_POWER_REQUEST_PARAM_SHUTDOWN_ONLY, + AP_POWER_REQUEST_PARAM_SLEEP_IMMEDIATELY, + AP_POWER_REQUEST_PARAM_HIBERNATE_IMMEDIATELY, + AP_POWER_REQUEST_PARAM_CAN_HIBERNATE, +}; + +/* state in command PWR_REQ */ +enum vehicle_power_request_state { + AP_POWER_REQUEST_STATE_ON = 0, + AP_POWER_REQUEST_STATE_SHUTDOWN_PREPARE, + AP_POWER_REQUEST_STATE_CANCEL_SHUTDOWN, + AP_POWER_REQUEST_STATE_FINISHED, +}; + +static struct vehicle_core_drvdata *vehicle_core; +static struct vehicle_property_set property_encode; +static struct vehicle_property_set property_decode; +static struct vehicle_power_req power_req_encode; + +void vehicle_hw_prop_ops_register(const struct hw_prop_ops *prop_ops) +{ + if (!prop_ops) + return; + + if (vehicle_core) + vehicle_core->prop_ops = prop_ops; +} +EXPORT_SYMBOL_GPL(vehicle_hw_prop_ops_register); + +static int vehicle_send_message_core(u32 prop, u32 area, u32 value) +{ + if (vehicle_core && vehicle_core->prop_ops && + vehicle_core->prop_ops->set_control_commands) + vehicle_core->prop_ops->set_control_commands(prop, area, value); + return 0; +} + +static int send_usrmsg(char *pbuf, uint16_t len) +{ + struct sk_buff *nl_skb; + struct nlmsghdr *nlh; + + int ret; + + if (nlsk == NULL || pbuf == NULL) { + pr_err("Invalid parameters nlsk %p pbuf %p\n", nlsk, pbuf); + return -1; + } + + nl_skb = nlmsg_new(len, GFP_ATOMIC); + if (!nl_skb) { + pr_err("netlink alloc failure\n"); + return -1; + } + + nlh = nlmsg_put(nl_skb, 0, 0, 0, len, 0); + if (nlh == NULL) { + pr_err("nlmsg_put failaure\n"); + nlmsg_free(nl_skb); + return -1; + } + + memcpy(nlmsg_data(nlh), pbuf, len); + ret = netlink_unicast(nlsk, nl_skb, g_user_pid, MSG_DONTWAIT); + + return ret; +} + +void vehicle_set_property(u16 prop, u8 index, u32 value, u32 param) +{ + char *buffer; + + buffer = kmalloc(128, GFP_KERNEL); + pr_debug("%s: prop %d, index %d, value %d\n", __func__, prop, index, value); + property_encode.value = value; + switch (prop) { + case VEHICLE_FAN_SPEED: + property_encode.prop = HVAC_FAN_SPEED; + property_encode.area_id = HVAC_ALL; + if (property_encode.value != FAN_SPEED_0 && + property_encode.value != FAN_SPEED_1 && + property_encode.value != FAN_SPEED_2 && + property_encode.value != FAN_SPEED_3 && + property_encode.value != FAN_SPEED_4 && + property_encode.value != FAN_SPEED_5) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_FAN_DIRECTION: + property_encode.prop = HVAC_FAN_DIRECTION; + property_encode.area_id = HVAC_ALL; + if (property_encode.value != FAN_DIRECTION_0 && + property_encode.value != FAN_DIRECTION_1 && + property_encode.value != FAN_DIRECTION_2 && + property_encode.value != FAN_DIRECTION_3) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_AUTO_ON: + property_encode.prop = HVAC_AUTO_ON; + property_encode.area_id = (u32)index; + if (property_encode.value != AUTO_ON && property_encode.value != AUTO_OFF) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_AC: + property_encode.prop = HVAC_AC_ON; + property_encode.area_id = HVAC_ALL; + if (property_encode.value != AC_ON && property_encode.value != AC_OFF) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_RECIRC_ON: + property_encode.prop = HVAC_RECIRC_ON; + property_encode.area_id = HVAC_ALL; + if (property_encode.value != RECIRC_ON && property_encode.value != RECIRC_OFF) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_DEFROST: + property_encode.prop = HVAC_DEFROSTER; + property_encode.area_id = (u32)index; + if (property_encode.value != DEFROST_ON && property_encode.value != DEFROST_OFF) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_AC_TEMP: + property_encode.prop = HVAC_TEMPERATURE_SET; + property_encode.area_id = (u32)index; + break; + case VEHICLE_HVAC_POWER_ON: + property_encode.prop = HVAC_POWER_ON; + property_encode.area_id = (u32)index; + if (property_encode.value != HVAC_ON && property_encode.value != HVAC_OFF) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_SEAT_TEMPERATURE: + property_encode.prop = HVAC_SEAT_TEMPERATURE; + property_encode.area_id = (u32)index; + if (property_encode.value != SEAT_TEMP_0 && + property_encode.value != SEAT_TEMP_1 && + property_encode.value != SEAT_TEMP_2 && + property_encode.value != SEAT_TEMP_3) { + pr_err("input value is not correct, please type correct one\n"); + goto exit; + } + break; + case VEHICLE_GEAR: + property_encode.prop = GEAR_SELECTION; + if (value == VEHICLE_GEAR_DRIVE) + property_encode.value = VEHICLE_GEAR_DRIVE_CLIENT; + else if (value == VEHICLE_GEAR_REVERSE) + property_encode.value = VEHICLE_GEAR_REVERSE_CLIENT; + else if (value == VEHICLE_GEAR_PARKING) + property_encode.value = VEHICLE_GEAR_PARK_CLIENT; + break; + case VEHICLE_TURN_SIGNAL: + property_encode.prop = TURN_SIGNAL_STATE; + break; + case VEHICLE_POWER_STATE_REQ: + if (value != AP_POWER_REQUEST_STATE_ON && + value != AP_POWER_REQUEST_STATE_SHUTDOWN_PREPARE && + value != AP_POWER_REQUEST_STATE_CANCEL_SHUTDOWN && + value != AP_POWER_REQUEST_STATE_FINISHED) { + pr_err("AP_POWER_STATE_REQ: invalid state\n"); + goto exit; + } + if (param != AP_POWER_REQUEST_PARAM_SHUTDOWN_IMMEDIATELY && + param != AP_POWER_REQUEST_PARAM_CAN_SLEEP && + param != AP_POWER_REQUEST_PARAM_SHUTDOWN_ONLY && + param != AP_POWER_REQUEST_PARAM_SLEEP_IMMEDIATELY && + param != AP_POWER_REQUEST_PARAM_HIBERNATE_IMMEDIATELY && + param != AP_POWER_REQUEST_PARAM_CAN_HIBERNATE) { + pr_err("AP_POWER_STATE_REQ: invalid param\n"); + goto exit; + } + + power_req_encode.prop = AP_POWER_STATE_REQ; + power_req_encode.state = value; + power_req_encode.param = param; + break; + default: + pr_err("property %d is not supported\n", prop); + } + + pb_ostream_t stream; + + stream = pb_ostream_from_buffer(buffer, 128); + + emulator_EmulatorMessage send_message = {}; + + send_message.msg_type = emulator_MsgType_SET_PROPERTY_CMD; + send_message.has_status = true; + send_message.status = emulator_Status_RESULT_OK; + if (prop == VEHICLE_POWER_STATE_REQ) { + send_message.value.funcs.encode = &encode_power_state_callback; + send_message.value.arg = &power_req_encode; + } else { + send_message.value.funcs.encode = &encode_value_callback; + send_message.value.arg = &property_encode; + } + if (!pb_encode(&stream, emulator_EmulatorMessage_fields, &send_message)) + pr_err("vehicle protocol encode fail\n"); + send_usrmsg(buffer, stream.bytes_written); +exit: + kfree(buffer); +} +EXPORT_SYMBOL_GPL(vehicle_set_property); + +static void netlink_rcv_msg(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = NULL; + char *umsg = NULL; + char *buffer; + bool status; + size_t len; + int i; + emulator_EmulatorMessage emulator_message; + + buffer = kmalloc(128, GFP_KERNEL); + if (skb->len >= nlmsg_total_size(0)) { + nlh = nlmsg_hdr(skb); + g_user_pid = nlh->nlmsg_pid; + umsg = NLMSG_DATA(nlh); + len = nlh->nlmsg_len - NLMSG_LENGTH(0); + if (umsg) { + for (i = 0; i < len; i++) + pr_debug("%s raw byte %d %d\n", __func__, i, umsg[i]); + memcpy(buffer, umsg, len); + pb_istream_t stream = pb_istream_from_buffer(buffer, len); + + emulator_message.prop.funcs.decode = &decode_prop_callback; + emulator_message.config.funcs.decode = &decode_config_callback; + emulator_message.value.funcs.decode = &decode_value_callback; + emulator_message.value.arg = &property_decode; + + status = pb_decode(&stream, emulator_EmulatorMessage_fields, + &emulator_message); + if (!status) + pr_err("pb_decode failed\n"); + + vehicle_send_message_core(property_decode.prop, property_decode.area_id, + property_decode.value); + } + } + kfree(buffer); +} + +static void create_netlink_vehicle(void) +{ + struct netlink_kernel_cfg cfg = { + .input = netlink_rcv_msg, + }; + + nlsk = netlink_kernel_create(&init_net, PROTOCOL_ID, &cfg); + if (nlsk == NULL) { + pr_err("netlink_kernel_create error !\n"); + return; + } +} + +static struct vehicle_core_drvdata * +vehicle_get_devtree_pdata(struct device *dev) +{ + struct vehicle_core_drvdata *ddata; + + ddata = devm_kzalloc(dev, + sizeof(*ddata), + GFP_KERNEL); + + if (!ddata) + return ERR_PTR(-ENOMEM); + + return ddata; +} + +static struct vehicle * +vehicle_get_dev_pdata(struct device *dev) +{ + struct vehicle *ddata; + + ddata = devm_kzalloc(dev, + sizeof(*ddata), + GFP_KERNEL); + if (!ddata) + return ERR_PTR(-ENOMEM); + + return ddata; +} + +static int vehicle_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vehicle_core_drvdata *ddata; + + ddata = vehicle_get_devtree_pdata(dev); + if (IS_ERR(ddata)) + return PTR_ERR(ddata); + + g_vehicle_hw = vehicle_get_dev_pdata(dev); + if (IS_ERR(g_vehicle_hw)) + return PTR_ERR(g_vehicle_hw); + + vehicle_core = ddata; + platform_set_drvdata(pdev, ddata); + platform_set_drvdata(pdev, g_vehicle_hw); + + create_netlink_vehicle(); + return 0; +} + +static int vehicle_remove(struct platform_device *pdev) +{ + if (nlsk) + netlink_kernel_release(nlsk); + return 0; +} + +static struct platform_driver vehicle_device_driver = { + .probe = vehicle_probe, + .remove = vehicle_remove, + .driver = { + .name = "vehicle-core", + } +}; +static struct platform_device *core_pdev; + +static int vehicle_init(void) +{ + int err; + + core_pdev = platform_device_alloc("vehicle-core", -1); + if (!core_pdev) { + pr_err("Failed to allocate core vehicle device\n"); + return -ENODEV; + } + + err = platform_device_add(core_pdev); + if (err != 0) { + pr_err("Failed to register core device: %d\n", err); + platform_device_put(core_pdev); + return err; + } + + err = platform_driver_register(&vehicle_device_driver); + if (err) + pr_err("Failed to register vehicle driver\n"); + + return err; +} + +static void __exit vehicle_exit(void) +{ + platform_driver_unregister(&vehicle_device_driver); + platform_device_unregister(core_pdev); +} + +postcore_initcall(vehicle_init); +module_exit(vehicle_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NXP Semiconductor"); +MODULE_DESCRIPTION("VEHICLE core driver"); diff --git a/drivers/misc/vehicle/vehicle_core.h b/drivers/misc/vehicle/vehicle_core.h new file mode 100644 index 000000000000..3a586c0ce75a --- /dev/null +++ b/drivers/misc/vehicle/vehicle_core.h @@ -0,0 +1,388 @@ +/* + * Copyright 2018 NXP + * + * 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 VEHICLE_CORE_H +#define VEHICLE_CORE_H + +#include + +// seat temperature indexes +#define SEAT_TEMP_LEFT_INDEX 1 +#define SEAT_TEMP_RIGHT_INDEX 4 +// seat temperature values +#define SEAT_TEMP_0 0 // off +#define SEAT_TEMP_1 1 +#define SEAT_TEMP_2 2 +#define SEAT_TEMP_3 3 + +#define DEFROST_ON 1 +#define DEFROST_OFF 0 + +#define AC_ON 1 +#define AC_OFF 0 + +#define AUTO_ON 1 +#define AUTO_OFF 0 + +#define HVAC_ON 1 +#define HVAC_OFF 0 + +#define RECIRC_ON 1 +#define RECIRC_OFF 0 + +#define FAN_SPEED_0 1 +#define FAN_SPEED_1 2 +#define FAN_SPEED_2 3 +#define FAN_SPEED_3 4 +#define FAN_SPEED_4 5 +#define FAN_SPEED_5 6 + +#define FAN_DIRECTION_0 1 +#define FAN_DIRECTION_1 2 +#define FAN_DIRECTION_2 3 +#define FAN_DIRECTION_3 6 + +struct vehicle_property_set { + u32 prop; + u32 area_id; + u64 value; +}; + +struct vehicle_power_req { + u32 prop; + u32 state; + u32 param; +}; + +struct hw_prop_ops { + /* send the control commands to hw */ + void (*set_control_commands)(u32 prop, u32 area, u32 value); +}; + +/* areaId defines - begin */ +#define VEHICLE_AREA_SEAT_ROW_1_LEFT 1 /* 0x0001 */ +#define VEHICLE_AREA_SEAT_ROW_1_CENTER 2 /* 0x0002 */ +#define VEHICLE_AREA_SEAT_ROW_1_RIGHT 4 /* 0x0004 */ +#define VEHICLE_AREA_SEAT_ROW_2_LEFT 16 /* 0x0010 */ +#define VEHICLE_AREA_SEAT_ROW_2_CENTER 32 /* 0x0020 */ +#define VEHICLE_AREA_SEAT_ROW_2_RIGHT 64 /* 0x0040 */ +#define VEHICLE_AREA_SEAT_ROW_3_LEFT 256 /* 0x0100 */ +#define VEHICLE_AREA_SEAT_ROW_3_CENTER 512 /* 0x0200 */ +#define VEHICLE_AREA_SEAT_ROW_3_RIGHT 1024 /* 0x0400 */ + +#define HVAC_LEFT VEHICLE_AREA_SEAT_ROW_1_LEFT +#define HVAC_RIGHT VEHICLE_AREA_SEAT_ROW_1_RIGHT +//Due to VHAL migration from hidl to aidl, details in commit message +#define HVAC_ALL VEHICLE_AREA_SEAT_ROW_1_LEFT +/* areaId defines - end */ + +#define HVAC_FAN_SPEED 356517120 +#define HVAC_FAN_DIRECTION 356517121 +#define HVAC_AUTO_ON 354419978 +#define HVAC_AC_ON 354419973 +#define HVAC_RECIRC_ON 354419976 +#define HVAC_DEFROSTER 320865540 +#define HVAC_TEMPERATURE_SET 358614275 +#define HVAC_POWER_ON 354419984 + +#define TURN_SIGNAL_STATE 289408008 +#define GEAR_SELECTION 289408000 +#define CURRENT_GEAR 289408001 + +#define AP_POWER_STATE_REQ 289475072 +#define AP_POWER_STATE_REPORT 289475073 + +#define VEHICLE_GEAR_DRIVE_CLIENT 8 +#define VEHICLE_GEAR_PARK_CLIENT 4 +#define VEHICLE_GEAR_REVERSE_CLIENT 2 + +#define WATCHDOG_ALIVE 290459441 +#define HVAC_SEAT_TEMPERATURE 356517131 +#define DISPLAY_BRIGHTNESS 289409539 +#define INFO_MAKE 286261505 +#define INFO_MODEL 286261506 +#define POWER_POLICY_REQ 286265121 +#define POWER_POLICY_GROUP_REQ 286265122 +#define CURRENT_POWER_POLICY 286265123 +#define FUEL_DOOR_OPEN 287310600 +#define EV_CHARGE_PORT_OPEN 287310602 +#define EV_CHARGE_PORT_CONNECTED 287310603 +#define PARKING_BRAKE_ON 287310850 +#define PARKING_BRAKE_AUTO_APPLY 287310851 +#define FUEL_LEVEL_LOW 287310853 +#define NIGHT_MODE 287310855 +#define ABS_ACTIVE 287310858 +#define TRACTION_CONTROL_ACTIVE 287310859 +#define SUPPORT_CUSTOMIZE_VENDOR_PERMISSION 287313669 +#define INFO_MODEL_YEAR 289407235 +#define INFO_FUEL_DOOR_LOCATION 289407240 +#define INFO_EV_PORT_LOCATION 289407241 +#define ENGINE_OIL_LEVEL 289407747 +#define IGNITION_STATE 289408009 +#define HVAC_STEERING_WHEEL_HEAT 289408269 +#define HVAC_TEMPERATURE_DISPLAY_UNITS 289408270 +#define DISTANCE_DISPLAY_UNITS 289408512 +#define TIRE_PRESSURE_DISPLAY_UNITS 289408514 +#define VEHICLE_SPEED_DISPLAY_UNITS 289408517 +#define HEADLIGHTS_STATE 289410560 +#define HIGH_BEAM_LIGHTS_STATE 289410561 +#define FOG_LIGHTS_STATE 289410562 +#define PARKING_BRAKE_AUTO_APPLY 287310851 +#define HAZARD_LIGHTS_STATE 289410563 +#define HEADLIGHTS_SWITCH 289410576 +#define HIGH_BEAM_LIGHTS_SWITCH 289410577 +#define FOG_LIGHTS_SWITCH 289410578 +#define HAZARD_LIGHTS_SWITCH 289410579 +#define CLUSTER_SWITCH_UI 289410868 +#define CLUSTER_REQUEST_DISPLAY 289410871 +#define POWER_POLICY_GROUP_REQ 286265122 +#define CURRENT_POWER_POLICY 286265123 +#define ELECTRONIC_TOLL_COLLECTION_CARD_TYPE 289410873 +#define ELECTRONIC_TOLL_COLLECTION_CARD_STATUS 289410874 +#define INFO_FUEL_TYPE 289472773 +#define INFO_EV_CONNECTOR_TYPE 289472775 +#define INFO_DRIVER_SEAT 356516106 +#define INFO_EXTERIOR_DIMENSIONS 289472779 +#define INFO_MULTI_EV_PORT_LOCATIONS 289472780 +#define HW_KEY_INPUT 289475088 +#define HW_ROTARY_INPUT 289475104 +#define HW_CUSTOM_INPUT 289475120 +#define EVS_SERVICE_REQUEST 289476368 +#define CLUSTER_DISPLAY_STATE 289476405 +#define EPOCH_TIME 290457094 +#define VHAL_HEARTBEAT 290459443 +#define WHEEL_TICK 290521862 +#define INFO_FUEL_CAPACITY 291504388 +#define INFO_EV_BATTERY_CAPACITY 291504390 +#define PERF_ODOMETER 291504644 +#define PERF_VEHICLE_SPEED 291504647 +#define PERF_STEERING_ANGLE 291504649 +#define PERF_REAR_STEERING_ANGLE 291504656 +#define ENGINE_OIL_TEMP 291504900 +#define ENGINE_RPM 291504901 +#define FUEL_LEVEL 291504903 +#define RANGE_REMAINING 291504904 +#define EV_BATTERY_LEVEL 291504905 +#define EV_BATTERY_INSTANTANEOUS_CHARGE_RATE 291504908 +#define ENV_OUTSIDE_TEMPERATURE 291505923 +#define HVAC_TEMPERATURE_VALUE_SUGGESTION 291570965 +#define STORAGE_ENCRYPTION_BINDING_SEED 292554247 +#define CLUSTER_NAVIGATION_STATE 292556600 +#define INITIAL_USER_INFO 299896583 +#define SWITCH_USER 299896584 +#define CREATE_USER 299896585 +#define REMOVE_USER 299896586 +#define USER_IDENTIFICATION_ASSOCIATION 299896587 +#define WATCHDOG_TERMINATED_PROCESS 299896626 +#define CLUSTER_REPORT_STATE 299896630 +#define HVAC_ELECTRIC_DEFROSTER_ON 320865556 +#define WINDOW_LOCK 320867268 +#define VEHICLE_MAP_SERVICE 299895808 +#define WINDOW_POS 322964416 +#define HVAC_MAX_AC_ON 354419974 +#define HVAC_MAX_DEFROST_ON 354419975 +#define HVAC_DUAL_ON 354419977 +#define HVAC_AUTO_RECIRC_ON 354419986 +#define HVAC_SEAT_VENTILATION 356517139 +#define HVAC_ELECTRIC_DEFROSTER_ON 320865556 +#define SEAT_OCCUPANCY 356518832 +#define HVAC_FAN_DIRECTION_AVAILABLE 356582673 +#define DOOR_LOCK 371198722 +#define DOOR_POS 373295872 +#define TIRE_PRESSURE 392168201 +#define CRITICALLY_LOW_TIRE_PRESSURE 392168202 +#define FRONT_FOG_LIGHTS_STATE 289410875 +#define FRONT_FOG_LIGHTS_SWITCH 289410876 +#define REAR_FOG_LIGHTS_STATE 289410877 +#define REAR_FOG_LIGHTS_SWITCH 289410878 +#define EV_CHARGE_CURRENT_DRAW_LIMIT 291508031 +#define EV_CHARGE_PERCENT_LIMIT 291508032 +#define EV_CHARGE_STATE 289410881 +#define EV_CHARGE_SWITCH 287313730 +#define EV_CHARGE_TIME_REMAINING 289410883 +#define EV_REGENERATIVE_BRAKING_STATE 289410884 +#define TRAILER_PRESENT 289410885 +#define VEHICLE_CURB_WEIGHT 289410886 +#define READING_LIGHTS_SWITCH 356519684 +#define SEAT_BELT_HEIGHT_POS 356518787 +#define WINDOW_MOVE 322964417 +#define MIRROR_AUTO_TILT_ENABLED 337644359 +#define SEAT_FORE_AFT_POS 356518789 +#define EV_BATTERY_DISPLAY_UNITS 289408515 +#define SEAT_HEIGHT_MOVE 356518796 +#define INFO_VIN 286261504 +#define SEAT_HEADREST_ANGLE_POS 356518807 +#define SEAT_HEADREST_ANGLE_MOVE 356518808 +#define ENGINE_COOLANT_TEMP 291504897 +#define MIRROR_LOCK 287312708 +#define HVAC_ACTUAL_FAN_SPEED_RPM 356517135 +#define SEAT_BELT_HEIGHT_MOVE 356518788 +#define SEAT_FORE_AFT_MOVE 356518790 +#define SEAT_BACKREST_ANGLE_2_MOVE 356518794 +#define SEAT_HEIGHT_POS 356518795 +#define SEAT_TILT_POS 356518799 +#define SEAT_DEPTH_MOVE 356518798 +#define SEAT_LUMBAR_FORE_AFT_POS 356518801 +#define SEAT_EASY_ACCESS_ENABLED 354421661 +#define SEAT_LUMBAR_FORE_AFT_MOVE 356518802 +#define SEAT_AIRBAG_ENABLED 354421662 +#define AUTOMATIC_EMERGENCY_BRAKING_ENABLED 287313920 +#define SEAT_LUMBAR_SIDE_SUPPORT_POS 356518803 +#define SEAT_LUMBAR_SIDE_SUPPORT_MOVE 356518804 +#define SEAT_MEMORY_SELECT 356518784 +#define HANDS_ON_DETECTION_DRIVER_STATE 289411095 +#define SEAT_HEADREST_HEIGHT_MOVE 356518806 +#define SEAT_HEADREST_FORE_AFT_POS 356518809 +#define MIRROR_FOLD 287312709 +#define SEAT_HEADREST_FORE_AFT_MOVE 356518810 +#define GLOVE_BOX_LOCKED 354421745 +#define SEAT_TILT_MOVE 356518800 +#define MIRROR_Z_POS 339741504 +#define HVAC_SIDE_MIRROR_HEAT 339739916 +#define SEAT_LUMBAR_VERTICAL_POS 356518817 +#define SEAT_FOOTWELL_LIGHTS_SWITCH 356518812 +#define WINDSHIELD_WIPERS_STATE 322964422 +#define SEAT_DEPTH_POS 356518797 +#define SEAT_HEADREST_HEIGHT_POS_V2 356518820 +#define EV_CURRENT_BATTERY_CAPACITY 291504909 +#define EV_BRAKE_REGENERATION_LEVEL 289408012 +#define SEAT_LUMBAR_VERTICAL_MOVE 356518818 +#define SEAT_WALK_IN_POS 356518819 +#define SEAT_BELT_BUCKLED 354421634 +#define SEAT_BACKREST_ANGLE_1_POS 356518791 +#define LANE_KEEP_ASSIST_STATE 289411081 +#define LANE_CENTERING_ASSIST_ENABLED 287313930 +#define SEAT_BACKREST_ANGLE_1_MOVE 356518792 +#define SEAT_BACKREST_ANGLE_2_POS 356518793 +#define MIRROR_AUTO_FOLD_ENABLED 337644358 +#define BLIND_SPOT_WARNING_ENABLED 287313924 +#define EV_STOPPING_MODE 289408013 +#define STEERING_WHEEL_LIGHTS_STATE 289410828 +#define MIRROR_Z_MOVE 339741505 +#define SEAT_CUSHION_SIDE_SUPPORT_POS 356518815 +#define MIRROR_Y_MOVE 339741507 +#define AUTOMATIC_EMERGENCY_BRAKING_STATE 289411073 +#define FORWARD_COLLISION_WARNING_ENABLED 287313922 +#define SEAT_MEMORY_SET 356518785 +#define HANDS_ON_DETECTION_WARNING 289411096 +#define WINDSHIELD_WIPERS_PERIOD 322964421 +#define SEAT_FOOTWELL_LIGHTS_STATE 356518811 +#define DOOR_CHILD_LOCK_ENABLED 371198723 +#define DOOR_MOVE 373295873 +#define WINDSHIELD_WIPERS_SWITCH 322964423 +#define STEERING_WHEEL_DEPTH_POS 289410016 +#define GLOVE_BOX_DOOR_POS 356518896 +#define STEERING_WHEEL_HEIGHT_POS 289410018 +#define STEERING_WHEEL_THEFT_LOCK_ENABLED 287312868 +#define SEAT_CUSHION_SIDE_SUPPORT_MOVE 356518816 +#define CABIN_LIGHTS_STATE 289410817 +#define STEERING_WHEEL_EASY_ACCESS_ENABLED 287312870 +#define CABIN_LIGHTS_SWITCH 289410818 +#define STEERING_WHEEL_HEIGHT_MOVE 289410019 +#define STEERING_WHEEL_LIGHTS_SWITCH 289410829 +#define FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME 287311364 +#define MIRROR_Y_POS 339741506 +#define LOCATION_CHARACTERIZATION 289410064 +#define EMERGENCY_LANE_KEEP_ASSIST_STATE 289411086 +#define CRUISE_CONTROL_TYPE 289411088 +#define CRUISE_CONTROL_STATE 289411089 +#define STEERING_WHEEL_LOCKED 287312869 +#define ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP 289411092 +#define ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE 289411093 +#define HANDS_ON_DETECTION_ENABLED 287313942 +#define FORWARD_COLLISION_WARNING_STATE 289411075 +#define STEERING_WHEEL_DEPTH_MOVE 289410017 +#define EMERGENCY_LANE_KEEP_ASSIST_ENABLED 287313933 +#define GENERAL_SAFETY_REGULATION_COMPLIANCE 289410887 +#define LANE_CENTERING_ASSIST_STATE 289411084 +#define CRUISE_CONTROL_ENABLED 287313935 +#define PERF_VEHICLE_SPEED_DISPLAY 291504648 +#define HVAC_TEMPERATURE_CURRENT 358614274 +#define LANE_KEEP_ASSIST_ENABLED 287313928 +#define READING_LIGHTS_STATE 356519683 +#define CRUISE_CONTROL_TARGET_SPEED 291508243 +#define ENGINE_IDLE_AUTO_STOP_ENABLED 287310624 +#define BLIND_SPOT_WARNING_STATE 339742725 +#define LANE_DEPARTURE_WARNING_ENABLED 287313926 +#define FUEL_VOLUME_DISPLAY_UNITS 289408513 +#define LANE_DEPARTURE_WARNING_STATE 289411079 + +/* (int)(0x104 | VehiclePropertyGroup:: + * VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL); + */ +#define VENDOR_EXTENSION_STRING_PROPERTY 554696964 +/* (int)(0x101 | VehiclePropertyGroup:: + * VENDOR | VehiclePropertyType::BOOLEAN | VehicleArea::DOOR); + */ +#define VENDOR_EXTENSION_BOOLEAN_PROPERTY 639631617 +/* (int)(0x102 | VehiclePropertyGroup:: + * VENDOR | VehiclePropertyType::FLOAT | VehicleArea::SEAT); + */ +#define VENDOR_EXTENSION_FLOAT_PROPERTY 627048706 +/* (int)(0x103 | VehiclePropertyGroup:: + * VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW); + */ +#define VENDOR_EXTENSION_INT_PROPERTY 591397123 +/* 0x1111 | VehiclePropertyGroup:: + * VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; + */ +#define kMixedTypePropertyForTest 568332561 + +/*vehicle_event_type: stateType in command VSTATE*/ +enum vehicle_event_type { + VEHICLE_AC = 0, + VEHICLE_AUTO_ON, + VEHICLE_AC_TEMP, + VEHICLE_FAN_SPEED, + VEHICLE_FAN_DIRECTION, + VEHICLE_RECIRC_ON, + VEHICLE_HEATER, + VEHICLE_DEFROST, + VEHICLE_HVAC_POWER_ON, + VEHICLE_MUTE, + VEHICLE_VOLUME, + VEHICLE_DOOR, + VEHICLE_RVC, + VEHICLE_LIGHT, + VEHICLE_GEAR, + VEHICLE_TURN_SIGNAL, + VEHICLE_POWER_STATE_REQ, + VEHICLE_SEAT_TEMPERATURE, + VEHICLE_UNSUPPORTED = -1, +}; + +/*vehicle_event_gear: stateValue of type VEHICLE_GEAR*/ +enum vehicle_event_gear { + VEHICLE_GEAR_NONE = 0, + VEHICLE_GEAR_PARKING, + VEHICLE_GEAR_REVERSE, + VEHICLE_GEAR_NEUTRAL, + VEHICLE_GEAR_DRIVE, + VEHICLE_GEAR_FIRST, + VEHICLE_GEAR_SECOND, + VEHICLE_GEAR_SPORT, + VEHICLE_GEAR_MANUAL_1, + VEHICLE_GEAR_MANUAL_2, + VEHICLE_GEAR_MANUAL_3, + VEHICLE_GEAR_MANUAL_4, + VEHICLE_GEAR_MANUAL_5, + VEHICLE_GEAR_MANUAL_6, +}; + +extern struct net init_net; +extern void vehicle_hw_prop_ops_register(const struct hw_prop_ops *prop_ops); +extern void vehicle_set_property(u16 prop, u8 index, u32 value, u32 param); + + +#endif diff --git a/drivers/misc/vehicle/vehicle_dummy_hw.c b/drivers/misc/vehicle/vehicle_dummy_hw.c new file mode 100644 index 000000000000..90d43bb30766 --- /dev/null +++ b/drivers/misc/vehicle/vehicle_dummy_hw.c @@ -0,0 +1,916 @@ +/* + * Copyright 2018 NXP + * + * 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 "vehicle_core.h" +#include "core.h" + +/* Miscellaneous external connector */ +#define EXTCON_VEHICLE_RPMSG_REGISTER 58 +#define EXTCON_VEHICLE_RPMSG_EVENT 59 +//VEHICLE is in state parking +#define GEAR_0 1 +//VEHICLE is in state reverse +#define GEAR_1 2 +//VEHICLE is in state neutral +#define GEAR_3 3 +//VEHICLE is in state driver +#define GEAR_2 4 +// no turn signal +#define TURN_0 0 +// left turn signal +#define TURN_1 1 +// right turn signal +#define TURN_2 2 + +#define POWER_REQ_STATE_ON 0 +#define POWER_REQ_STATE_SHUTDOWN_PREPARE 1 +#define POWER_REQ_STATE_CANCEL_SHUTDOWN 2 +#define POWER_REQ_STATE_FINISHED 3 + +#define POWER_REQ_PARAM_SHUTDOWN_IMMEDIATELY 1 +#define POWER_REQ_PARAM_CAN_SLEEP 2 +#define POWER_REQ_PARAM_SHUTDOWN_ONLY 3 +#define POWER_REQ_PARAM_SLEEP_IMMEDIATELY 4 +#define POWER_REQ_PARAM_HIBERNATE_IMMEDIATELY 5 +#define POWER_REQ_PARAM_CAN_HIBERNATE 6 + +// temperature set from hardware on Android OREO and PIE uses below indexes +#define AC_TEMP_LEFT_INDEX 1 +#define AC_TEMP_RIGHT_INDEX 4 + +// temperature set from APP on Android PIE uses below indexes +#define PIE_AC_TEMP_LEFT_INDEX 49 +#define PIE_AC_TEMP_RIGHT_INDEX 68 + +#ifdef CONFIG_EXTCON +static const unsigned int rk_vehicle_dummy_extcon_register_cables[] = { + EXTCON_VEHICLE_RPMSG_REGISTER, + EXTCON_NONE, +}; +static const unsigned int rk_vehicle_dummy_extcon_event_cables[] = { + EXTCON_VEHICLE_RPMSG_EVENT, + EXTCON_NONE, +}; +static struct extcon_dev *rg_edev; +static struct extcon_dev *ev_edev; +#endif + +static struct class *vehicle_dummy_class; + +static void mcu_set_control_commands(u32 prop, u32 area, u32 value) +{ + pr_debug("%s: prop %d, area %d, value %d\n", __func__, prop, area, value); + switch (prop) { + case HVAC_FAN_SPEED: + pr_info("set fan speed with value %d\n", value); + g_vehicle_hw->vehicle_data.fan_speed = value; + break; + case HVAC_FAN_DIRECTION: + pr_info("set fan direction with value %d\n", value); + g_vehicle_hw->vehicle_data.fan_direction = value; + break; + case HVAC_AUTO_ON: + pr_info("set fan auto on with value %d\n", value); + g_vehicle_hw->vehicle_data.auto_on = value; + break; + case HVAC_AC_ON: + pr_info("set fan ac on with value %d\n", value); + g_vehicle_hw->vehicle_data.ac_on = value; + break; + case HVAC_RECIRC_ON: + pr_info("set fan recirc on with value %d\n", value); + g_vehicle_hw->vehicle_data.recirc_on = value; + break; + case HVAC_DEFROSTER: + pr_info("set defroster index %d with value %d\n", area, value); + if (area == 1) + g_vehicle_hw->vehicle_data.defrost_left = value; + else + g_vehicle_hw->vehicle_data.defrost_right = value; + break; + case HVAC_TEMPERATURE_SET: + pr_info("set temp index %d with value %d\n", area, value); + if (area == AC_TEMP_LEFT_INDEX) + g_vehicle_hw->vehicle_data.temp_left = value; + else if (area == AC_TEMP_RIGHT_INDEX) + g_vehicle_hw->vehicle_data.temp_right = value; + break; + case HVAC_POWER_ON: + pr_info("set hvac power on with value %d\n", value); + g_vehicle_hw->vehicle_data.hvac_on = value; + break; + case AP_POWER_STATE_REPORT: + pr_info("receive power state report with value %d\n", value); + break; + case AP_POWER_STATE_REQ: + // Proper action is TBD + break; + case WATCHDOG_ALIVE: + case DISPLAY_BRIGHTNESS: + // Proper action is TBD + break; + case HVAC_SEAT_TEMPERATURE: + pr_info("set seat temperature index %d with value %d\n", area, value); + if (area == SEAT_TEMP_LEFT_INDEX) + g_vehicle_hw->vehicle_data.seat_temp_left = value; + else if (area == SEAT_TEMP_RIGHT_INDEX) + g_vehicle_hw->vehicle_data.seat_temp_right = value; + else + pr_err("unknown index: %d:%d:%d!\n", prop, area, value); + break; + case GEAR_SELECTION: + case TURN_SIGNAL_STATE: + case CURRENT_GEAR: + // GEAR is handled in mxc vehicle driver + break; + case INFO_MAKE: + case INFO_MODEL: + case POWER_POLICY_REQ: + case FUEL_DOOR_OPEN: + case EV_CHARGE_PORT_OPEN: + case EV_CHARGE_PORT_CONNECTED: + case PARKING_BRAKE_ON: + case FUEL_LEVEL_LOW: + case NIGHT_MODE: + case ABS_ACTIVE: + case TRACTION_CONTROL_ACTIVE: + case SUPPORT_CUSTOMIZE_VENDOR_PERMISSION: + case INFO_MODEL_YEAR: + case INFO_FUEL_DOOR_LOCATION: + case INFO_EV_PORT_LOCATION: + case ENGINE_OIL_LEVEL: + case IGNITION_STATE: + case HVAC_STEERING_WHEEL_HEAT: + case HVAC_TEMPERATURE_DISPLAY_UNITS: + case DISTANCE_DISPLAY_UNITS: + case TIRE_PRESSURE_DISPLAY_UNITS: + case VEHICLE_SPEED_DISPLAY_UNITS: + case HEADLIGHTS_STATE: + case HIGH_BEAM_LIGHTS_STATE: + case FOG_LIGHTS_STATE: + case PARKING_BRAKE_AUTO_APPLY: + case HAZARD_LIGHTS_STATE: + case HEADLIGHTS_SWITCH: + case HIGH_BEAM_LIGHTS_SWITCH: + case FOG_LIGHTS_SWITCH: + case HAZARD_LIGHTS_SWITCH: + case CLUSTER_SWITCH_UI: + case CLUSTER_REQUEST_DISPLAY: + case POWER_POLICY_GROUP_REQ: + case CURRENT_POWER_POLICY: + case ELECTRONIC_TOLL_COLLECTION_CARD_TYPE: + case ELECTRONIC_TOLL_COLLECTION_CARD_STATUS: + case INFO_FUEL_TYPE: + case INFO_EV_CONNECTOR_TYPE: + case INFO_DRIVER_SEAT: + case INFO_EXTERIOR_DIMENSIONS: + case INFO_MULTI_EV_PORT_LOCATIONS: + case HW_KEY_INPUT: + case HW_ROTARY_INPUT: + case HW_CUSTOM_INPUT: + case EVS_SERVICE_REQUEST: + case CLUSTER_DISPLAY_STATE: + case EPOCH_TIME: + case VHAL_HEARTBEAT: + case WHEEL_TICK: + case INFO_FUEL_CAPACITY: + case INFO_EV_BATTERY_CAPACITY: + case PERF_ODOMETER: + case PERF_VEHICLE_SPEED: + case PERF_STEERING_ANGLE: + case PERF_REAR_STEERING_ANGLE: + case ENGINE_OIL_TEMP: + case ENGINE_RPM: + case FUEL_LEVEL: + case RANGE_REMAINING: + case EV_BATTERY_LEVEL: + case EV_BATTERY_INSTANTANEOUS_CHARGE_RATE: + case ENV_OUTSIDE_TEMPERATURE: + case HVAC_TEMPERATURE_VALUE_SUGGESTION: + case STORAGE_ENCRYPTION_BINDING_SEED: + case CLUSTER_NAVIGATION_STATE: + case INITIAL_USER_INFO: + case SWITCH_USER: + case CREATE_USER: + case REMOVE_USER: + case USER_IDENTIFICATION_ASSOCIATION: + case WATCHDOG_TERMINATED_PROCESS: + case CLUSTER_REPORT_STATE: + case WINDOW_LOCK: + case VEHICLE_MAP_SERVICE: + case WINDOW_POS: + case HVAC_MAX_AC_ON: + case HVAC_MAX_DEFROST_ON: + case HVAC_DUAL_ON: + case HVAC_AUTO_RECIRC_ON: + case HVAC_SEAT_VENTILATION: + case HVAC_ELECTRIC_DEFROSTER_ON: + case SEAT_OCCUPANCY: + case HVAC_FAN_DIRECTION_AVAILABLE: + case DOOR_LOCK: + case DOOR_POS: + case TIRE_PRESSURE: + case CRITICALLY_LOW_TIRE_PRESSURE: + case FRONT_FOG_LIGHTS_STATE: + case FRONT_FOG_LIGHTS_SWITCH: + case REAR_FOG_LIGHTS_STATE: + case REAR_FOG_LIGHTS_SWITCH: + case EV_CHARGE_CURRENT_DRAW_LIMIT: + case EV_CHARGE_PERCENT_LIMIT: + case EV_CHARGE_STATE: + case EV_CHARGE_SWITCH: + case EV_CHARGE_TIME_REMAINING: + case EV_REGENERATIVE_BRAKING_STATE: + case TRAILER_PRESENT: + case VEHICLE_CURB_WEIGHT: + // Proper action is TBD + break; + case VENDOR_EXTENSION_STRING_PROPERTY: + case VENDOR_EXTENSION_BOOLEAN_PROPERTY: + case VENDOR_EXTENSION_FLOAT_PROPERTY: + case VENDOR_EXTENSION_INT_PROPERTY: + case READING_LIGHTS_SWITCH: + case SEAT_BELT_HEIGHT_POS: + case WINDOW_MOVE: + case MIRROR_AUTO_TILT_ENABLED: + case SEAT_FORE_AFT_POS: + case EV_BATTERY_DISPLAY_UNITS: + case SEAT_HEIGHT_MOVE: + case INFO_VIN: + case SEAT_HEADREST_ANGLE_POS: + case SEAT_HEADREST_ANGLE_MOVE: + case ENGINE_COOLANT_TEMP: + case MIRROR_LOCK: + case HVAC_ACTUAL_FAN_SPEED_RPM: + case SEAT_BELT_HEIGHT_MOVE: + case SEAT_FORE_AFT_MOVE: + case SEAT_BACKREST_ANGLE_2_MOVE: + case SEAT_HEIGHT_POS: + case SEAT_TILT_POS: + case SEAT_DEPTH_MOVE: + case SEAT_LUMBAR_FORE_AFT_POS: + case SEAT_EASY_ACCESS_ENABLED: + case SEAT_LUMBAR_FORE_AFT_MOVE: + case SEAT_AIRBAG_ENABLED: + case AUTOMATIC_EMERGENCY_BRAKING_ENABLED: + case SEAT_LUMBAR_SIDE_SUPPORT_POS: + case SEAT_LUMBAR_SIDE_SUPPORT_MOVE: + case SEAT_MEMORY_SELECT: + case HANDS_ON_DETECTION_DRIVER_STATE: + case SEAT_HEADREST_HEIGHT_MOVE: + case SEAT_HEADREST_FORE_AFT_POS: + case MIRROR_FOLD: + case SEAT_HEADREST_FORE_AFT_MOVE: + case GLOVE_BOX_LOCKED: + case SEAT_TILT_MOVE: + case MIRROR_Z_POS: + case HVAC_SIDE_MIRROR_HEAT: + case SEAT_LUMBAR_VERTICAL_POS: + case SEAT_FOOTWELL_LIGHTS_SWITCH: + case WINDSHIELD_WIPERS_STATE: + case SEAT_DEPTH_POS: + case SEAT_HEADREST_HEIGHT_POS_V2: + case EV_CURRENT_BATTERY_CAPACITY: + case EV_BRAKE_REGENERATION_LEVEL: + case SEAT_LUMBAR_VERTICAL_MOVE: + case SEAT_WALK_IN_POS: + case SEAT_BELT_BUCKLED: + case SEAT_BACKREST_ANGLE_1_POS: + case LANE_KEEP_ASSIST_STATE: + case LANE_CENTERING_ASSIST_ENABLED: + case SEAT_BACKREST_ANGLE_1_MOVE: + case SEAT_BACKREST_ANGLE_2_POS: + case MIRROR_AUTO_FOLD_ENABLED: + case BLIND_SPOT_WARNING_ENABLED: + case EV_STOPPING_MODE: + case STEERING_WHEEL_LIGHTS_STATE: + case MIRROR_Z_MOVE: + case SEAT_CUSHION_SIDE_SUPPORT_POS: + case MIRROR_Y_MOVE: + case AUTOMATIC_EMERGENCY_BRAKING_STATE: + case FORWARD_COLLISION_WARNING_ENABLED: + case SEAT_MEMORY_SET: + case HANDS_ON_DETECTION_WARNING: + case WINDSHIELD_WIPERS_PERIOD: + case SEAT_FOOTWELL_LIGHTS_STATE: + case DOOR_CHILD_LOCK_ENABLED: + case DOOR_MOVE: + case WINDSHIELD_WIPERS_SWITCH: + case STEERING_WHEEL_DEPTH_POS: + case GLOVE_BOX_DOOR_POS: + case STEERING_WHEEL_HEIGHT_POS: + case STEERING_WHEEL_THEFT_LOCK_ENABLED: + case SEAT_CUSHION_SIDE_SUPPORT_MOVE: + case CABIN_LIGHTS_STATE: + case STEERING_WHEEL_EASY_ACCESS_ENABLED: + case CABIN_LIGHTS_SWITCH: + case STEERING_WHEEL_HEIGHT_MOVE: + case STEERING_WHEEL_LIGHTS_SWITCH: + case FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME: + case MIRROR_Y_POS: + case LOCATION_CHARACTERIZATION: + case EMERGENCY_LANE_KEEP_ASSIST_STATE: + case CRUISE_CONTROL_TYPE: + case CRUISE_CONTROL_STATE: + case STEERING_WHEEL_LOCKED: + case ADAPTIVE_CRUISE_CONTROL_TARGET_TIME_GAP: + case ADAPTIVE_CRUISE_CONTROL_LEAD_VEHICLE_MEASURED_DISTANCE: + case HANDS_ON_DETECTION_ENABLED: + case FORWARD_COLLISION_WARNING_STATE: + case STEERING_WHEEL_DEPTH_MOVE: + case EMERGENCY_LANE_KEEP_ASSIST_ENABLED: + case GENERAL_SAFETY_REGULATION_COMPLIANCE: + case LANE_CENTERING_ASSIST_STATE: + case CRUISE_CONTROL_ENABLED: + case PERF_VEHICLE_SPEED_DISPLAY: + case HVAC_TEMPERATURE_CURRENT: + case LANE_KEEP_ASSIST_ENABLED: + case READING_LIGHTS_STATE: + case CRUISE_CONTROL_TARGET_SPEED: + case ENGINE_IDLE_AUTO_STOP_ENABLED: + case BLIND_SPOT_WARNING_STATE: + case LANE_DEPARTURE_WARNING_ENABLED: + case FUEL_VOLUME_DISPLAY_UNITS: + case LANE_DEPARTURE_WARNING_STATE: + case kMixedTypePropertyForTest: + // Proper action is TBD + break; + default: + pr_err("this type is not correct: %d:%d:%d!\n", prop, area, value); + } +} + +static ssize_t turn_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.turn); +} + +/* echo 0/1/2(none/left/right) > /sys/devices/platform/vehicle-dummy/turn*/ +static ssize_t turn_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 turn; + + if (!size) + return -EINVAL; + turn = strtoul(buf, NULL, 10); + if (turn != TURN_0 && turn != TURN_1 && turn != TURN_2) { + pr_err("input value is not correct, please type correct one\n"); + return -EINVAL; + } + if (turn != g_vehicle_hw->vehicle_data.turn) { + g_vehicle_hw->vehicle_data.turn = turn; + vehicle_set_property(VEHICLE_TURN_SIGNAL, 0, turn, 0); + } + return size; +} +static DEVICE_ATTR_RW(turn); + +static ssize_t gear_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.gear); +} + +/*echo 1/2/4(parking/reverse/drive) > /sys/devices/platform/vehicle-dummy/gear*/ +static ssize_t gear_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 gear; + + if (!size) + return -EINVAL; + gear = strtoul(buf, NULL, 10); + if (gear != g_vehicle_hw->vehicle_data.gear) { + g_vehicle_hw->vehicle_data.gear = gear; + vehicle_set_property(VEHICLE_GEAR, 0, gear, 0); + if (gear != GEAR_0 && gear != GEAR_1 && gear != GEAR_2) { + pr_err("input value is not correct, please type correct one\n"); + return -EINVAL; + } +#ifdef CONFIG_EXTCON + if (gear == VEHICLE_GEAR_DRIVE) + extcon_set_state_sync(ev_edev, EXTCON_VEHICLE_RPMSG_EVENT, 0); + else if (gear == VEHICLE_GEAR_REVERSE) + extcon_set_state_sync(ev_edev, EXTCON_VEHICLE_RPMSG_EVENT, 1); +#endif + } + return size; +} + +static DEVICE_ATTR_RW(gear); + +static ssize_t temp_left_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", g_vehicle_hw->vehicle_data.temp_left); +} + +/*echo 1100713529 > /sys/devices/platform/vehicle-dummy/temp_left*/ +static ssize_t temp_left_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 temp; + + if (!size) + return -EINVAL; + temp = strtoul(buf, NULL, 10); + if (temp != g_vehicle_hw->vehicle_data.temp_left) { + g_vehicle_hw->vehicle_data.temp_left = temp; + vehicle_set_property(VEHICLE_AC_TEMP, AC_TEMP_LEFT_INDEX, temp, 0); + } + return size; +} + +static DEVICE_ATTR_RW(temp_left); + +static ssize_t temp_right_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", g_vehicle_hw->vehicle_data.temp_right); +} + +/*echo 1100713529 > /sys/devices/platform/vehicle-dummy/temp_right*/ +static ssize_t temp_right_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 temp; + + if (!size) + return -EINVAL; + temp = strtoul(buf, NULL, 10); + if (temp != g_vehicle_hw->vehicle_data.temp_right) { + g_vehicle_hw->vehicle_data.temp_right = temp; + vehicle_set_property(VEHICLE_AC_TEMP, AC_TEMP_RIGHT_INDEX, temp, 0); + } + return size; +} + +static DEVICE_ATTR_RW(temp_right); + +static ssize_t seat_temp_left_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", g_vehicle_hw->vehicle_data.seat_temp_left); +} + +/*echo 0/1/2/3 > /sys/devices/platform/vehicle-dummy/seat_temp_left*/ +static ssize_t seat_temp_left_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 seat_temp; + + if (!size) + return -EINVAL; + seat_temp = strtoul(buf, NULL, 10); + + if (seat_temp != g_vehicle_hw->vehicle_data.seat_temp_left) { + g_vehicle_hw->vehicle_data.seat_temp_left = seat_temp; + vehicle_set_property(VEHICLE_SEAT_TEMPERATURE, SEAT_TEMP_LEFT_INDEX, seat_temp, 0); + } + return size; +} + +static DEVICE_ATTR_RW(seat_temp_left); + +static ssize_t seat_temp_right_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", g_vehicle_hw->vehicle_data.seat_temp_right); +} + +/*echo 0/1/2/3 > /sys/devices/platform/vehicle-dummy/seat_temp_right*/ +static ssize_t seat_temp_right_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 seat_temp; + + if (!size) + return -EINVAL; + seat_temp = strtoul(buf, NULL, 10); + if (seat_temp != SEAT_TEMP_0 && seat_temp != SEAT_TEMP_1 && + seat_temp != SEAT_TEMP_2 && seat_temp != SEAT_TEMP_3) { + pr_err("input value is not correct, please type correct one\n"); + return -EINVAL; + } + if (seat_temp != g_vehicle_hw->vehicle_data.seat_temp_right) { + g_vehicle_hw->vehicle_data.seat_temp_right = seat_temp; + vehicle_set_property(VEHICLE_SEAT_TEMPERATURE, SEAT_TEMP_RIGHT_INDEX, seat_temp, 0); + } + return size; +} + +static DEVICE_ATTR_RW(seat_temp_right); + +static ssize_t fan_direction_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.fan_direction); +} + +/*echo 1/2/3/6 > /sys/devices/platform/vehicle-dummy/fan_direction*/ +static ssize_t fan_direction_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 fan_direction; + + if (!size) + return -EINVAL; + fan_direction = strtoul(buf, NULL, 10); + + if (fan_direction != g_vehicle_hw->vehicle_data.fan_direction) { + g_vehicle_hw->vehicle_data.fan_direction = fan_direction; + vehicle_set_property(VEHICLE_FAN_DIRECTION, 0, fan_direction, 0); + } + return size; +} + +static DEVICE_ATTR_RW(fan_direction); + +static ssize_t fan_speed_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.fan_speed); +} + +/*echo 1/2/3/4/5/6 > /sys/devices/platform/vehicle-dummy/fan_speed*/ +static ssize_t fan_speed_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 fan_speed; + + if (!size) + return -EINVAL; + fan_speed = strtoul(buf, NULL, 10); + + if (fan_speed != g_vehicle_hw->vehicle_data.fan_speed) { + g_vehicle_hw->vehicle_data.fan_speed = fan_speed; + vehicle_set_property(VEHICLE_FAN_SPEED, 0, fan_speed, 0); + } + return size; +} + +static DEVICE_ATTR_RW(fan_speed); + +static ssize_t defrost_left_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.defrost_left); +} + +/*echo 0/1 > /sys/devices/platform/vehicle-dummy/defrost_left*/ +static ssize_t defrost_left_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 defrost; + + if (!size) + return -EINVAL; + + defrost = strtoul(buf, NULL, 10); + + if (defrost != g_vehicle_hw->vehicle_data.defrost_left) { + g_vehicle_hw->vehicle_data.defrost_left = defrost; + vehicle_set_property(VEHICLE_DEFROST, 1, defrost, 0); + } + return size; +} + +static DEVICE_ATTR_RW(defrost_left); + +static ssize_t defrost_right_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.defrost_right); +} + +/*echo 0/1 > /sys/devices/platform/vehicle-dummy/defrost_right*/ +static ssize_t defrost_right_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 defrost; + + if (!size) + return -EINVAL; + + defrost = strtoul(buf, NULL, 10); + if (defrost != DEFROST_ON && defrost != DEFROST_OFF) { + pr_err("input value is not correct, please type correct one\n"); + return -EINVAL; + } + if (defrost != g_vehicle_hw->vehicle_data.defrost_right) { + g_vehicle_hw->vehicle_data.defrost_right = defrost; + vehicle_set_property(VEHICLE_DEFROST, 2, defrost, 0); + } + return size; +} + +static DEVICE_ATTR_RW(defrost_right); + +static ssize_t ac_on_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.ac_on); +} + +/*echo 0/1 > /sys/devices/platform/vehicle-dummy/ac_on*/ +static ssize_t ac_on_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 ac_on; + + if (!size) + return -EINVAL; + + ac_on = strtoul(buf, NULL, 10); + + if (ac_on != g_vehicle_hw->vehicle_data.ac_on) { + g_vehicle_hw->vehicle_data.ac_on = ac_on; + vehicle_set_property(VEHICLE_AC, 0, ac_on, 0); + } + return size; +} + +static DEVICE_ATTR_RW(ac_on); + +static ssize_t auto_on_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.auto_on); +} + +/*echo 0/1 > /sys/devices/platform/vehicle-dummy/auto_on*/ +static ssize_t auto_on_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 auto_on; + + if (!size) + return -EINVAL; + + auto_on = strtoul(buf, NULL, 10); + + if (auto_on != g_vehicle_hw->vehicle_data.auto_on) { + g_vehicle_hw->vehicle_data.auto_on = auto_on; + vehicle_set_property(VEHICLE_AUTO_ON, VEHICLE_AREA_SEAT_ROW_1_LEFT, + auto_on, 0); + vehicle_set_property(VEHICLE_AUTO_ON, VEHICLE_AREA_SEAT_ROW_1_RIGHT, + auto_on, 0); + vehicle_set_property(VEHICLE_AUTO_ON, VEHICLE_AREA_SEAT_ROW_2_LEFT, + auto_on, 0); + vehicle_set_property(VEHICLE_AUTO_ON, VEHICLE_AREA_SEAT_ROW_2_RIGHT, + auto_on, 0); + vehicle_set_property(VEHICLE_AUTO_ON, VEHICLE_AREA_SEAT_ROW_2_CENTER, + auto_on, 0); + } + return size; +} + +static DEVICE_ATTR_RW(auto_on); + +static ssize_t hvac_on_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.hvac_on); +} + +/*echo 0/1 > /sys/devices/platform/vehicle-dummy/hvac_on*/ +static ssize_t hvac_on_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 hvac_on; + + if (!size) + return -EINVAL; + + hvac_on = strtoul(buf, NULL, 10); + + if (hvac_on != g_vehicle_hw->vehicle_data.hvac_on) { + g_vehicle_hw->vehicle_data.hvac_on = hvac_on; + vehicle_set_property(VEHICLE_HVAC_POWER_ON, VEHICLE_AREA_SEAT_ROW_1_LEFT, + hvac_on, 0); + vehicle_set_property(VEHICLE_HVAC_POWER_ON, VEHICLE_AREA_SEAT_ROW_1_RIGHT, + hvac_on, 0); + } + return size; +} + +static DEVICE_ATTR_RW(hvac_on); + +static ssize_t recirc_on_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", g_vehicle_hw->vehicle_data.recirc_on); +} + +/* echo 0/1 > /sys/devices/platform/vehicle-dummy/recirc_on*/ +static ssize_t recirc_on_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + u32 recirc_on; + + if (!size) + return -EINVAL; + + recirc_on = strtoul(buf, NULL, 10); + + if (recirc_on != g_vehicle_hw->vehicle_data.recirc_on) { + g_vehicle_hw->vehicle_data.recirc_on = recirc_on; + vehicle_set_property(VEHICLE_RECIRC_ON, 0, recirc_on, 0); + } + return size; +} + +static DEVICE_ATTR_RW(recirc_on); + +static ssize_t power_req_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u %u\n", g_vehicle_hw->vehicle_data.power_req_state, + g_vehicle_hw->vehicle_data.power_req_param); +} + +/* echo "1 1" > /sys/devices/platform/vehicle-dummy/power_req */ +static ssize_t power_req_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + char *ret; + u32 state; + u32 param; + + if (size < 4) { + pr_err("input command format is not correct, please type command like this: \"1 1\"\n"); + return -EINVAL; + } + + state = strtoul(buf, NULL, 10); + ret = strrchr(buf, ' '); + param = strtoul(ret + 1, NULL, 10); + + if (state != POWER_REQ_STATE_ON && + state != POWER_REQ_STATE_SHUTDOWN_PREPARE && + state != POWER_REQ_STATE_CANCEL_SHUTDOWN && + state != POWER_REQ_STATE_FINISHED) { + pr_err("input power request state is not correct, please type correct one\n"); + return -EINVAL; + } + + if (param != POWER_REQ_PARAM_SHUTDOWN_IMMEDIATELY && + param != POWER_REQ_PARAM_CAN_SLEEP && + param != POWER_REQ_PARAM_SHUTDOWN_ONLY && + param != POWER_REQ_PARAM_SLEEP_IMMEDIATELY && + param != POWER_REQ_PARAM_HIBERNATE_IMMEDIATELY && + param != POWER_REQ_PARAM_CAN_HIBERNATE) { + pr_err("input power request param is not correct, please type correct one\n"); + return -EINVAL; + } + + g_vehicle_hw->vehicle_data.power_req_state = state; + g_vehicle_hw->vehicle_data.power_req_param = param; + vehicle_set_property(VEHICLE_POWER_STATE_REQ, 0, state, param); + pr_info("power control with state: %d, param: %d\n", state, param); + return size; +} + +static DEVICE_ATTR_RW(power_req); + +static const struct hw_prop_ops hw_prop_mcu_ops = { + .set_control_commands = mcu_set_control_commands, +}; + +static int vehicle_dummy_hw_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct vehicle_dummy *vehicle_dummy; + int err; + + if (IS_ERR(g_vehicle_hw)) + return PTR_ERR(g_vehicle_hw); + + vehicle_dummy = devm_kzalloc(dev, sizeof(*vehicle_dummy), GFP_KERNEL); + if (vehicle_dummy == NULL) + return -ENOMEM; + + platform_set_drvdata(pdev, vehicle_dummy); + + vehicle_dummy_class = class_create(THIS_MODULE, "vehicle_dummy_hw"); + if (IS_ERR(vehicle_dummy_class)) { + dev_err(dev, "failed to create class.\n"); + return PTR_ERR(vehicle_dummy_class); + } + + err = device_create_file(dev, &dev_attr_recirc_on) || + device_create_file(dev, &dev_attr_hvac_on) || + device_create_file(dev, &dev_attr_auto_on) || + device_create_file(dev, &dev_attr_ac_on) || + device_create_file(dev, &dev_attr_defrost_right) || + device_create_file(dev, &dev_attr_defrost_left) || + device_create_file(dev, &dev_attr_fan_speed) || + device_create_file(dev, &dev_attr_fan_direction) || + device_create_file(dev, &dev_attr_temp_left) || + device_create_file(dev, &dev_attr_temp_right) || + device_create_file(dev, &dev_attr_gear) || + device_create_file(dev, &dev_attr_power_req) || + device_create_file(dev, &dev_attr_seat_temp_left) || + device_create_file(dev, &dev_attr_seat_temp_right) || + device_create_file(dev, &dev_attr_turn); + if (err) + return err; + + vehicle_hw_prop_ops_register(&hw_prop_mcu_ops); + +#ifdef CONFIG_EXTCON + rg_edev = devm_extcon_dev_allocate(dev, rk_vehicle_dummy_extcon_register_cables); + if (IS_ERR(rg_edev)) + dev_err(dev, "failed to allocate extcon device\n"); + + err = devm_extcon_dev_register(dev, rg_edev); + if (err < 0) + dev_err(dev, "failed to register extcon device\n"); + + ev_edev = devm_extcon_dev_allocate(dev, rk_vehicle_dummy_extcon_event_cables); + if (IS_ERR(ev_edev)) + dev_err(dev, "failed to allocate extcon device\n"); + + err = devm_extcon_dev_register(dev, ev_edev); + if (err < 0) + dev_err(dev, "failed to register extcon device\n"); +#endif + + return 0; +} + +static int vehicle_dummy_hw_remove(struct platform_device *pdev) +{ + class_destroy(vehicle_dummy_class); + + return 0; +} + +static struct platform_driver vehicle_dummy_hw_driver = { + .probe = vehicle_dummy_hw_probe, + .remove = vehicle_dummy_hw_remove, + .driver = { + .name = "vehicle-dummy-hw", + } +}; + +static struct platform_device *dummy_pdev; + +static int vehicle_dummy_init(void) +{ + int err; + + dummy_pdev = platform_device_alloc("vehicle-dummy-hw", -1); + if (!dummy_pdev) { + pr_err("Failed to allocate dummy vehicle device\n"); + return -ENODEV; + } + + err = platform_device_add(dummy_pdev); + if (err != 0) { + pr_err("Failed to register dummy regulator device: %d\n", err); + platform_device_put(dummy_pdev); + return err; + } + + err = platform_driver_register(&vehicle_dummy_hw_driver); + if (err) { + pr_err("Failed to register dummy vehicle driver\n"); + platform_device_unregister(dummy_pdev); + return err; + } + return 0; +} + +static void __exit vehicle_dummy_exit(void) +{ + platform_driver_unregister(&vehicle_dummy_hw_driver); + platform_device_unregister(dummy_pdev); +} + +late_initcall(vehicle_dummy_init); +module_exit(vehicle_dummy_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NXP Semiconductor"); +MODULE_DESCRIPTION("VEHICLE DUMMY HW"); diff --git a/drivers/misc/vehicle/vehicle_protocol_callback.c b/drivers/misc/vehicle/vehicle_protocol_callback.c new file mode 100644 index 000000000000..8a639a59656b --- /dev/null +++ b/drivers/misc/vehicle/vehicle_protocol_callback.c @@ -0,0 +1,336 @@ +/* + * Copyright 2018 NXP + * + * 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 "pb.h" +#include "pb_encode.h" +#include "pb_decode.h" +#include "vehicle_core.h" +#include "vehiclehalproto.pb.h" +#include "vehicle_protocol_callback.h" + +//VehiclePropertyType +#define VEHICLEPROPERTYTYPE_STRING 1048576 +#define VEHICLEPROPERTYTYPE_BOOLEAN 2097152 +#define VEHICLEPROPERTYTYPE_INT32 4194304 +#define VEHICLEPROPERTYTYPE_INT32_VEC 4259840 +#define VEHICLEPROPERTYTYPE_INT64 5242880 +#define VEHICLEPROPERTYTYPE_INT64_VEC 5308416 +#define VEHICLEPROPERTYTYPE_FLOAT 6291456 +#define VEHICLEPROPERTYTYPE_FLOAT_VEC 6356992 +#define VEHICLEPROPERTYTYPE_BYTES 7340032 +#define VEHICLEPROPERTYTYPE_MIXED 14680064 + + +bool decode_prop_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + emulator_VehiclePropGet propget; + + if (!pb_decode(stream, emulator_VehiclePropGet_fields, &propget)) { + pr_info("%s decode failed\n", __func__); + return false; + } + + return true; +} + +bool decode_config_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + emulator_VehiclePropConfig propconfigure; + + propconfigure.area_configs.funcs.decode = &decode_area_configs_callback; + propconfigure.config_array.funcs.decode = &decode_config_array_callback; + propconfigure.config_string.funcs.decode = &decode_config_string_callback; + + if (!pb_decode(stream, emulator_VehiclePropGet_fields, &propconfigure)) + return false; + + return true; +} + +bool decode_int32_values_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + uint64_t value; + + if (!pb_decode_svarint(stream, &value)) + return false; + *(u32 *)*arg = (u32)value; + return true; +} + +bool decode_int64_values_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + uint64_t value; + + if (!pb_decode_svarint(stream, &value)) + return false; + *(u64 *)*arg = (u64)value; + return true; +} + +bool decode_float_values_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + uint32_t value; + + if (!pb_decode_fixed32(stream, &value)) { + pr_info("float_values_callback failed\n"); + return false; + } + + *(u32 *)*arg = value; + return true; +} + +bool decode_value_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) +{ + struct vehicle_property_set *data = (struct vehicle_property_set *)(*arg); + emulator_VehiclePropValue propvalue; + + propvalue.int32_values.funcs.decode = &decode_int32_values_callback; + propvalue.int32_values.arg = &data->value; + propvalue.float_values.funcs.decode = &decode_float_values_callback; + propvalue.float_values.arg = &data->value; + propvalue.string_value.funcs.decode = &decode_config_string_callback; + propvalue.string_value.arg = &data->value; + propvalue.int64_values.funcs.decode = &decode_int64_values_callback; + propvalue.int64_values.arg = &data->value; + // Callback list must be extended if vhal starts to + // using new property variable type. + + if (!pb_decode(stream, emulator_VehiclePropValue_fields, &propvalue)) + return false; + + data->prop = propvalue.prop; + data->area_id = propvalue.area_id; + + return true; +} + +bool decode_area_configs_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + emulator_VehicleAreaConfig vehicle_area; + + if (!pb_decode(stream, emulator_VehicleAreaConfig_fields, &vehicle_area)) + return false; + return true; +} + +bool decode_config_array_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + uint64_t value; + + if (!pb_decode_varint(stream, &value)) + return false; + return true; +} + +bool decode_config_string_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) +{ + char *buffer; + + buffer = kmalloc(1024, GFP_KERNEL); + if (!buffer) { + pr_warn("Failed allocating memory for decode\n"); + return false; + } + + if (stream->bytes_left >= 1024) { + kfree(buffer); + return false; + } + + if (!pb_read(stream, buffer, stream->bytes_left)) { + kfree(buffer); + return false; + } + + kfree(buffer); + + return true; +} + +bool encode_prop_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + emulator_VehiclePropGet propget; + + //need fill arg emulator_VehiclePropGet if have this filed + if (!pb_encode(stream, emulator_VehiclePropGet_fields, &propget)) { + pr_info("%s encode failed\n", __func__); + return false; + } + + return true; +} + +bool encode_area_configs_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + emulator_VehicleAreaConfig vehicle_area; + + if (!pb_encode(stream, emulator_VehicleAreaConfig_fields, &vehicle_area)) + return false; + return true; +} + +bool encode_config_array_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + return pb_encode_tag_for_field(stream, field) && + pb_encode_fixed32(stream, *arg); +} + +bool encode_config_string_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + return pb_encode_tag_for_field(stream, field) && + pb_encode_string(stream, *arg, strlen(*arg)); +} + +bool encode_config_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) +{ + emulator_VehiclePropConfig propconfigure; + + propconfigure.area_configs.funcs.encode = &encode_area_configs_callback; + propconfigure.config_array.funcs.encode = &encode_config_array_callback; + propconfigure.config_string.funcs.encode = &encode_config_string_callback; + + if (!pb_encode(stream, emulator_VehiclePropGet_fields, &propconfigure)) + return false; + + return true; +} + +bool encode_int32_values_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + u32 *value = (u32 *)*arg; + + if (!pb_encode_tag_for_field(stream, field)) + return false; + + return pb_encode_svarint(stream, *value); +} + +bool encode_power_state_value_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + u32 *value = (u32 *)*arg; + + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!pb_encode_svarint(stream, *value)) + return false; + value++; + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!pb_encode_svarint(stream, *value)) + return false; + + return true; +} + +bool encode_int64_values_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + u64 *value = (u64 *)*arg; + + if (!pb_encode_tag_for_field(stream, field)) + return false; + return pb_encode_svarint(stream, *value); +} + +bool encode_fix32_values_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + if (!pb_encode_tag_for_field(stream, field)) + return false; + return pb_encode_fixed32(stream, (u32 *)*arg); +} + +bool encode_power_state_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + struct vehicle_power_req *data = (struct vehicle_power_req *)(*arg); + emulator_VehiclePropValue propvalue = {}; + + propvalue.prop = data->prop; + propvalue.has_value_type = true; + propvalue.has_timestamp = true; + propvalue.timestamp = 0; +#ifndef CONFIG_VEHICLE_DRIVER_OREO + propvalue.has_status = true; + propvalue.status = 0; +#endif + propvalue.int32_values.funcs.encode = &encode_power_state_value_callback; + propvalue.int32_values.arg = &data->state; + propvalue.value_type = VEHICLEPROPERTYTYPE_INT32; + + pb_encode_tag_for_field(stream, field); + if (!pb_encode_submessage(stream, emulator_VehiclePropValue_fields, &propvalue)) { + pr_info("%s encode submessage failed\n", __func__); + return false; + } + return true; +} + +bool encode_value_callback(pb_ostream_t *stream, const pb_field_t *field, + void * const *arg) +{ + struct vehicle_property_set *data = (struct vehicle_property_set *)(*arg); + emulator_VehiclePropValue propvalue = {}; + + propvalue.prop = data->prop; + propvalue.has_value_type = true; + propvalue.has_timestamp = true; + propvalue.timestamp = 0; + propvalue.has_area_id = true; + propvalue.area_id = data->area_id; +#ifndef CONFIG_VEHICLE_DRIVER_OREO + propvalue.has_status = true; + propvalue.status = 0; +#endif + if (data->prop == HVAC_TEMPERATURE_SET) { + propvalue.float_values.funcs.encode = &encode_fix32_values_callback; + propvalue.float_values.arg = &data->value; + propvalue.value_type = VEHICLEPROPERTYTYPE_FLOAT; + } else if (HVAC_FAN_SPEED == data->prop || HVAC_FAN_DIRECTION == data->prop || + HVAC_AUTO_ON == data->prop || HVAC_AC_ON == data->prop || + HVAC_RECIRC_ON == data->prop || HVAC_POWER_ON == data->prop || + HVAC_DEFROSTER == data->prop || TURN_SIGNAL_STATE == data->prop || + GEAR_SELECTION == data->prop || HVAC_SEAT_TEMPERATURE == data->prop) { + propvalue.int32_values.funcs.encode = &encode_int32_values_callback; + propvalue.int32_values.arg = &data->value; + propvalue.value_type = VEHICLEPROPERTYTYPE_INT32; + } + + //propvalue.int64_values.funcs.encode = &encode_int64_values_callback; + //propvalue.string_value.funcs.encode = &encode_config_string_callback; + //propvalue.bytes_value.funcs.encode = &encode_config_string_callback; + pb_encode_tag_for_field(stream, field); + if (!pb_encode_submessage(stream, emulator_VehiclePropValue_fields, &propvalue)) { + pr_info("%s encode submessage failed\n", __func__); + return false; + } + return true; +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NXP Semiconductor"); + diff --git a/drivers/misc/vehicle/vehicle_protocol_callback.h b/drivers/misc/vehicle/vehicle_protocol_callback.h new file mode 100644 index 000000000000..0610781471d8 --- /dev/null +++ b/drivers/misc/vehicle/vehicle_protocol_callback.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 NXP + * + * 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 VEHICLE_PROTOCOL_CALLBACK_H_ +#define VEHICLE_PROTOCOL_CALLBACK_H_ + +bool decode_prop_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_config_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_value_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_config_string_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_config_array_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_area_configs_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_float_values_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_int64_values_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool decode_int32_values_callback(pb_istream_t *stream, + const pb_field_t *field, + void **arg); +bool encode_value_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_prop_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_area_configs_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_config_array_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_config_string_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_config_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_int32_values_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_int64_values_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_fix32_values_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_power_state_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); +bool encode_power_state_value_callback(pb_ostream_t *stream, + const pb_field_t *field, + void * const *arg); + +#endif diff --git a/drivers/misc/vehicle/vehicle_spi_protocol.c b/drivers/misc/vehicle/vehicle_spi_protocol.c new file mode 100644 index 000000000000..c7ec813795fd --- /dev/null +++ b/drivers/misc/vehicle/vehicle_spi_protocol.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vehicle_spi_protocol.c -- define MCU protocol + * + * Copyright (c) 2023-2028 Rockchip Electronics Co., Ltd. + * + * Author: Tom Song + * + */ +#include "vehicle_spi_protocol.h" + +static unsigned char GetChkSum_CRC8(unsigned char *dptr, unsigned short len) +{ + unsigned char crc = 0; + unsigned short i; + + for (i = 0; i < len; i++) + crc ^= dptr[i]; + return crc; +} + +static int IS_GPIO_CMD(unsigned char cmd) +{ + int ret = ERROR; + + if (cmd <= SET_GPIO_END && cmd >= SET_GPIO_START) + ret = SUCCEED; + else if (cmd <= GET_GPIO_END && cmd >= GET_GPIO_START) + ret = SUCCEED; + else if (cmd <= GPIO_DIR_END && cmd >= GPIO_DIR_START) + ret = SUCCEED; + return ret; +} + +static int IS_REMSG_CORRECT(unsigned char *rxbuf) +{ + int len, ret = ERROR; + + len = rxbuf[1] - 1; + + if (rxbuf[0] == DATE_MCU) { + if (rxbuf[len] == GetChkSum_CRC8(rxbuf, len)) + ret = SUCCEED; + } + + return ret; +} + +static int HandleGPIO(unsigned char *txbuf, unsigned char *rxbuf) +{ + int ret = -1; + + if (rxbuf[2] <= GET_GPIO_END && rxbuf[2] >= GET_GPIO_START) { + if (rxbuf[3] == 1) + ret = -1; + else if (rxbuf[3] == 0) + ret = 0; + } + + if (rxbuf[2] <= SET_GPIO_END && rxbuf[2] >= SET_GPIO_START) { + if (rxbuf[3] == txbuf[3]) + ret = 0; + else + ret = -1; + } + + if (rxbuf[2] <= GPIO_DIR_END && rxbuf[2] >= GPIO_DIR_START) + ret = 0; + + return ret; +} + +static int HandleCanMSG(struct vehicle *device, unsigned char *rxbuf) +{ + int ret = 0; + u16 value = rxbuf[5]; + u16 state = rxbuf[4]; + + switch (rxbuf[3]) { + case VEHICLE_AC: + device->vehicle_data.ac_on = value; + break; + case VEHICLE_AUTO_ON: + device->vehicle_data.auto_on = value; + break; + case VEHICLE_FAN_SPEED: + device->vehicle_data.fan_speed = value; + break; + case VEHICLE_FAN_DIRECTION: + device->vehicle_data.fan_direction = value; + break; + case VEHICLE_RECIRC_ON: + device->vehicle_data.recirc_on = value; + break; + case VEHICLE_GEAR: + device->vehicle_data.gear = value; + break; + case VEHICLE_TURN_SIGNAL: + device->vehicle_data.turn = value; + break; + case VEHICLE_POWER_STATE_REQ: + vehicle_set_property(VEHICLE_POWER_STATE_REQ, 0, state, value); + ret = 1; + break; + default: + ret = -1; + break; + } + if (!ret) + vehicle_set_property(rxbuf[3], 0, value, 0); + return SUCCEED; + +} + +static int HandleOtherMsg(struct vehicle *device, unsigned char *rxbuf) +{ + int ret = -1; + + switch (rxbuf[2]) { + case BOARD: + case CAN_SOC_TO_MCU: + case HEART: + ret = rxbuf[3]; + break; + + case CAN_MCU_TO_SOC: + ret = HandleCanMSG(device, rxbuf); + break; + + default: + break; + } + + return ret; +} + +int vehicle_analyze_read_data(struct vehicle *device, unsigned char *rxbuf, size_t len) +{ + int ret = -1; + + vehicle_spi_read_slt(device, rxbuf, len); + if (IS_REMSG_CORRECT(rxbuf)) { + if (IS_GPIO_CMD(rxbuf[2])) + dev_info(device->vehicle_spi->dev, "read gpio"); + else if (HandleOtherMsg(device, rxbuf) == SUCCEED) + ret = 0; + } + + return ret; +} + +int vehicle_analyze_read_reg(struct vehicle *device, unsigned int reg, unsigned int *val) +{ + unsigned char *txbuf = NULL, *rxbuf = NULL; + int ret = -1; + struct device *dev = device->dev; + + *val = 0; + txbuf = kzalloc(SIZE_DATA, GFP_KERNEL); + if (!txbuf) { + dev_err(dev, "spi write alloc buf size %d fail\n", SIZE_DATA); + goto err_ret; + } + txbuf[0] = DATE_SOC_GET; + txbuf[1] = WRITE_RET_LEN; + txbuf[2] = reg; + txbuf[3] = 0; + txbuf[4] = GetChkSum_CRC8(txbuf, WRITE_RET_LEN-1); + rxbuf = kzalloc(SIZE_DATA, GFP_KERNEL); + if (!rxbuf) + goto err_free_txbuf; + + disable_irq(device->vehicle_spi->irq); + ret = vehicle_spi_write_slt(device, txbuf, WRITE_RET_LEN); + if (ret < 0) + goto err_irq; + ret = vehicle_spi_read_slt(device, rxbuf, WRITE_RET_LEN); + if (ret < 0) + goto err_irq; + + *val = rxbuf[3]; + +err_irq: + enable_irq(device->vehicle_spi->irq); + kfree(rxbuf); +err_free_txbuf: + kfree(txbuf); +err_ret: + return ret; +} + +int vehicle_analyze_write_data(struct vehicle *device, unsigned char cmd, + unsigned char *data, size_t len) +{ + int i, ret = -1; + unsigned char *txbuf = NULL, *rxbuf = NULL; + + if (len + DATA_LEN > SIZE_DATA) + goto err_ret; + + txbuf = kzalloc(SIZE_DATA, GFP_KERNEL); + if (!txbuf) + goto err_ret; + + if (cmd < GET_GPIO_START) + txbuf[0] = DATE_SOC_SET; + else + txbuf[0] = DATE_SOC_GET; + + txbuf[2] = cmd; + for (i = 0; i < len; i++) + txbuf[3 + i] = data[i]; + + len = len + DATA_LEN; + txbuf[1] = len; + txbuf[len - 1] = GetChkSum_CRC8(txbuf, len - 1); + + rxbuf = kzalloc(SIZE_DATA, GFP_KERNEL); + if (!rxbuf) + goto err_free_txbuf; + + disable_irq(device->vehicle_spi->irq); + ret = vehicle_spi_write_slt(device, txbuf, len); + if (ret < 0) + goto err_irq; + ret = vehicle_spi_read_slt(device, rxbuf, WRITE_RET_LEN); + if (ret < 0) + goto err_irq; +#if defined(VEHICLE_DEBUG) + print_hex_dump(KERN_ERR, "SPI RX: ", + DUMP_PREFIX_OFFSET, + 16, + 1, + rxbuf, + WRITE_RET_LEN, + 1); +#endif + + if (IS_REMSG_CORRECT(rxbuf)) { + if (IS_GPIO_CMD(rxbuf[2])) + ret = HandleGPIO(txbuf, rxbuf); + else if (rxbuf[3] == SUCCEED) + ret = 0; + } +err_irq: + enable_irq(device->vehicle_spi->irq); + kfree(rxbuf); +err_free_txbuf: + kfree(txbuf); +err_ret: + return ret; +} + diff --git a/drivers/misc/vehicle/vehicle_spi_protocol.h b/drivers/misc/vehicle/vehicle_spi_protocol.h new file mode 100644 index 000000000000..72305d434d0a --- /dev/null +++ b/drivers/misc/vehicle/vehicle_spi_protocol.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * vehicle_spi_protocol.h -- define MCU protocol + * + * Copyright (c) 2023-2028 Rockchip Electronics Co., Ltd. + * + * Author: Tom Song + * + */ +#ifndef VEHICLE_SPI_PROTOCOL_H +#define VEHICLE_SPI_PROTOCOL_H +#include "core.h" + +#define DATE_SOC_SET 0x91 +#define DATE_SOC_GET 0x90 +#define DATE_MCU 0x80 +#define SIZE_DATA 32 +#define DATA_LEN 4 +#define SET_GPIO_START 0x01 +#define SET_GPIO_END 0x20 +#define GPIO_DIR_OFFSET 0x20 +#define GPIO_DIR_START (SET_GPIO_START + GPIO_DIR_OFFSET) +#define GPIO_DIR_END (SET_GPIO_END + GPIO_DIR_OFFSET) +#define GET_GPIO_START 0x90 +#define GET_GPIO_END 0xCF +#define WRITE_RET_LEN 5 +#define BOARD 0x40 +#define CAN_SOC_TO_MCU 0x41 +#define HEART 0x42 +#define CAN_MCU_TO_SOC 0xd0 +#define VERSION 0x0 +#define VERSION_ID 0x21 + +#define ERROR 0X00 +#define SUCCEED 0X01 + +int vehicle_analyze_write_data(struct vehicle *device, unsigned char cmd, + unsigned char *data, size_t len); +int vehicle_analyze_read_data(struct vehicle *device, unsigned char *rxbuf, size_t len); +int vehicle_analyze_read_reg(struct vehicle *device, unsigned int reg, unsigned int *val); +#endif diff --git a/drivers/misc/vehicle/vehiclehalproto.pb.c b/drivers/misc/vehicle/vehiclehalproto.pb.c new file mode 100644 index 000000000000..3face5a2179d --- /dev/null +++ b/drivers/misc/vehicle/vehiclehalproto.pb.c @@ -0,0 +1,166 @@ +/* + * Copyright 2018 NXP + * + * 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 "vehiclehalproto.pb.h" + +const pb_field_t emulator_VehicleAreaConfig_fields[8] = { + PB_FIELD2(1, INT32, REQUIRED, STATIC, FIRST, + emulator_VehicleAreaConfig, area_id, area_id, 0), + PB_FIELD2(2, SINT32, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, min_int32_value, area_id, 0), + PB_FIELD2(3, SINT32, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, max_int32_value, min_int32_value, 0), + PB_FIELD2(4, SINT64, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, min_int64_value, max_int32_value, 0), + PB_FIELD2(5, SINT64, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, max_int64_value, min_int64_value, 0), + PB_FIELD2(6, FLOAT, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, min_float_value, max_int64_value, 0), + PB_FIELD2(7, FLOAT, OPTIONAL, STATIC, OTHER, + emulator_VehicleAreaConfig, max_float_value, min_float_value, 0), + PB_LAST_FIELD +}; + +const pb_field_t emulator_VehiclePropConfig_fields[12] = { + PB_FIELD2(1, INT32, REQUIRED, STATIC, FIRST, + emulator_VehiclePropConfig, prop, prop, 0), + PB_FIELD2(2, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, access, prop, 0), + PB_FIELD2(3, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, change_mode, access, 0), + PB_FIELD2(4, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, value_type, change_mode, 0), + PB_FIELD2(5, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, supported_areas, value_type, 0), + PB_FIELD2(6, MESSAGE, REPEATED, CALLBACK, OTHER, emulator_VehiclePropConfig, + area_configs, supported_areas, &emulator_VehicleAreaConfig_fields), + PB_FIELD2(7, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, config_flags, area_configs, 0), + PB_FIELD2(8, INT32, REPEATED, CALLBACK, OTHER, + emulator_VehiclePropConfig, config_array, config_flags, 0), + PB_FIELD2(9, STRING, OPTIONAL, CALLBACK, OTHER, + emulator_VehiclePropConfig, config_string, config_array, 0), + PB_FIELD2(10, FLOAT, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, min_sample_rate, config_string, 0), + PB_FIELD2(11, FLOAT, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropConfig, max_sample_rate, min_sample_rate, 0), + PB_LAST_FIELD +}; + +#ifdef CONFIG_VEHICLE_DRIVER_OREO +const pb_field_t emulator_VehiclePropValue_fields[10] = { + PB_FIELD2(1, INT32, REQUIRED, STATIC, FIRST, + emulator_VehiclePropValue, prop, prop, 0), + PB_FIELD2(2, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropValue, value_type, prop, 0), + PB_FIELD2(3, INT64, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropValue, timestamp, value_type, 0), + PB_FIELD2(4, INT32, OPTIONAL, STATIC, OTHER, + emulator_VehiclePropValue, area_id, timestamp, 0), + PB_FIELD2(5, SINT32, REPEATED, CALLBACK, OTHER, + emulator_VehiclePropValue, int32_values, area_id, 0), + PB_FIELD2(6, SINT64, REPEATED, CALLBACK, OTHER, + emulator_VehiclePropValue, int64_values, int32_values, 0), + PB_FIELD2(7, FLOAT, REPEATED, CALLBACK, OTHER, + emulator_VehiclePropValue, float_values, int64_values, 0), + PB_FIELD2(8, STRING, OPTIONAL, CALLBACK, OTHER, + emulator_VehiclePropValue, string_value, float_values, 0), + PB_FIELD2(9, BYTES, OPTIONAL, CALLBACK, OTHER, + emulator_VehiclePropValue, bytes_value, string_value, 0), + PB_LAST_FIELD +}; +#else +const pb_field_t emulator_VehiclePropValue_fields[11] = { + PB_FIELD2(1, INT32, REQUIRED, STATIC, FIRST, emulator_VehiclePropValue, + prop, prop, 0), + PB_FIELD2(2, INT32, OPTIONAL, STATIC, OTHER, emulator_VehiclePropValue, + value_type, prop, 0), + PB_FIELD2(3, INT64, OPTIONAL, STATIC, OTHER, emulator_VehiclePropValue, + timestamp, value_type, 0), + PB_FIELD2(4, INT32, OPTIONAL, STATIC, OTHER, emulator_VehiclePropValue, + area_id, timestamp, 0), + PB_FIELD2(5, SINT32, REPEATED, CALLBACK, OTHER, emulator_VehiclePropValue, + int32_values, area_id, 0), + PB_FIELD2(6, SINT64, REPEATED, CALLBACK, OTHER, emulator_VehiclePropValue, + int64_values, int32_values, 0), + PB_FIELD2(7, FLOAT, REPEATED, CALLBACK, OTHER, emulator_VehiclePropValue, + float_values, int64_values, 0), + PB_FIELD2(8, STRING, OPTIONAL, CALLBACK, OTHER, emulator_VehiclePropValue, + string_value, float_values, 0), + PB_FIELD2(9, BYTES, OPTIONAL, CALLBACK, OTHER, emulator_VehiclePropValue, + bytes_value, string_value, 0), + PB_FIELD2(10, ENUM, OPTIONAL, STATIC, OTHER, emulator_VehiclePropValue, + status, bytes_value, 0), + PB_LAST_FIELD +}; +#endif + +const pb_field_t emulator_VehiclePropGet_fields[3] = { + PB_FIELD2(1, INT32, REQUIRED, STATIC, FIRST, emulator_VehiclePropGet, + prop, prop, 0), + PB_FIELD2(2, INT32, OPTIONAL, STATIC, OTHER, emulator_VehiclePropGet, + area_id, prop, 0), + PB_LAST_FIELD +}; + +const pb_field_t emulator_EmulatorMessage_fields[6] = { + PB_FIELD2(1, ENUM, REQUIRED, STATIC, FIRST, emulator_EmulatorMessage, msg_type, + msg_type, 0), + PB_FIELD2(2, ENUM, OPTIONAL, STATIC, OTHER, emulator_EmulatorMessage, status, + msg_type, 0), + PB_FIELD2(3, MESSAGE, REPEATED, CALLBACK, OTHER, emulator_EmulatorMessage, + prop, status, &emulator_VehiclePropGet_fields), + PB_FIELD2(4, MESSAGE, REPEATED, CALLBACK, OTHER, emulator_EmulatorMessage, + config, prop, &emulator_VehiclePropConfig_fields), + PB_FIELD2(5, MESSAGE, REPEATED, CALLBACK, OTHER, emulator_EmulatorMessage, + value, config, &emulator_VehiclePropValue_fields), + PB_LAST_FIELD +}; + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +STATIC_ASSERT((pb_membersize(emulator_VehiclePropConfig, area_configs) < 65536 +&& pb_membersize(emulator_EmulatorMessage, prop) < 65536 +&& pb_membersize(emulator_EmulatorMessage, config) < 65536 +&& pb_membersize(emulator_EmulatorMessage, value) < 65536), +YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_emulator_VehicleAreaConfig_emulator_\ +VehiclePropConfig_emulator_VehiclePropValue_emulator_VehiclePropGet_emulator_EmulatorMessage) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +STATIC_ASSERT((pb_membersize(emulator_VehiclePropConfig, area_configs) < 256 +&& pb_membersize(emulator_EmulatorMessage, prop) < 256 +&& pb_membersize(emulator_EmulatorMessage, config) < 256 +&& pb_membersize(emulator_EmulatorMessage, value) < 256), +YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_emulator_VehicleAreaConfig_emulator_\ +VehiclePropConfig_emulator_VehiclePropValue_emulator_VehiclePropGet_emulator_EmulatorMessage) +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NXP Semiconductor"); diff --git a/drivers/misc/vehicle/vehiclehalproto.pb.h b/drivers/misc/vehicle/vehiclehalproto.pb.h new file mode 100644 index 000000000000..90e981bd06f7 --- /dev/null +++ b/drivers/misc/vehicle/vehiclehalproto.pb.h @@ -0,0 +1,191 @@ +/* + * Copyright 2018 NXP + * + * 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 _PB_VEHICLEHALPROTO_PB_H_ +#define _PB_VEHICLEHALPROTO_PB_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum definitions */ +typedef enum _emulator_MsgType { + emulator_MsgType_GET_CONFIG_CMD = 0, + emulator_MsgType_GET_CONFIG_RESP = 1, + emulator_MsgType_GET_CONFIG_ALL_CMD = 2, + emulator_MsgType_GET_CONFIG_ALL_RESP = 3, + emulator_MsgType_GET_PROPERTY_CMD = 4, + emulator_MsgType_GET_PROPERTY_RESP = 5, + emulator_MsgType_GET_PROPERTY_ALL_CMD = 6, + emulator_MsgType_GET_PROPERTY_ALL_RESP = 7, + emulator_MsgType_SET_PROPERTY_CMD = 8, + emulator_MsgType_SET_PROPERTY_RESP = 9, + emulator_MsgType_SET_PROPERTY_ASYNC = 10 +} emulator_MsgType; + +typedef enum _emulator_Status { + emulator_Status_RESULT_OK = 0, + emulator_Status_ERROR_UNKNOWN = 1, + emulator_Status_ERROR_UNIMPLEMENTED_CMD = 2, + emulator_Status_ERROR_INVALID_PROPERTY = 3, + emulator_Status_ERROR_INVALID_AREA_ID = 4, + emulator_Status_ERROR_PROPERTY_UNINITIALIZED = 5, + emulator_Status_ERROR_WRITE_ONLY_PROPERTY = 6, + emulator_Status_ERROR_MEMORY_ALLOC_FAILED = 7, + emulator_Status_ERROR_INVALID_OPERATION = 8 +} emulator_Status; + +#ifndef CONFIG_VEHICLE_DRIVER_OREO +typedef enum _emulator_VehiclePropStatus { + emulator_VehiclePropStatus_AVAILABLE = 0, + emulator_VehiclePropStatus_UNAVAILABLE = 1, + emulator_VehiclePropStatus_ERROR = 2 +} emulator_VehiclePropStatus; +#endif + +/* Struct definitions */ +typedef struct _emulator_VehicleAreaConfig { + int32_t area_id; + bool has_min_int32_value; + int32_t min_int32_value; + bool has_max_int32_value; + int32_t max_int32_value; + bool has_min_int64_value; + int64_t min_int64_value; + bool has_max_int64_value; + int64_t max_int64_value; + bool has_min_float_value; + float min_float_value; + bool has_max_float_value; + float max_float_value; +} emulator_VehicleAreaConfig; + +typedef struct _emulator_VehiclePropGet { + int32_t prop; + bool has_area_id; + int32_t area_id; +} emulator_VehiclePropGet; + +typedef struct _emulator_VehiclePropValue { + int32_t prop; + bool has_value_type; + int32_t value_type; + bool has_timestamp; + int64_t timestamp; + bool has_area_id; + int32_t area_id; + pb_callback_t int32_values; + pb_callback_t int64_values; + pb_callback_t float_values; + pb_callback_t string_value; + pb_callback_t bytes_value; +#ifndef CONFIG_VEHICLE_DRIVER_OREO + bool has_status; + emulator_VehiclePropStatus status; +#endif +} emulator_VehiclePropValue; + +typedef struct _emulator_VehiclePropConfig { + int32_t prop; + bool has_access; + int32_t access; + bool has_change_mode; + int32_t change_mode; + bool has_value_type; + int32_t value_type; + bool has_supported_areas; + int32_t supported_areas; + pb_callback_t area_configs; + bool has_config_flags; + int32_t config_flags; + pb_callback_t config_array; + pb_callback_t config_string; + bool has_min_sample_rate; + float min_sample_rate; + bool has_max_sample_rate; + float max_sample_rate; +} emulator_VehiclePropConfig; + +typedef struct _emulator_EmulatorMessage { + emulator_MsgType msg_type; + bool has_status; + emulator_Status status; + pb_callback_t prop; + pb_callback_t config; + pb_callback_t value; +} emulator_EmulatorMessage; + +/* Default values for struct fields */ + +/* Field tags (for use in manual encoding/decoding) */ +#define emulator_VehicleAreaConfig_area_id_tag 1 +#define emulator_VehicleAreaConfig_min_int32_value_tag 2 +#define emulator_VehicleAreaConfig_max_int32_value_tag 3 +#define emulator_VehicleAreaConfig_min_int64_value_tag 4 +#define emulator_VehicleAreaConfig_max_int64_value_tag 5 +#define emulator_VehicleAreaConfig_min_float_value_tag 6 +#define emulator_VehicleAreaConfig_max_float_value_tag 7 +#define emulator_VehiclePropGet_prop_tag 1 +#define emulator_VehiclePropGet_area_id_tag 2 +#define emulator_VehiclePropValue_prop_tag 1 +#define emulator_VehiclePropValue_value_type_tag 2 +#define emulator_VehiclePropValue_timestamp_tag 3 +#ifndef CONFIG_VEHICLE_DRIVER_OREO +#define emulator_VehiclePropValue_status_tag 10 +#endif +#define emulator_VehiclePropValue_area_id_tag 4 +#define emulator_VehiclePropValue_int32_values_tag 5 +#define emulator_VehiclePropValue_int64_values_tag 6 +#define emulator_VehiclePropValue_float_values_tag 7 +#define emulator_VehiclePropValue_string_value_tag 8 +#define emulator_VehiclePropValue_bytes_value_tag 9 +#define emulator_VehiclePropConfig_prop_tag 1 +#define emulator_VehiclePropConfig_access_tag 2 +#define emulator_VehiclePropConfig_change_mode_tag 3 +#define emulator_VehiclePropConfig_value_type_tag 4 +#define emulator_VehiclePropConfig_supported_areas_tag 5 +#define emulator_VehiclePropConfig_area_configs_tag 6 +#define emulator_VehiclePropConfig_config_flags_tag 7 +#define emulator_VehiclePropConfig_config_array_tag 8 +#define emulator_VehiclePropConfig_config_string_tag 9 +#define emulator_VehiclePropConfig_min_sample_rate_tag 10 +#define emulator_VehiclePropConfig_max_sample_rate_tag 11 +#define emulator_EmulatorMessage_msg_type_tag 1 +#define emulator_EmulatorMessage_status_tag 2 +#define emulator_EmulatorMessage_prop_tag 3 +#define emulator_EmulatorMessage_config_tag 4 +#define emulator_EmulatorMessage_value_tag 5 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t emulator_VehicleAreaConfig_fields[8]; +extern const pb_field_t emulator_VehiclePropConfig_fields[12]; +#ifdef CONFIG_VEHICLE_DRIVER_OREO +extern const pb_field_t emulator_VehiclePropValue_fields[10]; +#else +extern const pb_field_t emulator_VehiclePropValue_fields[11]; +#endif +extern const pb_field_t emulator_VehiclePropGet_fields[3]; +extern const pb_field_t emulator_EmulatorMessage_fields[6]; + +/* Maximum encoded size of messages (where known) */ +#define emulator_VehicleAreaConfig_size 55 +#define emulator_VehiclePropGet_size 22 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ab37cf7ab568..7f09de9495ec 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2405,9 +2405,13 @@ int mmc_attach_mmc(struct mmc_host *host) if (!mmc_host_is_spi(host)) mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); +#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC err = mmc_send_op_cond(host, 0, &ocr); if (err) return err; +#else + ocr = 0xc0ff8080; +#endif mmc_attach_bus(host, &mmc_ops); if (host->ocr_avail_mmc) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 7115e7f32ed4..f22a38cf42d2 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -824,6 +824,14 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE)) return -EROFS; + if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP)) { + /* + * All FF data is relatively friendly to the data retention capability of SPI + * Nand devices. + */ + memset((char *)ec_hdr + sizeof(struct ubi_ec_hdr), 0xFF, + ubi->ec_hdr_alsize - sizeof(struct ubi_ec_hdr)); + } err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); return err; } @@ -1074,6 +1082,14 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE)) return -EROFS; + if (IS_ENABLED(CONFIG_ARCH_ROCKCHIP)) { + /* + * All FF data is relatively friendly to the data retention capability of SPI + * Nand devices. + */ + memset((char *)p + sizeof(struct ubi_vid_hdr), 0xFF, + ubi->vid_hdr_alsize - sizeof(struct ubi_vid_hdr)); + } err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); return err; diff --git a/drivers/net/phy/rockchip-fephy.c b/drivers/net/phy/rockchip-fephy.c index 1b7fdd4685a4..e663f54711f0 100644 --- a/drivers/net/phy/rockchip-fephy.c +++ b/drivers/net/phy/rockchip-fephy.c @@ -108,7 +108,12 @@ static int rockchip_fephy_config_init(struct phy_device *phydev) return ret; /* 100M amplitude control */ - ret = rockchip_fephy_group_write(phydev, GROUP_CFG0, 0x18, 0xc); + ret = rockchip_fephy_group_write(phydev, GROUP_CFG0, 0x18, 0x9); + if (ret) + return ret; + + /* 10M amplitude control */ + ret = rockchip_fephy_group_write(phydev, GROUP_CFG0, 0x1f, 0x7); if (ret) return ret; diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index db82603a2d31..2c22ffdc4b8c 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -1793,7 +1793,8 @@ static int rk_pcie_remove(struct platform_device *pdev) * Timeout should not happen as it's longer than regular probe actually. * But probe maybe fail, so need to double check bridge bus. */ - if (!rk_pcie || !rk_pcie->finish_probe || !rk_pcie->pci->pp.bridge->bus) { + if (!rk_pcie || !rk_pcie->pci || !rk_pcie->pci->pp.bridge || + !rk_pcie->pci->pp.bridge->bus) { dev_dbg(dev, "%s return early due to failure in threaded init\n", __func__); return 0; } diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index db265f27bcd3..4e96b19ac333 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -1394,7 +1394,7 @@ int rockchip_csi2_dphy_hw_init(void) return platform_driver_register(&rockchip_csi2_dphy_hw_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) subsys_initcall(rockchip_csi2_dphy_hw_init); #else #if !defined(CONFIG_VIDEO_REVERSE_IMAGE) diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c index 5619e40f3c9b..5ee11606e950 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy.c @@ -1276,8 +1276,8 @@ int rockchip_csi2_dphy_init(void) return platform_driver_register(&rockchip_csi2_dphy_driver); } -#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) -subsys_initcall(rockchip_csi2_dphy_init); +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) +subsys_initcall_sync(rockchip_csi2_dphy_init); #else #if !defined(CONFIG_VIDEO_REVERSE_IMAGE) module_platform_driver(rockchip_csi2_dphy_driver); diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index 70417e421b46..aa2055ba0037 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -1487,6 +1487,10 @@ static int rv1126b_combphy_cfg(struct rockchip_combphy_priv *priv) /* Set Rx squelch input filler bandwidth */ writel(0x0e, priv->mmio + (0x14 << 2)); + /* Set Full Txswing and Txmargin 1200mV and -6dB De-emphasis */ + regmap_write(priv->phy_grf, 0x1800c, GENMASK(18, 16) | 0x0007); + regmap_write(priv->phy_grf, 0x18004, GENMASK(26, 21) | 0x0100); + rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); rockchip_combphy_param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index 65144789912e..3987a26f6537 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -173,25 +173,29 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv) static int rockchip_p3phy_rk3588_calibrate(struct rockchip_p3phy_priv *priv) { - int ret = 0; - u32 reg; + u32 phy0_status, phy1_status; + int i, sleep_us = 100; + bool check_both = (priv->pcie30_phymode == PHY_MODE_PCIE_AGGREGATION); - ret = regmap_read_poll_timeout(priv->phy_grf, - RK3588_PCIE3PHY_GRF_PHY0_STATUS1, - reg, RK3588_SRAM_INIT_DONE(reg), - 100, RK_PCIE_SRAM_INIT_TIMEOUT); - if (priv->pcie30_phymode == PHY_MODE_PCIE_AGGREGATION) { - ret |= regmap_read_poll_timeout(priv->phy_grf, - RK3588_PCIE3PHY_GRF_PHY1_STATUS1, - reg, RK3588_SRAM_INIT_DONE(reg), - 100, RK_PCIE_SRAM_INIT_TIMEOUT); + for (i = 0; i < RK_PCIE_SRAM_INIT_TIMEOUT; i += sleep_us) { + regmap_read(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY0_STATUS1, &phy0_status); + regmap_read(priv->phy_grf, RK3588_PCIE3PHY_GRF_PHY1_STATUS1, &phy1_status); + + if (check_both) { + if (RK3588_SRAM_INIT_DONE(phy0_status) && RK3588_SRAM_INIT_DONE(phy1_status)) + return 0; + } else { + if (RK3588_SRAM_INIT_DONE(phy0_status) || RK3588_SRAM_INIT_DONE(phy1_status)) + return 0; + } + + usleep_range(sleep_us, sleep_us + 10); } - if (ret) - dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n", - __func__, reg); + pr_err("%s: lock failed p0=0x%x p1=0x%x, check input refclk and power supply\n", + __func__, phy0_status, phy1_status); - return ret; + return -ETIMEDOUT; } static const struct rockchip_p3phy_ops rk3588_ops = { diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 65d37044fe0c..08139a095249 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -540,6 +540,13 @@ config PWM_RZ_MTU3 To compile this driver as a module, choose M here: the module will be called pwm-rz-mtu3. +config PWM_R7F701 + tristate "R7F701 PWM support" + help + This is a MCU for controlling brightness on the screen, which + adjusts brightness by writing corresponding registers through I2C. + If you don't have this MCU in your design, choose N. + config PWM_SAMSUNG tristate "Samsung PWM support" depends on PLAT_SAMSUNG || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 96af336a0f1d..d5440cce0e70 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o obj-$(CONFIG_PWM_ROCKCHIP_TEST) += pwm-rockchip-test.o obj-$(CONFIG_PWM_RZ_MTU3) += pwm-rz-mtu3.o +obj-$(CONFIG_PWM_R7F701) += pwm-r7f701.o obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o obj-$(CONFIG_PWM_SIFIVE) += pwm-sifive.o obj-$(CONFIG_PWM_SL28CPLD) += pwm-sl28cpld.o diff --git a/drivers/pwm/pwm-r7f701.c b/drivers/pwm/pwm-r7f701.c new file mode 100644 index 000000000000..38ffabaaeef9 --- /dev/null +++ b/drivers/pwm/pwm-r7f701.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-i2c.c -- Control screen brightness + * + * Copyright (c) 2025 Rockchip Electronics Co., Ltd. + * + * Author: ZITONG CAI + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PWM_MAX_LEVEL 0x64 + +#define DISPLAY_STATUS 0x40 +#define LVDS_LOCK_STATUS 0x41 +#define CUR_BRIGHTNESS_LEVEL 0x42 +#define OLED_FAULT_RECORD 0x43 +#define PCB_TEMP_STATUS 0x44 +#define OLED_TEMP_STATUS 0x45 +#define CID_POWER_STATUS 0x46 +#define CID_HARDWARE_VERSION 0x47 +#define CID_SOFT_APP_VERSION 0x48 +#define CID_BOOTLOADER_VERSION 0x49 +#define CID_FUALT_RECORD 0x4a +#define CID_VOLTAGE_VALUE 0x4b +#define CID_CURRENT_MODE_STATUS 0x4c +#define CID_ENTER_AUTO_CAUSE 0x4d +#define CID_CAN_STATUS 0x4e + + +#define REQUEST_DISPLAY_STATUS 0x80 +#define REQUEST_LVDS_LOCK_STATUS 0x81 +#define REQUEST_BRIGHTNESS_LEVEL 0x82 +#define REQUEST_OLED_FAULT_RECORD 0x83 +#define REQUEST_PCB_TEMP_STATUS 0x84 +#define REQUEST_OLED_TEMP_STATUS 0x85 +#define REQUEST_CID_POWER_STATE 0x86 +#define REQUEST_CID_HARDWARE_VERSION 0x87 +#define REQUEST_CID_SOFT_APP_VERSION 0x88 +#define REQUEST_CID_BOOTLOADER_VERSION 0x89 +#define REQUEST_CID_FUALT_RECORD 0x8a +#define REQUEST_CID_VOLTAGE_VALUE 0x8b +#define REQUEST_CID_CURRENT_MODE_STATUS 0x8c +#define REQUEST_CID_ENTER_AUTO_CAUSE 0x8d +#define REQUEST_DISPLAY_STATUS_SET 0x8e +#define REQUEST_CID_BRIGHTNESS_SET 0x8f +#define REQUEST_IDCM_WRITE_HEART 0x90 +#define REQUEST_CID_CAN_STATUS 0x91 +#define REQUEST_IDCM_SEND_CRC 0x92 + +enum { + DISPLAY_OFF, + DISPLAY_ON +}; + +struct r7f701_pwm_chip { + struct pwm_chip chip; + struct device *dev; + struct regmap *regmap; + +}; + +static bool r7f701_is_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x80 ... 0x92: + return true; + } + return false; +} + +static bool r7f701_is_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x40 ... 0x4e: + return true; + } + return false; +} + +static bool r7f701_is_volatile_reg(struct device *dev, unsigned int reg) +{ + return true; +} + + +static const struct regmap_config r7f701_regmap_config = { + .name = "r7f701", + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = r7f701_is_writeable_reg, + .readable_reg = r7f701_is_readable_reg, + .volatile_reg = r7f701_is_volatile_reg, + .cache_type = REGCACHE_RBTREE, + .max_register = 0x92, +}; + +static inline struct r7f701_pwm_chip *to_r7f701_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct r7f701_pwm_chip, chip); +} + +static int r7f701_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + u64 duty_ns, u64 period_ns) +{ + u8 reg = 0; + u64 div = 0; + u8 level = 0; + int ret = 0; + u8 data[7] = {0}; + struct r7f701_pwm_chip *r7f701 = to_r7f701_pwm_chip(chip); + + div = duty_ns * PWM_MAX_LEVEL; + level = DIV_ROUND_CLOSEST_ULL(div, period_ns); + + reg = REQUEST_DISPLAY_STATUS_SET; + data[0] = DISPLAY_ON; + data[1] = level; + data[6] = reg ^ data[0] ^ data[1]; + ret |= regmap_bulk_write(r7f701->regmap, reg, data, ARRAY_SIZE(data)); + memset(data, 0, sizeof(data)); + + reg = REQUEST_CID_BRIGHTNESS_SET; + data[0] = level; + data[6] = reg ^ data[0]; + ret |= regmap_bulk_write(r7f701->regmap, reg, data, ARRAY_SIZE(data)); + + dev_dbg(chip->dev, "%s: pwm chip BRIGHTNESS_SET level 0x%x ret=%d\n", __func__, level, ret); + + return 0; +} + +static int r7f701_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + dev_dbg(chip->dev, "%s: pwm chip\n", __func__); + + return 0; +} + +static void r7f701_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct r7f701_pwm_chip *r7f701 = to_r7f701_pwm_chip(chip); + int ret = 0; + u8 reg = 0; + u8 data[7] = {0}; + + reg = REQUEST_DISPLAY_STATUS_SET; + data[0] = DISPLAY_OFF; + data[6] = reg ^ data[0]; + ret = regmap_bulk_write(r7f701->regmap, reg, data, ARRAY_SIZE(data)); + + dev_dbg(chip->dev, "%s: pwm chip ret=%d\n", __func__, ret); +} + +static int r7f701_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + + if (state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) { + if (pwm->state.enabled) + r7f701_pwm_disable(chip, pwm); + + return 0; + } + + err = r7f701_pwm_config(chip, pwm, state->duty_cycle, state->period); + if (err) + return err; + + if (!pwm->state.enabled) + return r7f701_pwm_enable(chip, pwm); + + return 0; +} + +static int r7f701_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + state->enabled = true; + state->polarity = PWM_POLARITY_NORMAL; + + dev_dbg(chip->dev, "%s: pwm chip\n", __func__); + + return 0; +} + +static const struct pwm_ops r7f701_pwm_ops = { + .apply = r7f701_pwm_apply, + .get_state = r7f701_pwm_get_state, + .owner = THIS_MODULE, +}; + +static const struct of_device_id pwm_of_match[] = { + { .compatible = "r7f701-pwm", .data = 0}, + { } +}; + +static int pwm_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct r7f701_pwm_chip *r7f701; + int ret = 0; + + r7f701 = devm_kzalloc(dev, sizeof(*r7f701), GFP_KERNEL); + if (!r7f701) + return -ENOMEM; + + r7f701->dev = dev; + r7f701->chip.dev = dev; + r7f701->chip.ops = &r7f701_pwm_ops; + r7f701->chip.npwm = 1; + + i2c_set_clientdata(client, r7f701); + dev_set_drvdata(dev, r7f701); + + r7f701->regmap = devm_regmap_init_i2c(client, &r7f701_regmap_config); + if (IS_ERR(r7f701->regmap)) { + dev_err(dev, "%s: Failed to allocate r7f701 register map\n", __func__); + return PTR_ERR(r7f701->regmap); + } + + ret = devm_pwmchip_add(dev, &r7f701->chip); + if (ret < 0) { + dev_err(dev, "%s: pwmchip_add() failed: %d\n", __func__, ret); + return ret; + } + + dev_dbg(dev, "%s successful\n", __func__); + + return 0; +} + +static struct i2c_driver r7f701_i2c_driver = { + .driver = { + .name = "r7f701-pwm", + .of_match_table = of_match_ptr(pwm_of_match), + }, + .probe = pwm_probe, +}; + +static int __init r7f701_i2c_init(void) +{ + int ret; + + ret = i2c_add_driver(&r7f701_i2c_driver); + if (ret != 0) + pr_err("Failed to register r7f701 I2C driver: %d\n", ret); + + return ret; +} + +static void __exit r7f701_i2c_exit(void) +{ + i2c_del_driver(&r7f701_i2c_driver); +} + +subsys_initcall(r7f701_i2c_init); +module_exit(r7f701_i2c_exit); + +MODULE_AUTHOR("ZITONG CAI "); +MODULE_DESCRIPTION("display pwm interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:r7f701-PWM"); diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 1c462f33a34a..fa86d31e3b48 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -321,6 +321,7 @@ struct rockchip_pwm_chip { unsigned long is_clk_enabled; bool vop_pwm_en; /* indicate voppwm mirror register state */ bool center_aligned; + bool oneshot_valid; bool oneshot_en; bool capture_en; bool wave_en; @@ -561,7 +562,7 @@ static void rockchip_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm ctrl &= ~PWM_CLK_SEL_MASK; ctrl |= PWM_SEL_SCALED_CLOCK; - pc->oneshot_en = true; + pc->oneshot_valid = true; ctrl &= ~PWM_MODE_MASK; ctrl |= PWM_ONESHOT; @@ -584,7 +585,7 @@ static void rockchip_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", pc->data->oneshot_cnt_max); - pc->oneshot_en = false; + pc->oneshot_valid = false; ctrl &= ~PWM_MODE_MASK; ctrl |= PWM_CONTINUOUS; @@ -651,7 +652,7 @@ static int rockchip_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm, val |= PWM_OUTPUT_CENTER; } - if (pc->oneshot_en) { + if (pc->oneshot_valid) { enable_conf &= ~PWM_MODE_MASK; enable_conf |= PWM_ONESHOT; } else if (pc->capture_en) { @@ -679,6 +680,8 @@ static int rockchip_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm, if (!enable) clk_disable(pc->clk); + pc->oneshot_en = pc->oneshot_valid ? enable : false; + return 0; } @@ -830,17 +833,17 @@ static void rockchip_pwm_config_v4(struct pwm_chip *chip, struct pwm_device *pwm state->duty_cycle, state->period); } - pc->oneshot_en = true; + pc->oneshot_valid = true; } else { if (state->oneshot_count) dev_err(chip->dev, "Oneshot_count must be between 1 and %d.\n", pc->data->oneshot_cnt_max); - pc->oneshot_en = false; + pc->oneshot_valid = false; } #endif - if (pc->oneshot_en) { + if (pc->oneshot_valid) { writel_relaxed(PWM_MODE(ONESHOT_MODE) | PWM_ALIGNED_INVALID(true), pc->base + CTRL_V4); writel_relaxed(offset, pc->base + OFFSET); @@ -873,13 +876,20 @@ static int rockchip_pwm_enable_v4(struct pwm_chip *chip, struct pwm_device *pwm, writel_relaxed(PWM_EN(enable) | PWM_CLK_EN(enable), pc->base + ENABLE); - if (!enable) { + /* + * For pwm v4, the disable operation of continuous mode, which sets polarity + * to inactive state, will not take effect until the end of current period. + * Therefore, it makes sense to delay one period before disabling the dclk. + */ + if (!enable && !pc->oneshot_en) { pwm_get_state(pwm, &curstate); delay_us = DIV_ROUND_UP_ULL(curstate.period, NSEC_PER_USEC); fsleep(delay_us); clk_disable(pc->clk); } + pc->oneshot_en = pc->oneshot_valid ? enable : false; + return 0; } diff --git a/drivers/regulator/rk801-regulator.c b/drivers/regulator/rk801-regulator.c index 489b5eba0305..ae8be3e65d33 100644 --- a/drivers/regulator/rk801-regulator.c +++ b/drivers/regulator/rk801-regulator.c @@ -256,29 +256,34 @@ static int rk801_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) { struct rk801_regulator_data *pdata = rdev_get_drvdata(rdev); struct gpio_desc *gpio = pdata->pwrctrl_gpio; - unsigned int reg0 = rdev->desc->vsel_reg; - unsigned int reg1 = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET; - unsigned int reg; - int ret, gpio_level; + unsigned int reg_normal = rdev->desc->vsel_reg; + unsigned int reg_sleep = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET; + unsigned int reg_target; + int act_level; /* logic value */ + int ret; if (pdata->req_pwrctrl_dvs) { - gpio_level = gpiod_get_value(gpio); - reg = (gpio_level == 1) ? reg0 : reg1; + /* + * act_level=1: active on reg_sleep now -> target: reg_normal + * act_level=0: inactive on reg_normal now -> target: reg_sleep + */ + act_level = gpiod_get_value(gpio); + reg_target = act_level ? reg_normal : reg_sleep; sel <<= ffs(rdev->desc->vsel_mask) - 1; - ret = regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel); + ret = regmap_update_bits(rdev->regmap, reg_target, rdev->desc->vsel_mask, sel); if (ret) return ret; udelay(40); /* hw sync */ - gpiod_set_value(gpio, !gpio_level); + gpiod_set_value(gpio, !act_level); - if (reg == reg0) - ret = regmap_update_bits(rdev->regmap, reg1, + if (reg_target == reg_normal) + ret = regmap_update_bits(rdev->regmap, reg_sleep, rdev->desc->vsel_mask, sel); else - ret = regmap_update_bits(rdev->regmap, reg0, + ret = regmap_update_bits(rdev->regmap, reg_normal, rdev->desc->vsel_mask, sel); } else { ret = regulator_set_voltage_sel_regmap(rdev, sel); @@ -416,38 +421,6 @@ static const struct regulator_desc rk801_reg[] = { ENABLE_MASK(2), ENABLE_VAL(2), DISABLE_VAL(2), 400), }; -static int rk801_regulator_dt_parse_pdata(struct device *dev, - struct device *client_dev, - struct regmap *map, - struct rk801_regulator_data *pdata) -{ - struct device_node *np; - int ret = 0; - - np = of_get_child_by_name(client_dev->of_node, "regulators"); - if (!np) - return -ENXIO; - - if (pdata->req_pwrctrl_dvs) { - pdata->pwrctrl_gpio = devm_gpiod_get_optional(client_dev, - "pwrctrl", GPIOD_OUT_LOW); - if (IS_ERR(pdata->pwrctrl_gpio)) { - ret = PTR_ERR(pdata->pwrctrl_gpio); - dev_err(dev, "failed to get pwrctrl gpio! ret=%d\n", ret); - goto dt_parse_end; - } - - if (!pdata->pwrctrl_gpio) { - dev_err(dev, "there is no pwrctrl gpio!\n"); - ret = -EINVAL; - } - } -dt_parse_end: - of_node_put(np); - - return ret; -} - static int rk801_regulator_init(struct device *dev) { struct rk808 *rk808 = dev_get_drvdata(dev->parent); @@ -459,12 +432,18 @@ static int rk801_regulator_init(struct device *dev) { RK801_LDO1_ON_VSEL_REG, RK801_LDO1_SLP_VSEL_REG }, { RK801_LDO2_ON_VSEL_REG, RK801_LDO2_SLP_VSEL_REG }, }; - uint val, en0, en1; - int i, ret; + uint act_pol, en0, en1; + int i, ret, val; + + if (!pdata->req_pwrctrl_dvs) + return 0; + + /* set pmic-pwrctrl active pol and use sleep function */ + act_pol = rk808->pwrctrl.act_low ? + RK801_SLEEP_ACT_L : RK801_SLEEP_ACT_H; - /* pwrctrl gpio active high and use sleep function */ ret = regmap_update_bits(rk808->regmap, RK801_SYS_CFG2_REG, - RK801_SLEEP_POL_MSK, RK801_SLEEP_ACT_H); + RK801_SLEEP_POL_MSK, act_pol); if (ret) return ret; @@ -562,7 +541,7 @@ static int rk801_regulator_suspend_late(struct device *dev) if (!pdata->req_pwrctrl_dvs) return 0; - /* set pwrctrl pin low */ + /* set soc-pwrctrl inactive (0:inactive) */ gpiod_set_value(gpio, 0); udelay(40); @@ -595,26 +574,18 @@ static int rk801_regulator_probe(struct platform_device *pdev) struct regulator_config config = {}; struct regulator_dev *rk801_rdev; struct rk801_regulator_data *pdata; - int id_lsb, i, ret; + int i, ret; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - ret = regmap_read(rk808->regmap, RK801_ID_LSB, &id_lsb); - if (ret) - return ret; - - pdata->req_pwrctrl_dvs = (id_lsb & 0x0f) < 4; - dev_info(&pdev->dev, "req pwrctrl dvs: %d\n", pdata->req_pwrctrl_dvs); - - ret = rk801_regulator_dt_parse_pdata(&pdev->dev, &client->dev, - rk808->regmap, pdata); - if (ret < 0) - return ret; + pdata->req_pwrctrl_dvs = rk808->pwrctrl.req_pwrctrl_dvs; + pdata->pwrctrl_gpio = rk808->pwrctrl.gpio; + dev_info(&pdev->dev, "req pwrctrl dvs: %d, act: %s\n", + pdata->req_pwrctrl_dvs, rk808->pwrctrl.act_low ? "low" : "high"); platform_set_drvdata(pdev, pdata); - config.dev = &client->dev; config.driver_data = pdata; config.regmap = rk808->regmap; diff --git a/drivers/rknpu/rknpu_devfreq.c b/drivers/rknpu/rknpu_devfreq.c index 3ce543b606e6..d8db3a34c250 100644 --- a/drivers/rknpu/rknpu_devfreq.c +++ b/drivers/rknpu/rknpu_devfreq.c @@ -136,6 +136,42 @@ static int rk3588_npu_get_soc_info(struct device *dev, struct device_node *np, return ret; } +static int rv1126b_npu_get_soc_info(struct device *dev, struct device_node *np, + int *bin, int *process) +{ + int ret = 0; + u8 value = 0; + + if (!bin) + return 0; + + if (of_property_match_string(np, "nvmem-cell-names", + "specification_serial_number") >= 0) { + ret = rockchip_nvmem_cell_read_u8( + np, "specification_serial_number", &value); + if (ret) { + LOG_DEV_ERROR( + dev, + "Failed to get specification_serial_number\n"); + return ret; + } + /* RV1126BM */ + if (value == 0xd) + *bin = 1; + /* RV1126BJ */ + else if (value == 0xa) + *bin = 2; + /* RV1126BP */ + else if (value == 0x10) + *bin = 3; + } + if (*bin < 0) + *bin = 0; + LOG_DEV_INFO(dev, "bin=%d\n", *bin); + + return ret; +} + #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE static int rk3588_npu_set_soc_info(struct device *dev, struct device_node *np, struct rockchip_opp_info *opp_info) @@ -262,6 +298,8 @@ static const struct rockchip_opp_data rk3588_npu_opp_data = { static const struct rockchip_opp_data rv1126b_npu_opp_data = { .is_use_pvtpll = true, + .get_soc_info = rv1126b_npu_get_soc_info, + .set_soc_info = rk3588_npu_set_soc_info, #if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE .config_regulators = npu_opp_config_regulators, .config_clks = npu_opp_config_clks, diff --git a/drivers/rtc/rtc-rockchip.c b/drivers/rtc/rtc-rockchip.c index d26a07f5a904..710346ceee3a 100644 --- a/drivers/rtc/rtc-rockchip.c +++ b/drivers/rtc/rtc-rockchip.c @@ -87,6 +87,7 @@ /* RTC_CTRL_REG bitfields */ #define RTC_CTRL_REG_START_RTC BIT(0) #define RTC_TIMEOUT (3000 * 1000) +#define RTC_STATUS_TIMEOUT (500) /* RK630 has a shadowed register for saving a "frozen" RTC time. * When user setting "GET_TIME" to 1, the time will save in this shadowed @@ -256,8 +257,7 @@ static int rockchip_rtc_read_time(struct device *dev, struct rtc_time *tm) return ret; } -/* Set current time and date in RTC */ -static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) +static int rockchip_rtc_do_set_time(struct device *dev, struct rtc_time *tm, bool ready) { struct rockchip_rtc *rtc = dev_get_drvdata(dev); u32 rtc_data[NUM_TIME_REGS]; @@ -292,13 +292,15 @@ static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, - !(status & RTC_CTRL_REG_START_RTC), - 0, RTC_TIMEOUT); - if (ret) - dev_err(dev, - "%s:timeout Update RTC_STATUS1 : %d\n", - __func__, ret); + if (ready) { + ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, + !(status & RTC_CTRL_REG_START_RTC), + 100, RTC_STATUS_TIMEOUT); + if (ret) + dev_err(dev, + "%s:timeout Update RTC_STATUS1 : %d\n", + __func__, ret); + } ret = regmap_bulk_write(rtc->regmap, RTC_SET_SECONDS, rtc_data, NUM_TIME_REGS); @@ -318,17 +320,25 @@ static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) return ret; } - ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, - (status & RTC_CTRL_REG_START_RTC), - 0, RTC_TIMEOUT); - if (ret) - dev_err(dev, - "%s:timeout Update RTC_STATUS1 : %d\n", - __func__, ret); + if (ready) { + ret = regmap_read_poll_timeout(rtc->regmap, RTC_STATUS1, status, + (status & RTC_CTRL_REG_START_RTC), + 100, RTC_STATUS_TIMEOUT); + if (ret) + dev_err(dev, + "%s:timeout Update RTC_STATUS1 : %d\n", + __func__, ret); + } return 0; } +/* Set current time and date in RTC */ +static int rockchip_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return rockchip_rtc_do_set_time(dev, tm, true); +} + /* Read alarm time and date in RTC */ static int rockchip_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { @@ -948,7 +958,7 @@ static int rockchip_rtc_probe(struct platform_device *pdev) rockchip_rtc_read_time(&pdev->dev, &tm_read); if (rtc_valid_tm(&tm_read) != 0) - rockchip_rtc_set_time(&pdev->dev, &tm); + rockchip_rtc_do_set_time(&pdev->dev, &tm, false); rtc->irq = platform_get_irq(pdev, 0); if (rtc->irq < 0) diff --git a/drivers/soc/rockchip/rockchip-cpuinfo.c b/drivers/soc/rockchip/rockchip-cpuinfo.c index c37a0aa43a3c..6e25271669a1 100644 --- a/drivers/soc/rockchip/rockchip-cpuinfo.c +++ b/drivers/soc/rockchip/rockchip-cpuinfo.c @@ -24,6 +24,47 @@ unsigned long rockchip_soc_id; EXPORT_SYMBOL(rockchip_soc_id); +static char id[33] = "0"; +module_param_string(id, id, sizeof(id), 0444); + +static int rk3566_soc_init(struct device *dev) +{ + struct nvmem_cell *cell; + unsigned char *val; + + cell = nvmem_cell_get(dev, "remark_spec_serial_number"); + if (!IS_ERR(cell)) { + val = nvmem_cell_read(cell, NULL); + nvmem_cell_put(cell); + if (IS_ERR(val)) + return PTR_ERR(val); + + if (*val) { + if (*val == 0x1b) + rockchip_soc_id = ROCKCHIP_SOC_RK3566PRO; + kfree(val); + return 0; + } + + kfree(val); + } + + cell = nvmem_cell_get(dev, "specification_serial_number"); + if (!IS_ERR(cell)) { + val = nvmem_cell_read(cell, NULL); + nvmem_cell_put(cell); + if (IS_ERR(val)) + return PTR_ERR(val); + + if (*val == 0x1b) + rockchip_soc_id = ROCKCHIP_SOC_RK3566PRO; + + kfree(val); + } + + return 0; +} + static int rockchip_cpuinfo_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -33,6 +74,12 @@ static int rockchip_cpuinfo_probe(struct platform_device *pdev) size_t len = 0; int i; + if (cpu_is_rk3566()) { + rk3566_soc_init(dev); + if (soc_is_rk3566pro()) + goto skip_cpu_code; + } + cell = nvmem_cell_get(dev, "cpu-code1"); if (!IS_ERR(cell)) { efuse_buf = nvmem_cell_read(cell, &len); @@ -58,6 +105,7 @@ static int rockchip_cpuinfo_probe(struct platform_device *pdev) } } +skip_cpu_code: cell = nvmem_cell_get(dev, "cpu-version"); if (!IS_ERR(cell)) { efuse_buf = nvmem_cell_read(cell, &len); @@ -88,6 +136,7 @@ static int rockchip_cpuinfo_probe(struct platform_device *pdev) for (i = 0; i < 8; i++) { buf[i] = efuse_buf[1 + (i << 1)]; buf[i + 8] = efuse_buf[i << 1]; + sprintf(id + i * 4, "%02x%02x", efuse_buf[i << 1], efuse_buf[1 + (i << 1)]); } kfree(efuse_buf); @@ -169,6 +218,19 @@ static void rv1126_init(void) rockchip_soc_id = ROCKCHIP_SOC_RV1126; } +#define RV1126B_OS_REG1 0x20130204 +static void rv1109b_init(void) +{ + rockchip_soc_id = ROCKCHIP_SOC_RV1109B; + rockchip_set_cpu_version_from_os_reg(RV1126B_OS_REG1); +} + +static void rv1126b_init(void) +{ + rockchip_soc_id = ROCKCHIP_SOC_RV1126B; + rockchip_set_cpu_version_from_os_reg(RV1126B_OS_REG1); +} + static void rk3288_init(void) { void __iomem *base; @@ -284,8 +346,12 @@ int rockchip_soc_id_init(void) rv1106_init(); } else if (cpu_is_rv1109()) { rv1109_init(); + } else if (cpu_is_rv1109b()) { + rv1109b_init(); } else if (cpu_is_rv1126()) { rv1126_init(); + } else if (cpu_is_rv1126b()) { + rv1126b_init(); } else if (cpu_is_rk3528()) { rk3528_init(); } else if (cpu_is_rk3566()) { diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 129be7d647c4..6bb5cae09688 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -92,7 +92,6 @@ struct optee_supp { struct list_head reqs; struct idr idr; struct completion reqs_c; - bool shutdown; }; /* diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index c6156c94e5bd..d5b28fd35d66 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -1486,11 +1485,6 @@ static void optee_shutdown(struct platform_device *pdev) { struct optee *optee = platform_get_drvdata(pdev); - /* Tell requesting thread to interrupt an RPC */ - smp_store_mb(optee->supp.shutdown, true); - /* Wait requesting thread to release resources */ - mdelay(200); - if (!optee->rpc_param_count) optee_disable_shm_cache(optee); } diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c index a8656a72d83a..322a543b8c27 100644 --- a/drivers/tee/optee/supp.c +++ b/drivers/tee/optee/supp.c @@ -82,8 +82,6 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, struct optee_supp_req *req; bool interruptable; u32 ret; - int id; - struct optee_supp_req *get_req; /* * Return in case there is no supplicant available and @@ -116,15 +114,8 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, * exclusive access again. */ while (wait_for_completion_interruptible(&req->c)) { - if (supp->shutdown) { - /* Reboot happen, tee-supplicant is dead, interrupt an RPC */ - interruptable = true; - } else { - /* Deep sleep, tee-supplicant is freeze, wait tee-supplicant */ - continue; - } - mutex_lock(&supp->mutex); + interruptable = !supp->ctx; if (interruptable) { /* * There's no supplicant available and since the @@ -143,14 +134,6 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, list_del(&req->link); req->in_queue = false; } - - idr_for_each_entry(&supp->idr, get_req, id) { - if (get_req == req) { - idr_remove(&supp->idr, id); - supp->req_id = -1; - break; - } - } } mutex_unlock(&supp->mutex); diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index a1577c330b63..f21b9b74f85f 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -260,6 +260,8 @@ struct rockchip_thermal_data { #define TSADC_DATA_SIGN_BIT BIT(16) #define TSADC_DATA_NEGATIVE 0xfffe0000 +#define TSADC_TEMP_DEBOUNCE 5000 +#define TSADC_TEMP_CRITICAL 115000 #define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4 #define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4 @@ -1395,6 +1397,33 @@ static int rk_tsadcv4_get_temp(const struct chip_tsadc_table *table, return rk_tsadcv2_code_to_temp(table, val, temp); } +static int rk_tsadc_limit_amplitude(int new_temp, bool enable) +{ + static int last_temp = INT_MAX; + + /* Reinit last temp when phy init */ + if (!enable) { + last_temp = INT_MAX; + return 0; + } + + if (last_temp != INT_MAX) { + if (abs(new_temp - last_temp) > TSADC_TEMP_DEBOUNCE) { + if (new_temp > last_temp) + new_temp = last_temp + TSADC_TEMP_DEBOUNCE; + else + new_temp = last_temp - TSADC_TEMP_DEBOUNCE; + } + } else { + /* Limit the first temperature */ + if (new_temp >= TSADC_TEMP_CRITICAL) + new_temp = TSADC_TEMP_CRITICAL - TSADC_TEMP_DEBOUNCE; + } + last_temp = new_temp; + + return new_temp; +} + static int rk_tsadcv5_get_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int *temp) { @@ -1410,6 +1439,8 @@ static int rk_tsadcv5_get_temp(const struct chip_tsadc_table *table, else if (*temp > MAX_TEMP) *temp = MAX_TEMP; + *temp = rk_tsadc_limit_amplitude(*temp, true); + return 0; } @@ -1689,6 +1720,7 @@ static void rv1126b_tsadc_phy_init(struct device *dev, struct regmap *grf, regmap_write(grf, RV1126B_GRF_TSADC_CON1, RV1126B_UNLOCK_TRIGGER | RV1126B_UNLOCK_TRIGGER_MASK); regmap_write(grf, RV1126B_GRF_TSADC_CON1, RV1126B_UNLOCK_TRIGGER_MASK); + rk_tsadc_limit_amplitude(0, false); } static const struct rockchip_tsadc_chip px30_tsadc_data = { @@ -2670,7 +2702,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev) if (IS_ERR(thermal->regs)) return PTR_ERR(thermal->regs); - thermal->reset = devm_reset_control_array_get_exclusive(&pdev->dev); + thermal->reset = devm_reset_control_array_get_optional_exclusive(&pdev->dev); if (IS_ERR(thermal->reset)) return dev_err_probe(&pdev->dev, PTR_ERR(thermal->reset), "failed to get tsadc reset.\n"); diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 0a37f0d511cf..726215aa5877 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1450,7 +1450,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, err_count = 3; /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */ if (usb_endpoint_xfer_bulk(&ep->desc)) { - if (udev->speed == USB_SPEED_HIGH) + /* xHCI 1.1 can support HS bulk max packet smaller than 512 */ + if (udev->speed == USB_SPEED_HIGH && xhci->hci_version < 0x110) max_packet = 512; if (udev->speed == USB_SPEED_FULL) { max_packet = rounddown_pow_of_two(max_packet); diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c index 20d55f9f9635..5c51737cd482 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2_link.c @@ -537,7 +537,7 @@ static int rkvdec2_link_finish(struct mpp_dev *mpp, struct mpp_task *mpp_task) struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); struct rkvdec_link_dev *link_dec = dec->link_dec; - struct mpp_dma_buffer *table = link_dec->table; + struct mpp_dma_buffer *table = task->table; struct rkvdec_link_info *info = link_dec->info; struct rkvdec_link_part *part = info->part_r; u32 *tb_reg = (u32 *)table->vaddr; diff --git a/drivers/video/rockchip/rga3/rga3_reg_info.c b/drivers/video/rockchip/rga3/rga3_reg_info.c index c0ce4a3ff4f1..d23ad4a8b971 100644 --- a/drivers/video/rockchip/rga3/rga3_reg_info.c +++ b/drivers/video/rockchip/rga3/rga3_reg_info.c @@ -155,11 +155,13 @@ static void RGA3_set_reg_win0_info(u8 *base, struct rga3_req *msg) win_interleaved = 2; break; case RGA_FORMAT_ARGB_8888: + case RGA_FORMAT_XRGB_8888: win_format = 0x9; pixel_width = 4; win_interleaved = 2; break; case RGA_FORMAT_ABGR_8888: + case RGA_FORMAT_XBGR_8888: win_format = 0x7; pixel_width = 4; win_interleaved = 2; @@ -540,11 +542,13 @@ static void RGA3_set_reg_win1_info(u8 *base, struct rga3_req *msg) win_interleaved = 2; break; case RGA_FORMAT_ARGB_8888: + case RGA_FORMAT_XRGB_8888: win_format = 0x9; pixel_width = 4; win_interleaved = 2; break; case RGA_FORMAT_ABGR_8888: + case RGA_FORMAT_XBGR_8888: win_format = 0x7; pixel_width = 4; win_interleaved = 2; @@ -825,13 +829,24 @@ static void RGA3_set_reg_wr_info(u8 *base, struct rga3_req *msg) wr_format = 0x6; pixel_width = 4; wr_interleaved = 2; - wr_pix_swp = 1; + + /* fbc default RGBA8888, raster default BGRA8888 */ + if (msg->wr.rd_mode == 1) + wr_pix_swp = 0; + else + wr_pix_swp = 1; break; case RGA_FORMAT_BGRA_8888: case RGA_FORMAT_BGRX_8888: wr_format = 0x6; pixel_width = 4; wr_interleaved = 2; + + /* fbc default BGRA8888, raster default RGBA8888 */ + if (msg->wr.rd_mode == 1) + wr_pix_swp = 1; + else + wr_pix_swp = 0; break; case RGA_FORMAT_RGB_888: wr_format = 0x5; @@ -1569,9 +1584,6 @@ static void rga_cmd_to_rga3_cmd(struct rga_req *req_rga, struct rga3_req *req) addr_copy(&req->win0, &req_rga->dst); req->win0.format = req_rga->dst.format; - /* only win1 && wr support fbcd, win0 default raster */ - req->win0.rd_mode = 0; - /* set win0 dst size */ req->win0.dst_act_w = req_rga->dst.act_w; req->win0.dst_act_h = req_rga->dst.act_h; diff --git a/drivers/video/rockchip/rga3/rga_hw_config.c b/drivers/video/rockchip/rga3/rga_hw_config.c index d558c1513501..fadf251cfe0d 100644 --- a/drivers/video/rockchip/rga3/rga_hw_config.c +++ b/drivers/video/rockchip/rga3/rga_hw_config.c @@ -34,6 +34,8 @@ const uint32_t rga3_input_raster_format[] = { RGA_FORMAT_YCrCb_422_SP_10B, RGA_FORMAT_ARGB_8888, RGA_FORMAT_ABGR_8888, + RGA_FORMAT_XRGB_8888, + RGA_FORMAT_XBGR_8888, }; const uint32_t rga3_output_raster_format[] = { @@ -60,6 +62,29 @@ const uint32_t rga3_output_raster_format[] = { }; const uint32_t rga3_fbcd_format[] = { + RGA_FORMAT_RGBA_8888, + RGA_FORMAT_BGRA_8888, + RGA_FORMAT_RGBX_8888, + RGA_FORMAT_BGRX_8888, + RGA_FORMAT_ARGB_8888, + RGA_FORMAT_ABGR_8888, + RGA_FORMAT_XRGB_8888, + RGA_FORMAT_XBGR_8888, + RGA_FORMAT_RGB_888, + RGA_FORMAT_BGR_888, + RGA_FORMAT_RGB_565, + RGA_FORMAT_BGR_565, + RGA_FORMAT_YCbCr_422_SP, + RGA_FORMAT_YCbCr_420_SP, + RGA_FORMAT_YCrCb_422_SP, + RGA_FORMAT_YCrCb_420_SP, + RGA_FORMAT_YCbCr_420_SP_10B, + RGA_FORMAT_YCrCb_420_SP_10B, + RGA_FORMAT_YCbCr_422_SP_10B, + RGA_FORMAT_YCrCb_422_SP_10B, +}; + +const uint32_t rga3_fbce_format[] = { RGA_FORMAT_RGBA_8888, RGA_FORMAT_BGRA_8888, RGA_FORMAT_RGBX_8888, @@ -358,8 +383,8 @@ const struct rga_win_data rga3_win_data[] = { .name = "rga3-wr", .formats[RGA_RASTER_INDEX] = rga3_output_raster_format, .formats_count[RGA_RASTER_INDEX] = ARRAY_SIZE(rga3_output_raster_format), - .formats[RGA_AFBC16x16_INDEX] = rga3_fbcd_format, - .formats_count[RGA_AFBC16x16_INDEX] = ARRAY_SIZE(rga3_fbcd_format), + .formats[RGA_AFBC16x16_INDEX] = rga3_fbce_format, + .formats_count[RGA_AFBC16x16_INDEX] = ARRAY_SIZE(rga3_fbce_format), .formats[RGA_TILE8x8_INDEX] = rga3_tile_format, .formats_count[RGA_TILE8x8_INDEX] = ARRAY_SIZE(rga3_tile_format), .supported_rotations = 0, diff --git a/include/dt-bindings/clock/rockchip,rv1126b-cru.h b/include/dt-bindings/clock/rockchip,rv1126b-cru.h index c10caa9d25e8..09aa04325b51 100644 --- a/include/dt-bindings/clock/rockchip,rv1126b-cru.h +++ b/include/dt-bindings/clock/rockchip,rv1126b-cru.h @@ -371,6 +371,7 @@ #define CLK_MACPHY 361 #define HCLK_RKRNG_NS 362 #define HCLK_RKRNG_S_NS 363 +#define CLK_AISP_PLL_SRC 364 /* secure clks */ #define CLK_USER_OTPC_S 400 diff --git a/include/dt-bindings/display/rockchip_vop.h b/include/dt-bindings/display/rockchip_vop.h index 55d25bfd8875..87cd94de08e5 100644 --- a/include/dt-bindings/display/rockchip_vop.h +++ b/include/dt-bindings/display/rockchip_vop.h @@ -7,6 +7,14 @@ #ifndef _DT_BINDINGS_ROCKCHIP_VOP_H #define _DT_BINDINGS_ROCKCHIP_VOP_H +#define ROCKCHIP_VOP2_SHARED_MODE_PRIMARY 1 +#define ROCKCHIP_VOP2_SHARED_MODE_SECONDARY 2 + +#define ROCKCHIP_VOP_VP0 0 +#define ROCKCHIP_VOP_VP1 1 +#define ROCKCHIP_VOP_VP2 2 +#define ROCKCHIP_VOP_VP3 3 + #define ROCKCHIP_VOP2_CLUSTER0 0 #define ROCKCHIP_VOP2_CLUSTER1 1 #define ROCKCHIP_VOP2_ESMART0 2 @@ -20,4 +28,120 @@ #define ROCKCHIP_VOP2_PHY_ID_INVALID -1 +/* + * FBD: Fast Boot Display + * + * ROCKCHIP_DRM_FBD_FROM_UBOOT: + * show logo.bmp from uboot and show logo_kernel.bmp after enter kernel; + * ROCKCHIP_DRM_FBD_FROM_UBOOT_TO_RTOS: + * crtc/connector/panel will be init at uboot, and update plane at rtos; + * ROCKCHIP_DRM_FBD_FROM_RTOS: + * crtc/connector/panel will be init at rtos, uboot no need to do any hardware + * config, but need to pass the logic state to kernel to ensure pd/clk/drm + * state is continuous. + */ +#define ROCKCHIP_DRM_FBD_FROM_UBOOT 0 +#define ROCKCHIP_DRM_FBD_FROM_UBOOT_TO_RTOS 1 +#define ROCKCHIP_DRM_FBD_FROM_RTOS 2 + +/* mcu_data[23:0] */ +#define ROCKCHIP_MCU_DATA_MAP_DATA_1x24 0 +/* + * { mcu_data[7:3], 3'b0, mcu_data[2:0], mcu_data[7:5], 2'b0, mcu_data[4:0], 3'b0 } + * That is: + * LCDC_D23 -> MCU_D7_M1 + * LCDC_D22 -> MCU_D6_M1 + * LCDC_D21 -> MCU_D5_M1 + * LCDC_D20 -> MCU_D4_M1 + * LCDC_D19 -> MCU_D3_M1 + * LCDC_D18 -> N/A + * LCDC_D17 -> N/A + * LCDC_D16 -> N/A + * LCDC_D15 -> MCU_D2_M1 + * LCDC_D14 -> MCU_D1_M1 + * LCDC_D13 -> MCU_D0_M1 + * LCDC_D12 -> MCU_D7_M0 + * LCDC_D11 -> MCU_D6_M0 + * LCDC_D10 -> MCU_D5_M0 + * LCDC_D9 -> N/A + * LCDC_D8 -> N/A + * LCDC_D7 -> MCU_D4_M0 + * LCDC_D6 -> MCU_D3_M0 + * LCDC_D5 -> MCU_D2_M0 + * LCDC_D4 -> MCU_D1_M0 + * LCDC_D3 -> MCU_D0_M0 + * LCDC_D2 -> N/A + * LCDC_D1 -> N/A + * LCDC_D0 -> N/A + */ +#define ROCKCHIP_MCU_DATA_MAP_DATA_WITH_DUMMY_0 1 +/* { 8'd0, BT1120[15:0] } */ +#define ROCKCHIP_BT1120_DATA_MAP_DATA_PADLO 0 +/* { BT1120[15:0], 8'd0 }*/ +#define ROCKCHIP_BT1120_DATA_MAP_DATA_PADHI 1 +/* + * { BT1120[15:11], 3'd0, BT1120[10:5], 2'd0, BT1120[4:0], 3'b0 } + * That is: + * LCDC_D23 -> BT1120_D15 + * LCDC_D22 -> BT1120_D14 + * LCDC_D21 -> BT1120_D13 + * LCDC_D20 -> BT1120_D12 + * LCDC_D19 -> BT1120_D11 + * LCDC_D18 -> N/A + * LCDC_D17 -> N/A + * LCDC_D16 -> N/A + * LCDC_D15 -> BT1120_D10 + * LCDC_D14 -> BT1120_D9 + * LCDC_D13 -> BT1120_D8 + * LCDC_D12 -> BT1120_D7 + * LCDC_D11 -> BT1120_D6 + * LCDC_D10 -> BT1120_D5 + * LCDC_D9 -> N/A + * LCDC_D8 -> N/A + * LCDC_D7 -> BT1120_D4 + * LCDC_D6 -> BT1120_D3 + * LCDC_D5 -> BT1120_D2 + * LCDC_D4 -> BT1120_D1 + * LCDC_D3 -> BT1120_D0 + * LCDC_D2 -> N/A + * LCDC_D1 -> N/A + * LCDC_D0 -> N/A + */ +#define ROCKCHIP_BT1120_DATA_MAP_DATA_WITH_DUMMY_0 3 +/* { 16'd0, BT656[7:0] }*/ +#define ROCKCHIP_BT656_DATA_MAP_PADLO 0 +/* { 8'd0, BT656[7:0], 8'd0 }*/ +#define ROCKCHIP_BT656_DATA_MAP_DUMMY_HI_LO 1 +/* { BT656[7:0], 16'd0 }*/ +#define ROCKCHIP_BT656_DATA_MAP_PADHI 2 +/* + * { BT656[7:3], 3'd0, BT656[2:0], BT656[7:5], 2'd0, BT656[4:0], 3'd0 } + * That is: + * LCDC_D23 -> BT656_D7_M1 + * LCDC_D22 -> BT656_D6_M1 + * LCDC_D21 -> BT656_D5_M1 + * LCDC_D20 -> BT656_D4_M1 + * LCDC_D19 -> BT656_D3_M1 + * LCDC_D18 -> N/A + * LCDC_D17 -> N/A + * LCDC_D16 -> N/A + * LCDC_D15 -> BT656_D2_M1 + * LCDC_D14 -> BT656_D1_M1 + * LCDC_D13 -> BT656_D0_M1 + * LCDC_D12 -> BT656_D7_M0 + * LCDC_D11 -> BT656_D6_M0 + * LCDC_D10 -> BT656_D5_M0 + * LCDC_D9 -> N/A + * LCDC_D8 -> N/A + * LCDC_D7 -> BT656_D4_M0 + * LCDC_D6 -> BT656_D3_M0 + * LCDC_D5 -> BT656_D2_M0 + * LCDC_D4 -> BT656_D1_M0 + * LCDC_D3 -> BT656_D0_M0 + * LCDC_D2 -> N/A + * LCDC_D1 -> N/A + * LCDC_D0 -> N/A + */ +#define ROCKCHIP_BT656_DATA_MAP_DATA_WITH_DUMMY_0 3 + #endif diff --git a/include/linux/memory_group_manager.h b/include/linux/memory_group_manager.h index ec55d74f56ad..8729e2dfb9e5 100644 --- a/include/linux/memory_group_manager.h +++ b/include/linux/memory_group_manager.h @@ -41,6 +41,11 @@ typedef int vm_fault_t; struct memory_group_manager_device; struct memory_group_manager_import_data; +/** + * enum mgm_pte_flags - Memory Group Manager PTE Flags + * @MMA_VIOLATION: Bit-number of flag used to indicate that Mismatched Memory Attributes (MMA) + * exist for a page. Specifically, this means CPU-uncached, GPU-cached. + */ enum mgm_pte_flags { MMA_VIOLATION = 0, }; @@ -138,11 +143,17 @@ struct memory_group_manager_ops { * decoded to determine the physical address and any other * properties of the mapping the manager requires. * - * This function allows the memory group manager to modify a GPU page - * table entry before it is stored by the kbase module (controller - * driver). It may set certain bits in the page table entry attributes - * or modify the physical address, based on the physical memory group ID, - * PBHA ID, PTE flags and/or additional data in struct memory_group_manager_device. + * This function allows the memory group manager to modify a GPU page table entry before it + * is stored by the kbase module (controller driver). It may set certain bits in the page + * table entry attributes or modify the physical address, based on the physical memory + * group ID, PBHA ID, PTE flags and/or additional data in + * struct memory_group_manager_device. + * + * If mgm_pte_flags has the MMA_VIOLATION bit set - ie, 1< +#include + +struct aiisp_aiynr_ybuf_cfg { + int dev_id; + int width; + int height; + u32 buf_cnt; + struct dma_buf *buf[RKAIISP_AIYNR_YBUF_NUM_MAX]; +}; + +#if IS_REACHABLE(CONFIG_VIDEO_ROCKCHIP_AIISP) +int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg); + +#else + +static inline int rkaiisp_cfg_aiynr_yuvbuf(struct aiisp_aiynr_ybuf_cfg *buf_cfg) +{ + return -EINVAL; +} + +#endif +#endif diff --git a/include/uapi/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h b/include/uapi/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h index 46be917cad33..7a4901258866 100644 --- a/include/uapi/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h +++ b/include/uapi/gpu/arm/valhall/backend/gpu/mali_kbase_model_dummy.h @@ -29,11 +29,7 @@ #include #define KBASE_DUMMY_MODEL_COUNTER_HEADER_DWORDS (4) -#if MALI_USE_CSF #define KBASE_DUMMY_MODEL_COUNTER_PER_CORE (65) -#else /* MALI_USE_CSF */ -#define KBASE_DUMMY_MODEL_COUNTER_PER_CORE (60) -#endif /* MALI_USE_CSF */ #define KBASE_DUMMY_MODEL_COUNTERS_PER_BIT (4) #define KBASE_DUMMY_MODEL_COUNTER_ENABLED(enable_mask, ctr_idx) \ (enable_mask & (1U << (ctr_idx / KBASE_DUMMY_MODEL_COUNTERS_PER_BIT))) diff --git a/include/uapi/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_regmap_jm.h b/include/uapi/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_regmap_jm.h deleted file mode 100644 index d24afccf49ee..000000000000 --- a/include/uapi/gpu/arm/valhall/gpu/backend/mali_kbase_gpu_regmap_jm.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _UAPI_KBASE_GPU_REGMAP_JM_H_ -#define _UAPI_KBASE_GPU_REGMAP_JM_H_ - -#endif /* _UAPI_KBASE_GPU_REGMAP_JM_H_ */ diff --git a/include/uapi/gpu/arm/valhall/gpu/mali_kbase_gpu_regmap.h b/include/uapi/gpu/arm/valhall/gpu/mali_kbase_gpu_regmap.h index 8256191f331b..84c3e8c877b7 100644 --- a/include/uapi/gpu/arm/valhall/gpu/mali_kbase_gpu_regmap.h +++ b/include/uapi/gpu/arm/valhall/gpu/mali_kbase_gpu_regmap.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * - * (C) COPYRIGHT 2019-2023 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -22,10 +22,6 @@ #ifndef _UAPI_KBASE_GPU_REGMAP_H_ #define _UAPI_KBASE_GPU_REGMAP_H_ -#if MALI_USE_CSF #include "backend/mali_kbase_gpu_regmap_csf.h" -#else -#include "backend/mali_kbase_gpu_regmap_jm.h" -#endif /* !MALI_USE_CSF */ #endif /* _UAPI_KBASE_GPU_REGMAP_H_ */ diff --git a/include/uapi/gpu/arm/valhall/jm/mali_base_jm_kernel.h b/include/uapi/gpu/arm/valhall/jm/mali_base_jm_kernel.h deleted file mode 100644 index 48a43210d03f..000000000000 --- a/include/uapi/gpu/arm/valhall/jm/mali_base_jm_kernel.h +++ /dev/null @@ -1,892 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2019-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _UAPI_BASE_JM_KERNEL_H_ -#define _UAPI_BASE_JM_KERNEL_H_ - -#include -#include "../mali_base_common_kernel.h" - -/* Similar to BASE_MEM_TILER_ALIGN_TOP, memory starting from the end of the - * initial commit is aligned to 'extension' pages, where 'extension' must be a power - * of 2 and no more than BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES - */ -#define BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP (1 << 0) - -/** - * BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE - If set, the heap info address points - * to a __u32 holding the used size in bytes; - * otherwise it points to a __u64 holding the lowest address of unused memory. - */ -#define BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE (1 << 1) - -/** - * BASE_JIT_ALLOC_VALID_FLAGS - Valid set of just-in-time memory allocation flags - * - * Note: BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE cannot be set if heap_info_gpu_addr - * in %base_jit_alloc_info is 0 (atom with BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE set - * and heap_info_gpu_addr being 0 will be rejected). - */ -#define BASE_JIT_ALLOC_VALID_FLAGS \ - (BASE_JIT_ALLOC_MEM_TILER_ALIGN_TOP | BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE) - -/* Bitpattern describing the ::base_context_create_flags that can be - * passed to base_context_init() - */ -#define BASEP_CONTEXT_CREATE_ALLOWED_FLAGS \ - (BASE_CONTEXT_CCTX_EMBEDDED | BASEP_CONTEXT_CREATE_KERNEL_FLAGS) - -/* - * Private flags used on the base context - * - * These start at bit 31, and run down to zero. - * - * They share the same space as base_context_create_flags, and so must - * not collide with them. - */ - -/* Private flag tracking whether job descriptor dumping is disabled */ -#define BASEP_CONTEXT_FLAG_JOB_DUMP_DISABLED ((base_context_create_flags)(1 << 31)) - -/* Flags for base tracepoint specific to JM */ -#define BASE_TLSTREAM_FLAGS_MASK \ - (BASE_TLSTREAM_ENABLE_LATENCY_TRACEPOINTS | BASE_TLSTREAM_JOB_DUMPING_ENABLED) -/* - * Dependency stuff, keep it private for now. May want to expose it if - * we decide to make the number of semaphores a configurable - * option. - */ -#define BASE_JD_ATOM_COUNT 256 - -/* Set/reset values for a software event */ -#define BASE_JD_SOFT_EVENT_SET ((unsigned char)1) -#define BASE_JD_SOFT_EVENT_RESET ((unsigned char)0) - -/** - * struct base_jd_udata - Per-job data - * - * @blob: per-job data array - * - * This structure is used to store per-job data, and is completely unused - * by the Base driver. It can be used to store things such as callback - * function pointer, data to handle job completion. It is guaranteed to be - * untouched by the Base driver. - */ -struct base_jd_udata { - __u64 blob[2]; -}; - -/** - * typedef base_jd_dep_type - Job dependency type. - * - * A flags field will be inserted into the atom structure to specify whether a - * dependency is a data or ordering dependency (by putting it before/after - * 'core_req' in the structure it should be possible to add without changing - * the structure size). - * When the flag is set for a particular dependency to signal that it is an - * ordering only dependency then errors will not be propagated. - */ -typedef __u8 base_jd_dep_type; - -#define BASE_JD_DEP_TYPE_INVALID (0) /**< Invalid dependency */ -#define BASE_JD_DEP_TYPE_DATA (1U << 0) /**< Data dependency */ -#define BASE_JD_DEP_TYPE_ORDER (1U << 1) /**< Order dependency */ - -/** - * typedef base_jd_core_req - Job chain hardware requirements. - * - * A job chain must specify what GPU features it needs to allow the - * driver to schedule the job correctly. By not specifying the - * correct settings can/will cause an early job termination. Multiple - * values can be ORed together to specify multiple requirements. - * Special case is ::BASE_JD_REQ_DEP, which is used to express complex - * dependencies, and that doesn't execute anything on the hardware. - */ -typedef __u32 base_jd_core_req; - -/* Requirements that come from the HW */ - -/* No requirement, dependency only - */ -#define BASE_JD_REQ_DEP ((base_jd_core_req)0) - -/* Requires fragment shaders - */ -#define BASE_JD_REQ_FS ((base_jd_core_req)1 << 0) - -/* Requires compute shaders - * - * This covers any of the following GPU job types: - * - Vertex Shader Job - * - Geometry Shader Job - * - An actual Compute Shader Job - * - * Compare this with BASE_JD_REQ_ONLY_COMPUTE, which specifies that the - * job is specifically just the "Compute Shader" job type, and not the "Vertex - * Shader" nor the "Geometry Shader" job type. - */ -#define BASE_JD_REQ_CS ((base_jd_core_req)1 << 1) - -/* Requires tiling */ -#define BASE_JD_REQ_T ((base_jd_core_req)1 << 2) - -/* Requires cache flushes */ -#define BASE_JD_REQ_CF ((base_jd_core_req)1 << 3) - -/* Requires value writeback */ -#define BASE_JD_REQ_V ((base_jd_core_req)1 << 4) - -/* SW-only requirements - the HW does not expose these as part of the job slot - * capabilities - */ - -/* Requires fragment job with AFBC encoding */ -#define BASE_JD_REQ_FS_AFBC ((base_jd_core_req)1 << 13) - -/* SW-only requirement: coalesce completion events. - * If this bit is set then completion of this atom will not cause an event to - * be sent to userspace, whether successful or not; completion events will be - * deferred until an atom completes which does not have this bit set. - * - * This bit may not be used in combination with BASE_JD_REQ_EXTERNAL_RESOURCES. - */ -#define BASE_JD_REQ_EVENT_COALESCE ((base_jd_core_req)1 << 5) - -/* SW Only requirement: the job chain requires a coherent core group. We don't - * mind which coherent core group is used. - */ -#define BASE_JD_REQ_COHERENT_GROUP ((base_jd_core_req)1 << 6) - -/* SW Only requirement: The performance counters should be enabled only when - * they are needed, to reduce power consumption. - */ -#define BASE_JD_REQ_PERMON ((base_jd_core_req)1 << 7) - -/* SW Only requirement: External resources are referenced by this atom. - * - * This bit may not be used in combination with BASE_JD_REQ_EVENT_COALESCE and - * BASE_JD_REQ_SOFT_EVENT_WAIT. - */ -#define BASE_JD_REQ_EXTERNAL_RESOURCES ((base_jd_core_req)1 << 8) - -/* SW Only requirement: Software defined job. Jobs with this bit set will not be - * submitted to the hardware but will cause some action to happen within the - * driver - */ -#define BASE_JD_REQ_SOFT_JOB ((base_jd_core_req)1 << 9) - -#define BASE_JD_REQ_SOFT_DUMP_CPU_GPU_TIME (BASE_JD_REQ_SOFT_JOB | 0x1) -#define BASE_JD_REQ_SOFT_FENCE_TRIGGER (BASE_JD_REQ_SOFT_JOB | 0x2) -#define BASE_JD_REQ_SOFT_FENCE_WAIT (BASE_JD_REQ_SOFT_JOB | 0x3) - -/* 0x4 RESERVED for now */ - -/* SW only requirement: event wait/trigger job. - * - * - BASE_JD_REQ_SOFT_EVENT_WAIT: this job will block until the event is set. - * - BASE_JD_REQ_SOFT_EVENT_SET: this job sets the event, thus unblocks the - * other waiting jobs. It completes immediately. - * - BASE_JD_REQ_SOFT_EVENT_RESET: this job resets the event, making it - * possible for other jobs to wait upon. It completes immediately. - */ -#define BASE_JD_REQ_SOFT_EVENT_WAIT (BASE_JD_REQ_SOFT_JOB | 0x5) -#define BASE_JD_REQ_SOFT_EVENT_SET (BASE_JD_REQ_SOFT_JOB | 0x6) -#define BASE_JD_REQ_SOFT_EVENT_RESET (BASE_JD_REQ_SOFT_JOB | 0x7) - -#define BASE_JD_REQ_SOFT_DEBUG_COPY (BASE_JD_REQ_SOFT_JOB | 0x8) - -/* SW only requirement: Just In Time allocation - * - * This job requests a single or multiple just-in-time allocations through a - * list of base_jit_alloc_info structure which is passed via the jc element of - * the atom. The number of base_jit_alloc_info structures present in the - * list is passed via the nr_extres element of the atom - * - * It should be noted that the id entry in base_jit_alloc_info must not - * be reused until it has been released via BASE_JD_REQ_SOFT_JIT_FREE. - * - * Should this soft job fail it is expected that a BASE_JD_REQ_SOFT_JIT_FREE - * soft job to free the JIT allocation is still made. - * - * The job will complete immediately. - */ -#define BASE_JD_REQ_SOFT_JIT_ALLOC (BASE_JD_REQ_SOFT_JOB | 0x9) - -/* SW only requirement: Just In Time free - * - * This job requests a single or multiple just-in-time allocations created by - * BASE_JD_REQ_SOFT_JIT_ALLOC to be freed. The ID list of the just-in-time - * allocations is passed via the jc element of the atom. - * - * The job will complete immediately. - */ -#define BASE_JD_REQ_SOFT_JIT_FREE (BASE_JD_REQ_SOFT_JOB | 0xa) - -/* SW only requirement: Map external resource - * - * This job requests external resource(s) are mapped once the dependencies - * of the job have been satisfied. The list of external resources are - * passed via the jc element of the atom which is a pointer to a - * base_external_resource_list. - */ -#define BASE_JD_REQ_SOFT_EXT_RES_MAP (BASE_JD_REQ_SOFT_JOB | 0xb) - -/* SW only requirement: Unmap external resource - * - * This job requests external resource(s) are unmapped once the dependencies - * of the job has been satisfied. The list of external resources are - * passed via the jc element of the atom which is a pointer to a - * base_external_resource_list. - */ -#define BASE_JD_REQ_SOFT_EXT_RES_UNMAP (BASE_JD_REQ_SOFT_JOB | 0xc) - -/* HW Requirement: Requires Compute shaders (but not Vertex or Geometry Shaders) - * - * This indicates that the Job Chain contains GPU jobs of the 'Compute - * Shaders' type. - * - * In contrast to BASE_JD_REQ_CS, this does not indicate that the Job - * Chain contains 'Geometry Shader' or 'Vertex Shader' jobs. - */ -#define BASE_JD_REQ_ONLY_COMPUTE ((base_jd_core_req)1 << 10) - -/* HW Requirement: Use the base_jd_atom::device_nr field to specify a - * particular core group - * - * If both BASE_JD_REQ_COHERENT_GROUP and this flag are set, this flag - * takes priority - * - * This is only guaranteed to work for BASE_JD_REQ_ONLY_COMPUTE atoms. - */ -#define BASE_JD_REQ_SPECIFIC_COHERENT_GROUP ((base_jd_core_req)1 << 11) - -/* SW Flag: If this bit is set then the successful completion of this atom - * will not cause an event to be sent to userspace - */ -#define BASE_JD_REQ_EVENT_ONLY_ON_FAILURE ((base_jd_core_req)1 << 12) - -/* SW Flag: If this bit is set then completion of this atom will not cause an - * event to be sent to userspace, whether successful or not. - */ -#define BASEP_JD_REQ_EVENT_NEVER ((base_jd_core_req)1 << 14) - -/* SW Flag: Skip GPU cache clean and invalidation before starting a GPU job. - * - * If this bit is set then the GPU's cache will not be cleaned and invalidated - * until a GPU job starts which does not have this bit set or a job completes - * which does not have the BASE_JD_REQ_SKIP_CACHE_END bit set. Do not use - * if the CPU may have written to memory addressed by the job since the last job - * without this bit set was submitted. - */ -#define BASE_JD_REQ_SKIP_CACHE_START ((base_jd_core_req)1 << 15) - -/* SW Flag: Skip GPU cache clean and invalidation after a GPU job completes. - * - * If this bit is set then the GPU's cache will not be cleaned and invalidated - * until a GPU job completes which does not have this bit set or a job starts - * which does not have the BASE_JD_REQ_SKIP_CACHE_START bit set. Do not use - * if the CPU may read from or partially overwrite memory addressed by the job - * before the next job without this bit set completes. - */ -#define BASE_JD_REQ_SKIP_CACHE_END ((base_jd_core_req)1 << 16) - -/* Request the atom be executed on a specific job slot. - * - * When this flag is specified, it takes precedence over any existing job slot - * selection logic. - */ -#define BASE_JD_REQ_JOB_SLOT ((base_jd_core_req)1 << 17) - -/* SW-only requirement: The atom needs to run on a limited core mask affinity. - * - * If this bit is set then the kbase_context.limited_core_mask will be applied - * to the affinity. - */ -#define BASE_JD_REQ_LIMITED_CORE_MASK ((base_jd_core_req)1 << 20) - -/* These requirement bits are currently unused in base_jd_core_req - */ -#define BASEP_JD_REQ_RESERVED \ - (~(BASE_JD_REQ_ATOM_TYPE | BASE_JD_REQ_EXTERNAL_RESOURCES | \ - BASE_JD_REQ_EVENT_ONLY_ON_FAILURE | BASEP_JD_REQ_EVENT_NEVER | \ - BASE_JD_REQ_EVENT_COALESCE | BASE_JD_REQ_COHERENT_GROUP | \ - BASE_JD_REQ_SPECIFIC_COHERENT_GROUP | BASE_JD_REQ_FS_AFBC | BASE_JD_REQ_PERMON | \ - BASE_JD_REQ_SKIP_CACHE_START | BASE_JD_REQ_SKIP_CACHE_END | BASE_JD_REQ_JOB_SLOT | \ - BASE_JD_REQ_LIMITED_CORE_MASK)) - -/* Mask of all bits in base_jd_core_req that control the type of the atom. - * - * This allows dependency only atoms to have flags set - */ -#define BASE_JD_REQ_ATOM_TYPE \ - (BASE_JD_REQ_FS | BASE_JD_REQ_CS | BASE_JD_REQ_T | BASE_JD_REQ_CF | BASE_JD_REQ_V | \ - BASE_JD_REQ_SOFT_JOB | BASE_JD_REQ_ONLY_COMPUTE) - -/** - * BASE_JD_REQ_SOFT_JOB_TYPE - Mask of all bits in base_jd_core_req that - * controls the type of a soft job. - */ -#define BASE_JD_REQ_SOFT_JOB_TYPE (BASE_JD_REQ_SOFT_JOB | 0x1f) - -/* Returns non-zero value if core requirements passed define a soft job or - * a dependency only job. - */ -#define BASE_JD_REQ_SOFT_JOB_OR_DEP(core_req) \ - (((core_req)&BASE_JD_REQ_SOFT_JOB) || ((core_req)&BASE_JD_REQ_ATOM_TYPE) == BASE_JD_REQ_DEP) - -/** - * enum kbase_jd_atom_state - Atom states - * - * @KBASE_JD_ATOM_STATE_UNUSED: Atom is not used. - * @KBASE_JD_ATOM_STATE_QUEUED: Atom is queued in JD. - * @KBASE_JD_ATOM_STATE_IN_JS: Atom has been given to JS (is runnable/running). - * @KBASE_JD_ATOM_STATE_HW_COMPLETED: Atom has been completed, but not yet - * handed back to job dispatcher for - * dependency resolution. - * @KBASE_JD_ATOM_STATE_COMPLETED: Atom has been completed, but not yet handed - * back to userspace. - */ -enum kbase_jd_atom_state { - KBASE_JD_ATOM_STATE_UNUSED, - KBASE_JD_ATOM_STATE_QUEUED, - KBASE_JD_ATOM_STATE_IN_JS, - KBASE_JD_ATOM_STATE_HW_COMPLETED, - KBASE_JD_ATOM_STATE_COMPLETED -}; - -/** - * typedef base_atom_id - Type big enough to store an atom number in. - */ -typedef __u8 base_atom_id; - -/** - * struct base_dependency - base dependency - * - * @atom_id: An atom number - * @dependency_type: Dependency type - */ -struct base_dependency { - base_atom_id atom_id; - base_jd_dep_type dependency_type; -}; - -/** - * typedef base_jd_prio - Base Atom priority. - * - * Only certain priority levels are actually implemented, as specified by the - * BASE_JD_PRIO_<...> definitions below. It is undefined to use a priority - * level that is not one of those defined below. - * - * Priority levels only affect scheduling after the atoms have had dependencies - * resolved. For example, a low priority atom that has had its dependencies - * resolved might run before a higher priority atom that has not had its - * dependencies resolved. - * - * In general, fragment atoms do not affect non-fragment atoms with - * lower priorities, and vice versa. One exception is that there is only one - * priority value for each context. So a high-priority (e.g.) fragment atom - * could increase its context priority, causing its non-fragment atoms to also - * be scheduled sooner. - * - * The atoms are scheduled as follows with respect to their priorities: - * * Let atoms 'X' and 'Y' be for the same job slot who have dependencies - * resolved, and atom 'X' has a higher priority than atom 'Y' - * * If atom 'Y' is currently running on the HW, then it is interrupted to - * allow atom 'X' to run soon after - * * If instead neither atom 'Y' nor atom 'X' are running, then when choosing - * the next atom to run, atom 'X' will always be chosen instead of atom 'Y' - * * Any two atoms that have the same priority could run in any order with - * respect to each other. That is, there is no ordering constraint between - * atoms of the same priority. - * - * The sysfs file 'js_ctx_scheduling_mode' is used to control how atoms are - * scheduled between contexts. The default value, 0, will cause higher-priority - * atoms to be scheduled first, regardless of their context. The value 1 will - * use a round-robin algorithm when deciding which context's atoms to schedule - * next, so higher-priority atoms can only preempt lower priority atoms within - * the same context. See KBASE_JS_SYSTEM_PRIORITY_MODE and - * KBASE_JS_PROCESS_LOCAL_PRIORITY_MODE for more details. - */ -typedef __u8 base_jd_prio; - -/* Medium atom priority. This is a priority higher than BASE_JD_PRIO_LOW */ -#define BASE_JD_PRIO_MEDIUM ((base_jd_prio)0) -/* High atom priority. This is a priority higher than BASE_JD_PRIO_MEDIUM and - * BASE_JD_PRIO_LOW - */ -#define BASE_JD_PRIO_HIGH ((base_jd_prio)1) -/* Low atom priority. */ -#define BASE_JD_PRIO_LOW ((base_jd_prio)2) -/* Real-Time atom priority. This is a priority higher than BASE_JD_PRIO_HIGH, - * BASE_JD_PRIO_MEDIUM, and BASE_JD_PRIO_LOW - */ -#define BASE_JD_PRIO_REALTIME ((base_jd_prio)3) - -/* Invalid atom priority (max uint8_t value) */ -#define BASE_JD_PRIO_INVALID ((base_jd_prio)255) - -/* Count of the number of priority levels. This itself is not a valid - * base_jd_prio setting - */ -#define BASE_JD_NR_PRIO_LEVELS 4 - -/** - * struct base_jd_atom_v2 - Node of a dependency graph used to submit a - * GPU job chain or soft-job to the kernel driver. - * - * @jc: GPU address of a job chain. - * @udata: User data. - * @extres_list: List of external resources. - * @nr_extres: Number of external resources or JIT allocations. - * @jit_id: Zero-terminated array of IDs of just-in-time memory - * allocations written to by the atom. When the atom - * completes, the value stored at the - * &struct_base_jit_alloc_info.heap_info_gpu_addr of - * each allocation is read in order to enforce an - * overall physical memory usage limit. - * @pre_dep: Pre-dependencies. One need to use SETTER function to assign - * this field; this is done in order to reduce possibility of - * improper assignment of a dependency field. - * @atom_number: Unique number to identify the atom. - * @prio: Atom priority. Refer to base_jd_prio for more details. - * @device_nr: Core group when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP - * specified. - * @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified. - * @core_req: Core requirements. - * @padding: Unused. Must be zero. - * - * This structure has changed since UK 10.2 for which base_jd_core_req was a - * __u16 value. - * - * In UK 10.3 a core_req field of a __u32 type was added to the end of the - * structure, and the place in the structure previously occupied by __u16 - * core_req was kept but renamed to compat_core_req. - * - * From UK 11.20 - compat_core_req is now occupied by __u8 jit_id[2]. - * Compatibility with UK 10.x from UK 11.y is not handled because - * the major version increase prevents this. - * - * For UK 11.20 jit_id[2] must be initialized to zero. - */ -struct base_jd_atom_v2 { - __u64 jc; - struct base_jd_udata udata; - __u64 extres_list; - __u16 nr_extres; - __u8 jit_id[2]; - struct base_dependency pre_dep[2]; - base_atom_id atom_number; - base_jd_prio prio; - __u8 device_nr; - __u8 jobslot; - base_jd_core_req core_req; - __u8 padding[8]; -}; - -/** - * struct base_jd_atom - Same as base_jd_atom_v2, but has an extra seq_nr - * at the beginning. - * - * @seq_nr: Sequence number of logical grouping of atoms. - * @jc: GPU address of a job chain. - * @udata: User data. - * @extres_list: List of external resources. - * @nr_extres: Number of external resources or JIT allocations. - * @jit_id: Zero-terminated array of IDs of just-in-time memory - * allocations written to by the atom. When the atom - * completes, the value stored at the - * &struct_base_jit_alloc_info.heap_info_gpu_addr of - * each allocation is read in order to enforce an - * overall physical memory usage limit. - * @pre_dep: Pre-dependencies. One need to use SETTER function to assign - * this field; this is done in order to reduce possibility of - * improper assignment of a dependency field. - * @atom_number: Unique number to identify the atom. - * @prio: Atom priority. Refer to base_jd_prio for more details. - * @device_nr: Core group when BASE_JD_REQ_SPECIFIC_COHERENT_GROUP - * specified. - * @jobslot: Job slot to use when BASE_JD_REQ_JOB_SLOT is specified. - * @core_req: Core requirements. - * @renderpass_id: Renderpass identifier used to associate an atom that has - * BASE_JD_REQ_START_RENDERPASS set in its core requirements - * with an atom that has BASE_JD_REQ_END_RENDERPASS set. - * @padding: Unused. Must be zero. - */ -typedef struct base_jd_atom { - __u64 seq_nr; - __u64 jc; - struct base_jd_udata udata; - __u64 extres_list; - __u16 nr_extres; - __u8 jit_id[2]; - struct base_dependency pre_dep[2]; - base_atom_id atom_number; - base_jd_prio prio; - __u8 device_nr; - __u8 jobslot; - base_jd_core_req core_req; - __u8 renderpass_id; - __u8 padding[7]; -} base_jd_atom; - -/* Job chain event code bits - * Defines the bits used to create ::base_jd_event_code - */ -enum { - BASE_JD_SW_EVENT_KERNEL = (1u << 15), /* Kernel side event */ - BASE_JD_SW_EVENT = (1u << 14), /* SW defined event */ - /* Event indicates success (SW events only) */ - BASE_JD_SW_EVENT_SUCCESS = (1u << 13), - BASE_JD_SW_EVENT_JOB = (0u << 11), /* Job related event */ - BASE_JD_SW_EVENT_BAG = (1u << 11), /* Bag related event */ - BASE_JD_SW_EVENT_INFO = (2u << 11), /* Misc/info event */ - BASE_JD_SW_EVENT_RESERVED = (3u << 11), /* Reserved event type */ - /* Mask to extract the type from an event code */ - BASE_JD_SW_EVENT_TYPE_MASK = (3u << 11) -}; - -/** - * enum base_jd_event_code - Job chain event codes - * - * @BASE_JD_EVENT_RANGE_HW_NONFAULT_START: Start of hardware non-fault status - * codes. - * Obscurely, BASE_JD_EVENT_TERMINATED - * indicates a real fault, because the - * job was hard-stopped. - * @BASE_JD_EVENT_NOT_STARTED: Can't be seen by userspace, treated as - * 'previous job done'. - * @BASE_JD_EVENT_STOPPED: Can't be seen by userspace, becomes - * TERMINATED, DONE or JOB_CANCELLED. - * @BASE_JD_EVENT_TERMINATED: This is actually a fault status code - the job - * was hard stopped. - * @BASE_JD_EVENT_ACTIVE: Can't be seen by userspace, jobs only returned on - * complete/fail/cancel. - * @BASE_JD_EVENT_RANGE_HW_NONFAULT_END: End of hardware non-fault status codes. - * Obscurely, BASE_JD_EVENT_TERMINATED - * indicates a real fault, - * because the job was hard-stopped. - * @BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START: Start of hardware fault and - * software error status codes. - * @BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END: End of hardware fault and - * software error status codes. - * @BASE_JD_EVENT_RANGE_SW_SUCCESS_START: Start of software success status - * codes. - * @BASE_JD_EVENT_RANGE_SW_SUCCESS_END: End of software success status codes. - * @BASE_JD_EVENT_RANGE_KERNEL_ONLY_START: Start of kernel-only status codes. - * Such codes are never returned to - * user-space. - * @BASE_JD_EVENT_RANGE_KERNEL_ONLY_END: End of kernel-only status codes. - * @BASE_JD_EVENT_DONE: atom has completed successfull - * @BASE_JD_EVENT_JOB_CONFIG_FAULT: Atom dependencies configuration error which - * shall result in a failed atom - * @BASE_JD_EVENT_JOB_POWER_FAULT: The job could not be executed because the - * part of the memory system required to access - * job descriptors was not powered on - * @BASE_JD_EVENT_JOB_READ_FAULT: Reading a job descriptor into the Job - * manager failed - * @BASE_JD_EVENT_JOB_WRITE_FAULT: Writing a job descriptor from the Job - * manager failed - * @BASE_JD_EVENT_JOB_AFFINITY_FAULT: The job could not be executed because the - * specified affinity mask does not intersect - * any available cores - * @BASE_JD_EVENT_JOB_BUS_FAULT: A bus access failed while executing a job - * @BASE_JD_EVENT_INSTR_INVALID_PC: A shader instruction with an illegal program - * counter was executed. - * @BASE_JD_EVENT_INSTR_INVALID_ENC: A shader instruction with an illegal - * encoding was executed. - * @BASE_JD_EVENT_INSTR_TYPE_MISMATCH: A shader instruction was executed where - * the instruction encoding did not match the - * instruction type encoded in the program - * counter. - * @BASE_JD_EVENT_INSTR_OPERAND_FAULT: A shader instruction was executed that - * contained invalid combinations of operands. - * @BASE_JD_EVENT_INSTR_TLS_FAULT: A shader instruction was executed that tried - * to access the thread local storage section - * of another thread. - * @BASE_JD_EVENT_INSTR_ALIGN_FAULT: A shader instruction was executed that - * tried to do an unsupported unaligned memory - * access. - * @BASE_JD_EVENT_INSTR_BARRIER_FAULT: A shader instruction was executed that - * failed to complete an instruction barrier. - * @BASE_JD_EVENT_DATA_INVALID_FAULT: Any data structure read as part of the job - * contains invalid combinations of data. - * @BASE_JD_EVENT_TILE_RANGE_FAULT: Tile or fragment shading was asked to - * process a tile that is entirely outside the - * bounding box of the frame. - * @BASE_JD_EVENT_STATE_FAULT: Matches ADDR_RANGE_FAULT. A virtual address - * has been found that exceeds the virtual - * address range. - * @BASE_JD_EVENT_OUT_OF_MEMORY: The tiler ran out of memory when executing a job. - * @BASE_JD_EVENT_UNKNOWN: If multiple jobs in a job chain fail, only - * the first one the reports an error will set - * and return full error information. - * Subsequent failing jobs will not update the - * error status registers, and may write an - * error status of UNKNOWN. - * @BASE_JD_EVENT_DELAYED_BUS_FAULT: The GPU received a bus fault for access to - * physical memory where the original virtual - * address is no longer available. - * @BASE_JD_EVENT_SHAREABILITY_FAULT: Matches GPU_SHAREABILITY_FAULT. A cache - * has detected that the same line has been - * accessed as both shareable and non-shareable - * memory from inside the GPU. - * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1: A memory access hit an invalid table - * entry at level 1 of the translation table. - * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2: A memory access hit an invalid table - * entry at level 2 of the translation table. - * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3: A memory access hit an invalid table - * entry at level 3 of the translation table. - * @BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4: A memory access hit an invalid table - * entry at level 4 of the translation table. - * @BASE_JD_EVENT_PERMISSION_FAULT: A memory access could not be allowed due to - * the permission flags set in translation - * table - * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1: A bus fault occurred while reading - * level 0 of the translation tables. - * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2: A bus fault occurred while reading - * level 1 of the translation tables. - * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3: A bus fault occurred while reading - * level 2 of the translation tables. - * @BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4: A bus fault occurred while reading - * level 3 of the translation tables. - * @BASE_JD_EVENT_ACCESS_FLAG: Matches ACCESS_FLAG_0. A memory access hit a - * translation table entry with the ACCESS_FLAG - * bit set to zero in level 0 of the - * page table, and the DISABLE_AF_FAULT flag - * was not set. - * @BASE_JD_EVENT_MEM_GROWTH_FAILED: raised for JIT_ALLOC atoms that failed to - * grow memory on demand - * @BASE_JD_EVENT_JOB_CANCELLED: raised when this atom was hard-stopped or its - * dependencies failed - * @BASE_JD_EVENT_JOB_INVALID: raised for many reasons, including invalid data - * in the atom which overlaps with - * BASE_JD_EVENT_JOB_CONFIG_FAULT, or if the - * platform doesn't support the feature specified in - * the atom. - * @BASE_JD_EVENT_DRV_TERMINATED: this is a special event generated to indicate - * to userspace that the KBase context has been - * destroyed and Base should stop listening for - * further events - * @BASE_JD_EVENT_REMOVED_FROM_NEXT: raised when an atom that was configured in - * the GPU has to be retried (but it has not - * started) due to e.g., GPU reset - * HW and low-level SW events are represented by event codes. - * The status of jobs which succeeded are also represented by - * an event code (see @BASE_JD_EVENT_DONE). - * Events are usually reported as part of a &struct base_jd_event. - * - * The event codes are encoded in the following way: - * * 10:0 - subtype - * * 12:11 - type - * * 13 - SW success (only valid if the SW bit is set) - * * 14 - SW event (HW event if not set) - * * 15 - Kernel event (should never be seen in userspace) - * - * Events are split up into ranges as follows: - * * BASE_JD_EVENT_RANGE__START - * * BASE_JD_EVENT_RANGE__END - * - * code is in 's range when: - * BASE_JD_EVENT_RANGE__START <= code < - * BASE_JD_EVENT_RANGE__END - * - * Ranges can be asserted for adjacency by testing that the END of the previous - * is equal to the START of the next. This is useful for optimizing some tests - * for range. - * - * A limitation is that the last member of this enum must explicitly be handled - * (with an assert-unreachable statement) in switch statements that use - * variables of this type. Otherwise, the compiler warns that we have not - * handled that enum value. - */ -enum base_jd_event_code { - /* HW defined exceptions */ - BASE_JD_EVENT_RANGE_HW_NONFAULT_START = 0, - - /* non-fatal exceptions */ - BASE_JD_EVENT_NOT_STARTED = 0x00, - BASE_JD_EVENT_DONE = 0x01, - BASE_JD_EVENT_STOPPED = 0x03, - BASE_JD_EVENT_TERMINATED = 0x04, - BASE_JD_EVENT_ACTIVE = 0x08, - - BASE_JD_EVENT_RANGE_HW_NONFAULT_END = 0x40, - BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_START = 0x40, - - /* job exceptions */ - BASE_JD_EVENT_JOB_CONFIG_FAULT = 0x40, - BASE_JD_EVENT_JOB_POWER_FAULT = 0x41, - BASE_JD_EVENT_JOB_READ_FAULT = 0x42, - BASE_JD_EVENT_JOB_WRITE_FAULT = 0x43, - BASE_JD_EVENT_JOB_AFFINITY_FAULT = 0x44, - BASE_JD_EVENT_JOB_BUS_FAULT = 0x48, - BASE_JD_EVENT_INSTR_INVALID_PC = 0x50, - BASE_JD_EVENT_INSTR_INVALID_ENC = 0x51, - BASE_JD_EVENT_INSTR_TYPE_MISMATCH = 0x52, - BASE_JD_EVENT_INSTR_OPERAND_FAULT = 0x53, - BASE_JD_EVENT_INSTR_TLS_FAULT = 0x54, - BASE_JD_EVENT_INSTR_BARRIER_FAULT = 0x55, - BASE_JD_EVENT_INSTR_ALIGN_FAULT = 0x56, - BASE_JD_EVENT_DATA_INVALID_FAULT = 0x58, - BASE_JD_EVENT_TILE_RANGE_FAULT = 0x59, - BASE_JD_EVENT_STATE_FAULT = 0x5A, - BASE_JD_EVENT_OUT_OF_MEMORY = 0x60, - BASE_JD_EVENT_UNKNOWN = 0x7F, - - /* GPU exceptions */ - BASE_JD_EVENT_DELAYED_BUS_FAULT = 0x80, - BASE_JD_EVENT_SHAREABILITY_FAULT = 0x88, - - /* MMU exceptions */ - BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL1 = 0xC1, - BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL2 = 0xC2, - BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL3 = 0xC3, - BASE_JD_EVENT_TRANSLATION_FAULT_LEVEL4 = 0xC4, - BASE_JD_EVENT_PERMISSION_FAULT = 0xC8, - BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL1 = 0xD1, - BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL2 = 0xD2, - BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL3 = 0xD3, - BASE_JD_EVENT_TRANSTAB_BUS_FAULT_LEVEL4 = 0xD4, - BASE_JD_EVENT_ACCESS_FLAG = 0xD8, - - /* SW defined exceptions */ - BASE_JD_EVENT_MEM_GROWTH_FAILED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x000, - BASE_JD_EVENT_JOB_CANCELLED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x002, - BASE_JD_EVENT_JOB_INVALID = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_JOB | 0x003, - - BASE_JD_EVENT_RANGE_HW_FAULT_OR_SW_ERROR_END = BASE_JD_SW_EVENT | - BASE_JD_SW_EVENT_RESERVED | 0x3FF, - - BASE_JD_EVENT_RANGE_SW_SUCCESS_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | 0x000, - - BASE_JD_EVENT_DRV_TERMINATED = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | - BASE_JD_SW_EVENT_INFO | 0x000, - - BASE_JD_EVENT_RANGE_SW_SUCCESS_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_SUCCESS | - BASE_JD_SW_EVENT_RESERVED | 0x3FF, - - BASE_JD_EVENT_RANGE_KERNEL_ONLY_START = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | 0x000, - BASE_JD_EVENT_REMOVED_FROM_NEXT = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | - BASE_JD_SW_EVENT_JOB | 0x000, - - BASE_JD_EVENT_RANGE_KERNEL_ONLY_END = BASE_JD_SW_EVENT | BASE_JD_SW_EVENT_KERNEL | - BASE_JD_SW_EVENT_RESERVED | 0x3FF -}; - -/** - * struct base_jd_event_v2 - Event reporting structure - * - * @event_code: event code of type @ref base_jd_event_code. - * @atom_number: the atom number that has completed. - * @padding: padding. - * @udata: user data. - * - * This structure is used by the kernel driver to report information - * about GPU events. They can either be HW-specific events or low-level - * SW events, such as job-chain completion. - * - * The event code contains an event type field which can be extracted - * by ANDing with BASE_JD_SW_EVENT_TYPE_MASK. - */ -struct base_jd_event_v2 { - __u32 event_code; - base_atom_id atom_number; - __u8 padding[3]; - struct base_jd_udata udata; -}; - -/** - * struct base_dump_cpu_gpu_counters - Structure for - * BASE_JD_REQ_SOFT_DUMP_CPU_GPU_COUNTERS - * jobs. - * @system_time: gpu timestamp - * @cycle_counter: gpu cycle count - * @sec: cpu time(sec) - * @usec: cpu time(usec) - * @padding: padding - * - * This structure is stored into the memory pointed to by the @jc field - * of &struct base_jd_atom. - * - * It must not occupy the same CPU cache line(s) as any neighboring data. - * This is to avoid cases where access to pages containing the structure - * is shared between cached and un-cached memory regions, which would - * cause memory corruption. - */ - -struct base_dump_cpu_gpu_counters { - __u64 system_time; - __u64 cycle_counter; - __u64 sec; - __u32 usec; - __u8 padding[36]; -}; - -/** - * struct mali_base_gpu_core_props - GPU core props info - * - * @product_id: Pro specific value. - * @version_status: Status of the GPU release. No defined values, but starts at - * 0 and increases by one for each release status (alpha, beta, EAC, etc.). - * 4 bit values (0-15). - * @minor_revision: Minor release number of the GPU. "P" part of an "RnPn" - * release number. - * 8 bit values (0-255). - * @major_revision: Major release number of the GPU. "R" part of an "RnPn" - * release number. - * 4 bit values (0-15). - * @padding: padding to align to 8-byte - * @gpu_freq_khz_max: The maximum GPU frequency. Reported to applications by - * clGetDeviceInfo() - * @log2_program_counter_size: Size of the shader program counter, in bits. - * @texture_features: TEXTURE_FEATURES_x registers, as exposed by the GPU. This - * is a bitpattern where a set bit indicates that the format is supported. - * Before using a texture format, it is recommended that the corresponding - * bit be checked. - * @paddings_1: Padding bytes. - * @gpu_available_memory_size: Theoretical maximum memory available to the GPU. - * It is unlikely that a client will be able to allocate all of this memory - * for their own purposes, but this at least provides an upper bound on the - * memory available to the GPU. - * This is required for OpenCL's clGetDeviceInfo() call when - * CL_DEVICE_GLOBAL_MEM_SIZE is requested, for OpenCL GPU devices. The - * client will not be expecting to allocate anywhere near this value. - * @num_exec_engines: The number of execution engines. Only valid for tGOX - * (Bifrost) GPUs, where GPU_HAS_REG_CORE_FEATURES is defined. Otherwise, - * this is always 0. - * @paddings_2: Padding bytes. - */ -struct mali_base_gpu_core_props { - __u32 product_id; - __u16 version_status; - __u16 minor_revision; - __u16 major_revision; - __u16 padding; - __u32 gpu_freq_khz_max; - __u32 log2_program_counter_size; - __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; - __u8 paddings_1[4]; - __u64 gpu_available_memory_size; - __u8 num_exec_engines; - __u8 paddings_2[7]; -}; - -#endif /* _UAPI_BASE_JM_KERNEL_H_ */ diff --git a/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_ioctl.h b/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_ioctl.h deleted file mode 100644 index be554da15ba3..000000000000 --- a/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_ioctl.h +++ /dev/null @@ -1,274 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _UAPI_KBASE_JM_IOCTL_H_ -#define _UAPI_KBASE_JM_IOCTL_H_ - -#include -#include - -/* - * 11.1: - * - Add BASE_MEM_TILER_ALIGN_TOP under base_mem_alloc_flags - * 11.2: - * - KBASE_MEM_QUERY_FLAGS can return KBASE_REG_PF_GROW and KBASE_REG_PROTECTED, - * which some user-side clients prior to 11.2 might fault if they received - * them - * 11.3: - * - New ioctls KBASE_IOCTL_STICKY_RESOURCE_MAP and - * KBASE_IOCTL_STICKY_RESOURCE_UNMAP - * 11.4: - * - New ioctl KBASE_IOCTL_MEM_FIND_GPU_START_AND_OFFSET - * 11.5: - * - New ioctl: KBASE_IOCTL_MEM_JIT_INIT (old ioctl renamed to _OLD) - * 11.6: - * - Added flags field to base_jit_alloc_info structure, which can be used to - * specify pseudo chunked tiler alignment for JIT allocations. - * 11.7: - * - Removed UMP support - * 11.8: - * - Added BASE_MEM_UNCACHED_GPU under base_mem_alloc_flags - * 11.9: - * - Added BASE_MEM_PERMANENT_KERNEL_MAPPING and BASE_MEM_FLAGS_KERNEL_ONLY - * under base_mem_alloc_flags - * 11.10: - * - Enabled the use of nr_extres field of base_jd_atom_v2 structure for - * JIT_ALLOC and JIT_FREE type softjobs to enable multiple JIT allocations - * with one softjob. - * 11.11: - * - Added BASE_MEM_GPU_VA_SAME_4GB_PAGE under base_mem_alloc_flags - * 11.12: - * - Removed ioctl: KBASE_IOCTL_GET_PROFILING_CONTROLS - * 11.13: - * - New ioctl: KBASE_IOCTL_MEM_EXEC_INIT - * 11.14: - * - Add BASE_MEM_GROUP_ID_MASK, base_mem_group_id_get, base_mem_group_id_set - * under base_mem_alloc_flags - * 11.15: - * - Added BASEP_CONTEXT_MMU_GROUP_ID_MASK under base_context_create_flags. - * - Require KBASE_IOCTL_SET_FLAGS before BASE_MEM_MAP_TRACKING_HANDLE can be - * passed to mmap(). - * 11.16: - * - Extended ioctl KBASE_IOCTL_MEM_SYNC to accept imported dma-buf. - * - Modified (backwards compatible) ioctl KBASE_IOCTL_MEM_IMPORT behavior for - * dma-buf. Now, buffers are mapped on GPU when first imported, no longer - * requiring external resource or sticky resource tracking. UNLESS, - * CONFIG_MALI_DMA_BUF_MAP_ON_DEMAND is enabled. - * 11.17: - * - Added BASE_JD_REQ_JOB_SLOT. - * - Reused padding field in base_jd_atom_v2 to pass job slot number. - * - New ioctl: KBASE_IOCTL_GET_CPU_GPU_TIMEINFO - * 11.18: - * - Added BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP under base_mem_alloc_flags - * 11.19: - * - Extended base_jd_atom_v2 to allow a renderpass ID to be specified. - * 11.20: - * - Added new phys_pages member to kbase_ioctl_mem_jit_init for - * KBASE_IOCTL_MEM_JIT_INIT, previous variants of this renamed to use _10_2 - * (replacing '_OLD') and _11_5 suffixes - * - Replaced compat_core_req (deprecated in 10.3) with jit_id[2] in - * base_jd_atom_v2. It must currently be initialized to zero. - * - Added heap_info_gpu_addr to base_jit_alloc_info, and - * BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE allowable in base_jit_alloc_info's - * flags member. Previous variants of this structure are kept and given _10_2 - * and _11_5 suffixes. - * - The above changes are checked for safe values in usual builds - * 11.21: - * - v2.0 of mali_trace debugfs file, which now versions the file separately - * 11.22: - * - Added base_jd_atom (v3), which is seq_nr + base_jd_atom_v2. - * KBASE_IOCTL_JOB_SUBMIT supports both in parallel. - * 11.23: - * - Modified KBASE_IOCTL_MEM_COMMIT behavior to reject requests to modify - * the physical memory backing of JIT allocations. This was not supposed - * to be a valid use case, but it was allowed by the previous implementation. - * 11.24: - * - Added a sysfs file 'serialize_jobs' inside a new sub-directory - * 'scheduling'. - * 11.25: - * - Enabled JIT pressure limit in base/kbase by default - * 11.26 - * - Added kinstr_jm API - * 11.27 - * - Backwards compatible extension to HWC ioctl. - * 11.28: - * - Added kernel side cache ops needed hint - * 11.29: - * - Reserve ioctl 52 - * 11.30: - * - Add a new priority level BASE_JD_PRIO_REALTIME - * - Add ioctl 54: This controls the priority setting. - * 11.31: - * - Added BASE_JD_REQ_LIMITED_CORE_MASK. - * - Added ioctl 55: set_limited_core_count. - * 11.32: - * - Added new HW performance counters interface to all GPUs. - * 11.33: - * - Removed Kernel legacy HWC interface - * 11.34: - * - First release of new HW performance counters interface. - * 11.35: - * - Dummy model (no mali) backend will now clear HWC values after each sample - * 11.36: - * - Remove legacy definitions: - * - base_jit_alloc_info_10_2 - * - base_jit_alloc_info_11_5 - * - kbase_ioctl_mem_jit_init_10_2 - * - kbase_ioctl_mem_jit_init_11_5 - * 11.37: - * - Fix kinstr_prfcnt issues: - * - Missing implicit sample for CMD_STOP when HWCNT buffer is full. - * - Race condition when stopping periodic sampling. - * - prfcnt_block_metadata::block_idx gaps. - * - PRFCNT_CONTROL_CMD_SAMPLE_ASYNC is removed. - * 11.38: - * - Relax the requirement to create a mapping with BASE_MEM_MAP_TRACKING_HANDLE - * before allocating GPU memory for the context. - * - CPU mappings of USER_BUFFER imported memory handles must be cached. - * 11.39: - * - Restrict child process from doing supported file operations (like mmap, ioctl, - * read, poll) on the file descriptor of mali device file that was inherited - * from the parent process. - * 11.40: - * - Remove KBASE_IOCTL_HWCNT_READER_SETUP and KBASE_HWCNT_READER_* ioctls. - * - Made the BASE_MEM_DONT_NEED memory flag queryable. - * 11.41: - * - Disallows changing the sharability on the GPU of imported dma-bufs to - * BASE_MEM_COHERENT_SYSTEM using KBASE_IOCTL_MEM_FLAGS_CHANGE. - * 11.42: - * - Implement full block state support for hardware counters. - * 11.43: - * - Made the BASE_MEM_IMPORT_SYNC_ON_MAP_UNMAP and BASE_MEM_KERNEL_SYNC memory - * flags queryable. - * 11.44: - * - Made the SAME_VA memory flag queryable. - * 11.45: - * - Re-allow child process to do supported file operations (like mmap, ioctl - * read, poll) on the file descriptor of mali device that was inherited - * from the parent process. - * 11.46: - * - Remove renderpass_id from base_jd_atom_v2 to deprecate support for JM Incremental Rendering - * 11.47: - * - Reject non-protected allocations containing the BASE_MEM_PROTECTED memory flag. - * - Reject allocations containing the BASE_MEM_DONT_NEED memory flag (it is only settable). - * - Reject allocations containing the BASE_MEM_UNUSED_BIT_xx memory flags. - * 11.48: - * - Add UNUSED_BIT_5, UNUSED_BIT_7, UNUSED_BIT_27 and UNUSED_BIT_29 previously occupied by - * kernel-only flags to kbase cap table. - * 11.49: - * - Increased KBASE_MEM_PROFILE_MAX_BUF_SIZE for more cctx memory classes. - */ - -#define BASE_UK_VERSION_MAJOR 11 -#define BASE_UK_VERSION_MINOR 49 - -/** - * struct kbase_ioctl_version_check - Check version compatibility between - * kernel and userspace - * - * @major: Major version number - * @minor: Minor version number - */ -struct kbase_ioctl_version_check { - __u16 major; - __u16 minor; -}; - -#define KBASE_IOCTL_VERSION_CHECK _IOWR(KBASE_IOCTL_TYPE, 0, struct kbase_ioctl_version_check) - -/** - * struct kbase_ioctl_job_submit - Submit jobs/atoms to the kernel - * - * @addr: Memory address of an array of struct base_jd_atom_v2 or v3 - * @nr_atoms: Number of entries in the array - * @stride: sizeof(struct base_jd_atom_v2) or sizeof(struct base_jd_atom) - */ -struct kbase_ioctl_job_submit { - __u64 addr; - __u32 nr_atoms; - __u32 stride; -}; - -#define KBASE_IOCTL_JOB_SUBMIT _IOW(KBASE_IOCTL_TYPE, 2, struct kbase_ioctl_job_submit) - -#define KBASE_IOCTL_POST_TERM _IO(KBASE_IOCTL_TYPE, 4) - -/** - * struct kbase_ioctl_soft_event_update - Update the status of a soft-event - * @event: GPU address of the event which has been updated - * @new_status: The new status to set - * @flags: Flags for future expansion - */ -struct kbase_ioctl_soft_event_update { - __u64 event; - __u32 new_status; - __u32 flags; -}; - -#define KBASE_IOCTL_SOFT_EVENT_UPDATE \ - _IOW(KBASE_IOCTL_TYPE, 28, struct kbase_ioctl_soft_event_update) - -/** - * struct kbase_kinstr_jm_fd_out - Explains the compatibility information for - * the `struct kbase_kinstr_jm_atom_state_change` structure returned from the - * kernel - * - * @size: The size of the `struct kbase_kinstr_jm_atom_state_change` - * @version: Represents a breaking change in the - * `struct kbase_kinstr_jm_atom_state_change` - * @padding: Explicit padding to get the structure up to 64bits. See - * https://www.kernel.org/doc/Documentation/ioctl/botching-up-ioctls.rst - * - * The `struct kbase_kinstr_jm_atom_state_change` may have extra members at the - * end of the structure that older user space might not understand. If the - * `version` is the same, the structure is still compatible with newer kernels. - * The `size` can be used to cast the opaque memory returned from the kernel. - */ -struct kbase_kinstr_jm_fd_out { - __u16 size; - __u8 version; - __u8 padding[5]; -}; - -/** - * struct kbase_kinstr_jm_fd_in - Options when creating the file descriptor - * - * @count: Number of atom states that can be stored in the kernel circular - * buffer. Must be a power of two - * @padding: Explicit padding to get the structure up to 64bits. See - * https://www.kernel.org/doc/Documentation/ioctl/botching-up-ioctls.rst - */ -struct kbase_kinstr_jm_fd_in { - __u16 count; - __u8 padding[6]; -}; - -union kbase_kinstr_jm_fd { - struct kbase_kinstr_jm_fd_in in; - struct kbase_kinstr_jm_fd_out out; -}; - -#define KBASE_IOCTL_KINSTR_JM_FD _IOWR(KBASE_IOCTL_TYPE, 51, union kbase_kinstr_jm_fd) - -#define KBASE_IOCTL_VERSION_CHECK_RESERVED \ - _IOWR(KBASE_IOCTL_TYPE, 52, struct kbase_ioctl_version_check) - -#endif /* _UAPI_KBASE_JM_IOCTL_H_ */ diff --git a/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h b/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h deleted file mode 100644 index 5818e01d1b31..000000000000 --- a/include/uapi/gpu/arm/valhall/jm/mali_kbase_jm_mem_flags.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2024 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -#ifndef _UAPI_KBASE_JM_MEM_FLAGS_H_ -#define _UAPI_KBASE_JM_MEM_FLAGS_H_ - -/* Memory allocation, access/hint flags & mask specific to JM GPU. - * - * See base_mem_alloc_flags. - */ - -/* Unused bit for JM, only used in CSF for BASE_MEM_FIXED */ -#define BASE_MEM_UNUSED_BIT_8 ((base_mem_alloc_flags)1 << 8) - -/* Unused bit for JM, only used in CSF for BASE_CSF_EVENT */ -#define BASE_MEM_UNUSED_BIT_19 ((base_mem_alloc_flags)1 << 19) - -/** - * BASE_MEM_TILER_ALIGN_TOP - Memory starting from the end of the initial commit is aligned - * to 'extension' pages, where 'extension' must be a power of 2 and no more than - * BASE_MEM_TILER_ALIGN_TOP_EXTENSION_MAX_PAGES - */ -#define BASE_MEM_TILER_ALIGN_TOP ((base_mem_alloc_flags)1 << 20) - -/* Previously BASEP_MEM_PERFORM_JIT_TRIM, can be reused in the future */ -#define BASE_MEM_UNUSED_BIT_29 ((base_mem_alloc_flags)1 << 29) - -/* A mask of flags that, when provided, cause other flags to be - * enabled but are not enabled themselves - */ -#define BASE_MEM_FLAGS_ACTION_MODIFIERS (BASE_MEM_COHERENT_SYSTEM_REQUIRED | BASE_MEM_IMPORT_SHARED) - -/* A mask of all currently reserved flags */ -#define BASE_MEM_FLAGS_RESERVED ((base_mem_alloc_flags)0) - -/* Number of bits used as flags for base memory management from kernel-side - * only (ie BASEP_MEM_* flags), located from 63 bit downwards: - * < 63 .. (64 - BASEP_MEM_FLAGS_NR_BITS) > - */ -#define BASEP_MEM_FLAGS_NR_BITS (6) - -/* A mask of all bits that are not used by a flag on JM */ -#define BASE_MEM_FLAGS_UNUSED \ - (BASE_MEM_UNUSED_BIT_5 | BASE_MEM_UNUSED_BIT_7 | BASE_MEM_UNUSED_BIT_8 | \ - BASE_MEM_UNUSED_BIT_19 | BASE_MEM_UNUSED_BIT_27 | BASE_MEM_UNUSED_BIT_29) - -#endif /* _UAPI_KBASE_JM_MEM_FLAGS_H_ */ diff --git a/include/uapi/gpu/arm/valhall/mali_base_common_kernel.h b/include/uapi/gpu/arm/valhall/mali_base_common_kernel.h index 66093c1689c1..ef09088b318c 100644 --- a/include/uapi/gpu/arm/valhall/mali_base_common_kernel.h +++ b/include/uapi/gpu/arm/valhall/mali_base_common_kernel.h @@ -25,12 +25,6 @@ #include #include "mali_kbase_mem_flags.h" -struct base_mem_handle { - struct { - __u64 handle; - } basep; -}; - #define BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS 4 /* Flags to pass to ::base_context_init. diff --git a/include/uapi/gpu/arm/valhall/mali_base_kernel.h b/include/uapi/gpu/arm/valhall/mali_base_kernel.h index 21e12a6f250a..2564860b0f12 100644 --- a/include/uapi/gpu/arm/valhall/mali_base_kernel.h +++ b/include/uapi/gpu/arm/valhall/mali_base_kernel.h @@ -167,26 +167,27 @@ struct base_fence { /** * struct base_mem_aliasing_info - Memory aliasing info * - * @handle: Handle to alias, can be BASE_MEM_WRITE_ALLOC_PAGES_HANDLE - * @offset: Offset within the handle to start aliasing from, in pages. - * Not used with BASE_MEM_WRITE_ALLOC_PAGES_HANDLE. - * @length: Length to alias, in pages. For BASE_MEM_WRITE_ALLOC_PAGES_HANDLE + * @gpu_va: GPU VA of an allocation to be aliased, can be a special value + * BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE + * @offset: Offset within the allocation to start aliasing from, in pages. + * Not used with BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE. + * @length: Length to alias, in pages. For BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE * specifies the number of times the special page is needed. * - * Describes a memory handle to be aliased. - * A subset of the handle can be chosen for aliasing, given an offset and a + * Describes a GPU memory allocation to be aliased. + * A subset of the allocation can be chosen for aliasing, given an offset and a * length. - * A special handle BASE_MEM_WRITE_ALLOC_PAGES_HANDLE is used to represent a + * A special value BASEP_MEM_WRITE_ALLOC_PAGES_HANDLE is used to represent a * region where a special page is mapped with a write-alloc cache setup, * typically used when the write result of the GPU isn't needed, but the GPU * must write anyway. * * Offset and length are specified in pages. - * Offset must be within the size of the handle. - * Offset+length must not overrun the size of the handle. + * Offset must be within the size of the allocation. + * Offset+length must not overrun the size of the allocation. */ struct base_mem_aliasing_info { - struct base_mem_handle handle; + __u64 gpu_va; __u64 offset; __u64 length; }; @@ -487,11 +488,7 @@ struct mali_base_gpu_coherent_group_info { struct mali_base_gpu_coherent_group group[BASE_MAX_COHERENT_GROUPS]; }; -#if MALI_USE_CSF #include "csf/mali_base_csf_kernel.h" -#else -#include "jm/mali_base_jm_kernel.h" -#endif /** * struct gpu_raw_gpu_props - A complete description of the GPU's Hardware diff --git a/include/uapi/gpu/arm/valhall/mali_base_mem_priv.h b/include/uapi/gpu/arm/valhall/mali_base_mem_priv.h index 1db3ff11d0c0..5ceda9b54b17 100644 --- a/include/uapi/gpu/arm/valhall/mali_base_mem_priv.h +++ b/include/uapi/gpu/arm/valhall/mali_base_mem_priv.h @@ -33,21 +33,21 @@ * It can either be: * @li a sync from CPU to Memory: * - type = ::BASE_SYNCSET_OP_MSYNC - * - mem_handle = a handle to the memory object on which the operation + * - gpu_va = GPU VA of GPU memory object on which the operation * is taking place * - user_addr = the address of the range to be synced * - size = the amount of data to be synced, in bytes * - offset is ignored. * @li a sync from Memory to CPU: * - type = ::BASE_SYNCSET_OP_CSYNC - * - mem_handle = a handle to the memory object on which the operation + * - gpu_va = GPU VA of GPU memory object on which the operation * is taking place * - user_addr = the address of the range to be synced * - size = the amount of data to be synced, in bytes. * - offset is ignored. */ struct basep_syncset { - struct base_mem_handle mem_handle; + __u64 gpu_va; __u64 user_addr; __u64 size; __u8 type; diff --git a/include/uapi/gpu/arm/valhall/mali_gpu_props.h b/include/uapi/gpu/arm/valhall/mali_gpu_props.h index 09ce542a76c4..5b4166017329 100644 --- a/include/uapi/gpu/arm/valhall/mali_gpu_props.h +++ b/include/uapi/gpu/arm/valhall/mali_gpu_props.h @@ -31,7 +31,9 @@ /** * struct gpu_props_user_data - structure for gpu props user buffer. * @core_props: Core props. + * @unused2: Extra space for address alignment. * @l2_props: L2 props. + * @unused4: Extra space for address alignment. * @tiler_props: Tiler props. * @thread_props: Thread props. * @raw_props: Raw register values kept for backwards compatibility. Kbase @@ -47,17 +49,21 @@ struct gpu_props_user_data { __u16 version_status; __u16 minor_revision; __u16 major_revision; + __u8 unused0[2]; __u32 gpu_freq_khz_max; __u32 log2_program_counter_size; __u32 texture_features[BASE_GPU_NUM_TEXTURE_FEATURES_REGISTERS]; + __u8 unused1[4]; __u64 gpu_available_memory_size; __u8 num_exec_engines; } core_props; + __u8 unused2[7]; struct { __u8 log2_line_size; __u8 log2_cache_size; __u8 num_l2_slices; } l2_props; + __u8 unused4[2]; struct { __u32 bin_size_bytes; __u32 max_active_levels; @@ -70,6 +76,7 @@ struct gpu_props_user_data { __u8 max_task_queue; __u8 max_thread_group_split; __u8 impl_tech; + __u8 unused5; __u32 tls_alloc; } thread_props; @@ -103,6 +110,7 @@ struct gpu_props_user_data { __u32 num_groups; __u32 num_core_groups; __u32 coherency; + __u8 unused6[4]; struct { __u64 core_mask; __u32 num_cores; diff --git a/include/uapi/gpu/arm/valhall/mali_kbase_ioctl.h b/include/uapi/gpu/arm/valhall/mali_kbase_ioctl.h index 6c3f8f127fd9..46ea47f252b6 100644 --- a/include/uapi/gpu/arm/valhall/mali_kbase_ioctl.h +++ b/include/uapi/gpu/arm/valhall/mali_kbase_ioctl.h @@ -29,11 +29,7 @@ extern "C" { #include #include -#if MALI_USE_CSF #include "csf/mali_kbase_csf_ioctl.h" -#else -#include "jm/mali_kbase_jm_ioctl.h" -#endif /* MALI_USE_CSF */ #define KBASE_IOCTL_TYPE 0x80 @@ -236,9 +232,9 @@ struct kbase_ioctl_mem_jit_init { #define KBASE_IOCTL_MEM_JIT_INIT _IOW(KBASE_IOCTL_TYPE, 14, struct kbase_ioctl_mem_jit_init) /** - * struct kbase_ioctl_mem_sync - Perform cache maintenance on memory + * struct kbase_ioctl_mem_sync - Perform CPU cache maintenance on GPU memory * - * @handle: GPU memory handle (GPU VA) + * @gpu_va: GPU VA of the memory for which cache maintenance needs to be performed. * @user_addr: The address where it is mapped in user space * @size: The number of bytes to synchronise * @type: The direction to synchronise: 0 is sync to memory (clean), @@ -246,7 +242,7 @@ struct kbase_ioctl_mem_jit_init { * @padding: Padding to round up to a multiple of 8 bytes, must be zero */ struct kbase_ioctl_mem_sync { - __u64 handle; + __u64 gpu_va; __u64 user_addr; __u64 size; __u8 type; diff --git a/include/uapi/gpu/arm/valhall/mali_kbase_kinstr_jm_reader.h b/include/uapi/gpu/arm/valhall/mali_kbase_kinstr_jm_reader.h deleted file mode 100644 index 72e1b9dbf245..000000000000 --- a/include/uapi/gpu/arm/valhall/mali_kbase_kinstr_jm_reader.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* - * - * (C) COPYRIGHT 2020-2021 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms - * of such GNU license. - * - * 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, you can access it online at - * http://www.gnu.org/licenses/gpl-2.0.html. - * - */ - -/* - * mali_kbase_kinstr_jm_reader.h - * Provides an ioctl API to read kernel atom state changes. The flow of the - * API is: - * 1. Obtain the file descriptor with ``KBASE_IOCTL_KINSTR_JM_FD`` - * 2. Determine the buffer structure layout via the above ioctl's returned - * size and version fields in ``struct kbase_kinstr_jm_fd_out`` - * 4. Poll the file descriptor for ``POLLIN`` - * 5. Get data with read() on the fd - * 6. Use the structure version to understand how to read the data from the - * buffer - * 7. Repeat 4-6 - * 8. Close the file descriptor - */ - -#ifndef _UAPI_KBASE_KINSTR_JM_READER_H_ -#define _UAPI_KBASE_KINSTR_JM_READER_H_ - -/** - * enum kbase_kinstr_jm_reader_atom_state - Determines the work state of an atom - * @KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE: Signifies that an atom has - * entered a hardware queue - * @KBASE_KINSTR_JM_READER_ATOM_STATE_START: Signifies that work has started - * on an atom - * @KBASE_KINSTR_JM_READER_ATOM_STATE_STOP: Signifies that work has stopped - * on an atom - * @KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE: Signifies that work has - * completed on an atom - * @KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT: The number of state enumerations - * - * We can add new states to the end of this if they do not break the existing - * state machine. Old user mode code can gracefully ignore states they do not - * understand. - * - * If we need to make a breaking change to the state machine, we can do that by - * changing the version reported by KBASE_IOCTL_KINSTR_JM_FD. This will - * mean that old user mode code will fail to understand the new state field in - * the structure and gracefully not use the state change API. - */ -enum kbase_kinstr_jm_reader_atom_state { - KBASE_KINSTR_JM_READER_ATOM_STATE_QUEUE, - KBASE_KINSTR_JM_READER_ATOM_STATE_START, - KBASE_KINSTR_JM_READER_ATOM_STATE_STOP, - KBASE_KINSTR_JM_READER_ATOM_STATE_COMPLETE, - KBASE_KINSTR_JM_READER_ATOM_STATE_COUNT -}; - -#endif /* _UAPI_KBASE_KINSTR_JM_READER_H_ */ diff --git a/include/uapi/gpu/arm/valhall/mali_kbase_mem_flags.h b/include/uapi/gpu/arm/valhall/mali_kbase_mem_flags.h index 465d27a014c2..04d5ca3c3d8a 100644 --- a/include/uapi/gpu/arm/valhall/mali_kbase_mem_flags.h +++ b/include/uapi/gpu/arm/valhall/mali_kbase_mem_flags.h @@ -22,11 +22,7 @@ #ifndef _UAPI_KBASE_MEM_FLAGS_H_ #define _UAPI_KBASE_MEM_FLAGS_H_ -#if MALI_USE_CSF #include "csf/mali_kbase_csf_mem_flags.h" -#else -#include "jm/mali_kbase_jm_mem_flags.h" -#endif /* Memory allocation, access/hint flags & mask. * diff --git a/include/uapi/linux/rk-aiisp-config.h b/include/uapi/linux/rk-aiisp-config.h index 54f51202a8c5..6453e62dcc3a 100644 --- a/include/uapi/linux/rk-aiisp-config.h +++ b/include/uapi/linux/rk-aiisp-config.h @@ -10,10 +10,12 @@ #include #define RKAIISP_PYRAMID_LAYER_NUM 4 +#define RKAIISP_AIYNR_LAYER_NUM 5 #define RKAIISP_MAX_RUNCNT 8 #define RKAIISP_MAX_ISPBUF 8 #define RKAIISP_MODEL_UPDATE 0x01 #define RKAIISP_OTHER_UPDATE 0x02 +#define RKAIISP_AIYNR_YBUF_NUM_MAX 8 #define RKAIISP_CMD_SET_PARAM_INFO \ _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkaiisp_param_info) @@ -30,6 +32,9 @@ #define RKAIISP_CMD_INIT_AIRMS_BUFPOOL \ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct rkaiisp_rmsbuf_info) +#define RKAIISP_CMD_GET_YNRBUF_INFO \ + _IOR('V', BASE_VIDIOC_PRIVATE + 5, struct rkaiisp_ynrbuf_info) + /**********************EVENT_PRIVATE***************************/ #define RKAIISP_V4L2_EVENT_AIISP_DONE (V4L2_EVENT_PRIVATE_START + 1) @@ -50,7 +55,8 @@ enum rkaiisp_chn_src { AIISP_LAST_OUT, VICAP_BAYER_RAW, ALLZERO_SIGMA, - ALLZERO_NARMAP + ALLZERO_NARMAP, + ISP_FINAL_Y }; enum rkaiisp_exealgo { @@ -63,7 +69,8 @@ enum rkaiisp_model_mode { SINGLE_MODE, COMBO_MODE, SINGLEX2_MODE, - REMOSAIC_MODE + REMOSAIC_MODE, + AIYNR_MODE }; enum rkaiisp_exemode { @@ -115,6 +122,13 @@ struct rkaiisp_rmsbuf_info { int outbuf_fd[6]; } __attribute__ ((packed)); +struct rkaiisp_ynrbuf_info { + int width; + int height; + __u32 buf_cnt; + int dma_fd[RKAIISP_AIYNR_YBUF_NUM_MAX]; +} __attribute__ ((packed)); + struct rkaiisp_other_cfg { __u16 sw_neg_noiselimit; __u16 sw_pos_noiselimit; diff --git a/include/uapi/linux/rk-camera-module.h b/include/uapi/linux/rk-camera-module.h index dd44f8afdfd8..75100050e3e9 100644 --- a/include/uapi/linux/rk-camera-module.h +++ b/include/uapi/linux/rk-camera-module.h @@ -12,8 +12,6 @@ #define RKMODULE_API_VERSION KERNEL_VERSION(0, 1, 0x2) -/* using for rk3588 dual isp unite */ -#define RKMOUDLE_UNITE_EXTEND_PIXEL 128 /* using for rv1109 and rv1126 */ #define RKMODULE_EXTEND_LINE 24 @@ -222,6 +220,15 @@ #define RKMODULE_GET_BAYER_MODE \ _IOR('V', BASE_VIDIOC_PRIVATE + 52, __u32) +#define RKMODULE_GET_WB_GAIN_INFO \ + _IOR('V', BASE_VIDIOC_PRIVATE + 53, struct rkmodule_wb_gain_info) + +#define RKMODULE_GET_BLC_INFO \ + _IOR('V', BASE_VIDIOC_PRIVATE + 54, struct rkmodule_blc_info) + +#define RKMODULE_SET_CMPS_MODE \ + _IOW('V', BASE_VIDIOC_PRIVATE + 55, __u32) + struct rkmodule_i2cdev_info { __u8 slave_addr; } __attribute__ ((packed)); @@ -964,4 +971,20 @@ enum rkmodule_bayer_mode { RKMODULE_QUARD_BAYER, }; +struct rkmodule_wb_gain_info { + __u32 coarse_bit; + __u32 fine_bit; + __u32 reserved[8]; +}; + +struct rkmodule_blc_info { + __u32 bit_width; + __u32 reserved[8]; +}; + +enum rkmodule_cmps_mode { + CMPS_LOW_BIT_WIDTH_MODE, + CMPS_HIGH_BIT_WIDTH_MODE, +}; + #endif /* _UAPI_RKMODULE_CAMERA_H */ diff --git a/include/uapi/linux/rk-isp2-config.h b/include/uapi/linux/rk-isp2-config.h index 295d2e9283ff..c2ab7d526f51 100644 --- a/include/uapi/linux/rk-isp2-config.h +++ b/include/uapi/linux/rk-isp2-config.h @@ -436,6 +436,9 @@ struct rkisp_aiisp_ev_info { int vpsl_index; int aiisp_index; + + int y_src_index; + int y_dest_index; } __attribute__ ((packed)); struct rkisp_aiisp_st { @@ -449,17 +452,22 @@ struct rkisp_aiisp_st { int aipre_gain_index; int vpsl_index; + + int y_src_index; + int y_dest_index; } __attribute__ ((packed)); /* struct rkisp_aiisp_cfg - * mode: 0: disable aiisp, 1:enable aiisp - * wr_linecnt: aiisp write irq line - * rd_linecnt: aiisp read irq line + * mode: 0:isp whole 1:isp divided into isp_fe and isp_be + * wr_linecnt: btnr iir write irq line + * rd_linecnt: isp_be read irq line + * wr_mode: 0:frame with only one RKISP_AIISP_WR_LINECNT_ID event, else event per wr_linecnt */ struct rkisp_aiisp_cfg { int mode; int wr_linecnt; int rd_linecnt; + int wr_mode; } __attribute__ ((packed)); #define VPSL_YRAW_CHN_MAX 6 @@ -481,6 +489,7 @@ struct rkisp_bnr_buf_info { struct rkisp_buf_info gain; struct rkisp_buf_info aipre_gain; struct rkisp_buf_info vpsl; + struct rkisp_buf_info y_src; __u8 iir_rw_fmt; __u8 gain_mode; __u8 yraw_sel; diff --git a/include/uapi/linux/rk-isp35-config.h b/include/uapi/linux/rk-isp35-config.h index e8d706617c7d..24f8d14d1bc4 100644 --- a/include/uapi/linux/rk-isp35-config.h +++ b/include/uapi/linux/rk-isp35-config.h @@ -128,8 +128,8 @@ #define ISP35_ENH_LUMA_NUM ISP33_ENH_LUMA_NUM #define ISP35_ENH_DETAIL_NUM ISP33_ENH_DETAIL_NUM -#define ISP35_ENH_IIR_ROW_MAX ISP33_ENH_IIR_ROW_MAX -#define ISP35_ENH_IIR_COL_MAX ISP33_ENH_IIR_COL_MAX +#define ISP35_ENH_IIR_ROW_MAX 24 +#define ISP35_ENH_IIR_COL_MAX 32 #define ISP35_HIST_ALPHA_NUM ISP33_HIST_ALPHA_NUM #define ISP35_HIST_THUMB_ROW_MAX ISP33_HIST_THUMB_ROW_MAX @@ -961,6 +961,45 @@ struct isp35_sharp_cfg { __u16 lo_saturation_strg; } __attribute__ ((packed)); +struct isp35_enh_cfg { + /* CTRL */ + __u8 bypass; + __u8 blf3_bypass; + /* IIR_FLT */ + __u16 iir_inv_sigma; + __u8 iir_soft_thed; + __u8 iir_cur_wgt; + /* BILAT_FLT3X3 */ + __u16 blf3_inv_sigma; + __u16 blf3_cur_wgt; + __u8 blf3_thumb_cur_wgt; + /* BILAT_FLT5X5 */ + __u8 blf5_cur_wgt; + __u16 blf5_inv_sigma; + /* GLOBAL_STRG */ + __u16 global_strg; + /* LUMA_LUT */ + __u16 lum2strg[ISP35_ENH_LUMA_NUM]; + /* DETAIL_IDX */ + __u16 detail2strg_idx[ISP35_ENH_DETAIL_NUM]; + /* DETAIL_POWER */ + __u8 detail2strg_power0; + __u8 detail2strg_power1; + __u8 detail2strg_power2; + __u8 detail2strg_power3; + __u8 detail2strg_power4; + __u8 detail2strg_power5; + __u8 detail2strg_power6; + /* DETAIL_VALUE */ + __u16 detail2strg_val[ISP35_ENH_DETAIL_NUM]; + /* PRE_FRAME */ + __u8 pre_wet_frame_cnt0; + __u8 pre_wet_frame_cnt1; + /* IIR */ + __u8 iir_wr; + __u8 iir[ISP35_ENH_IIR_ROW_MAX][ISP35_ENH_IIR_COL_MAX]; +} __attribute__ ((packed)); + struct isp35_drc_cfg { /* DRC_CTRL0 */ __u8 bypass_en; @@ -1698,7 +1737,7 @@ struct isp35_isp_other_cfg { struct isp35_cnr_cfg cnr_cfg; struct isp35_ynr_cfg ynr_cfg; struct isp35_sharp_cfg sharp_cfg; - struct isp33_enh_cfg enh_cfg; + struct isp35_enh_cfg enh_cfg; struct isp33_hist_cfg hist_cfg; struct isp32_ldch_cfg ldch_cfg; struct isp21_cgc_cfg cgc_cfg; @@ -1734,6 +1773,10 @@ struct isp35_awbsync_stat { __u64 sump[ISP35_AWBSYNC_WIN_MAX]; } __attribute__ ((packed)); +struct isp35_enh_stat { + __u8 iir[ISP35_ENH_IIR_ROW_MAX][ISP35_ENH_IIR_COL_MAX]; +} __attribute__ ((packed)); + struct isp35_stat { /* mean to ddr */ struct isp33_rawae_stat rawae3; @@ -1745,7 +1788,7 @@ struct isp35_stat { /* ahb read reg */ struct isp33_bay3d_stat bay3d; struct isp33_sharp_stat sharp; - struct isp33_enh_stat enh; + struct isp35_enh_stat enh; struct isp33_hist_stat hist; struct isp35_awbsync_stat awbsync; struct isp32_info2ddr_stat info2ddr; diff --git a/net/rfkill/rfkill-bt.c b/net/rfkill/rfkill-bt.c index 09eb1c1a15f1..471a1899e1e7 100644 --- a/net/rfkill/rfkill-bt.c +++ b/net/rfkill/rfkill-bt.c @@ -775,6 +775,7 @@ static int rfkill_rk_remove(struct platform_device *pdev) rfkill_unregister(rfkill->rfkill_dev); rfkill_destroy(rfkill->rfkill_dev); remove_proc_subtree("bluetooth/sleep", NULL); + remove_proc_entry("bluetooth", NULL); cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work); diff --git a/net/rfkill/rfkill-wlan.c b/net/rfkill/rfkill-wlan.c index aa27779c7d13..816ef7c9f099 100644 --- a/net/rfkill/rfkill-wlan.c +++ b/net/rfkill/rfkill-wlan.c @@ -798,13 +798,9 @@ static int rfkill_wlan_probe(struct platform_device *pdev) LOG("Enter %s\n", __func__); - ret = class_register(&rkwifi_power); - if (ret < 0) - return ret; - if (!pdata) { #ifdef CONFIG_OF - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; @@ -818,9 +814,9 @@ static int rfkill_wlan_probe(struct platform_device *pdev) #endif } - rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); + rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL); if (!rfkill) - goto rfkill_alloc_fail; + return -ENOMEM; rfkill->pdata = pdata; g_rfkill = rfkill; @@ -857,21 +853,11 @@ static int rfkill_wlan_probe(struct platform_device *pdev) LOG("Exit %s\n", __func__); return 0; -#ifdef COMPATIBILE_WITH_GPIO_FOR_LOWERVERSION -fail_alloc: -#endif - kfree(rfkill); -rfkill_alloc_fail: - kfree(pdata); - - g_rfkill = NULL; - - return ret; } static int rfkill_wlan_remove(struct platform_device *pdev) { - struct rfkill_wlan_data *rfkill = platform_get_drvdata(pdev); + struct rfkill_wlan_data *rfkill = g_rfkill; LOG("Enter %s\n", __func__); @@ -882,7 +868,6 @@ static int rfkill_wlan_remove(struct platform_device *pdev) #if defined(CONFIG_HAS_EARLYSUSPEND) unregister_early_suspend(&wlan_early_suspend_handler); #endif - kfree(rfkill); g_rfkill = NULL; return 0; @@ -920,24 +905,33 @@ static struct platform_driver rfkill_wlan_driver = { .probe = rfkill_wlan_probe, .remove = rfkill_wlan_remove, .shutdown = rfkill_wlan_shutdown, - .suspend = rfkill_wlan_suspend, - .resume = rfkill_wlan_resume, + .suspend = rfkill_wlan_suspend, + .resume = rfkill_wlan_resume, .driver = { .name = "wlan-platdata", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(wlan_platdata_of_match), + .of_match_table = of_match_ptr(wlan_platdata_of_match), }, }; int __init rfkill_wlan_init(void) { + int ret; + LOG("Enter %s\n", __func__); + + ret = class_register(&rkwifi_power); + if (ret < 0) + return ret; + return platform_driver_register(&rfkill_wlan_driver); } void __exit rfkill_wlan_exit(void) { LOG("Enter %s\n", __func__); + + class_unregister(&rkwifi_power); platform_driver_unregister(&rfkill_wlan_driver); }